Skip to content

Commit 4cc51db

Browse files
committed
Merge branch 'scalar-gentler-config-locking'
Allow concurrent `scalar register` and `scalar unregister` calls to be more collaborative when trying to lock the global Git config at the very same time. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2 parents bac2805 + f298444 commit 4cc51db

File tree

3 files changed

+26
-1
lines changed

3 files changed

+26
-1
lines changed

Documentation/config/core.adoc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,3 +795,12 @@ core.WSLCompat::
795795
The default value is false. When set to true, Git will set the mode
796796
bits of the file in the way of wsl, so that the executable flag of
797797
files can be set or read correctly.
798+
799+
core.configWriteLockTimeoutMS::
800+
When processes try to write to the config concurrently, it is likely
801+
that one process "wins" and the other process(es) fail to lock the
802+
config file. By configuring a timeout larger than zero, Git can be
803+
told to try to lock the config again a couple times within the
804+
specified timeout. If the timeout is configure to zero (which is the
805+
default), Git will fail immediately when the config is already
806+
locked.

config.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2953,6 +2953,7 @@ int repo_config_set_multivar_in_file_gently(struct repository *r,
29532953
const char *comment,
29542954
unsigned flags)
29552955
{
2956+
static unsigned long timeout_ms = ULONG_MAX;
29562957
int fd = -1, in_fd = -1;
29572958
int ret;
29582959
struct lock_file lock = LOCK_INIT;
@@ -2981,11 +2982,16 @@ int repo_config_set_multivar_in_file_gently(struct repository *r,
29812982
if (!config_filename)
29822983
config_filename = filename_buf = repo_git_path(r, "config");
29832984

2985+
if ((long)timeout_ms < 0 &&
2986+
repo_config_get_ulong(r, "core.configWriteLockTimeoutMS", &timeout_ms))
2987+
timeout_ms = 0;
2988+
29842989
/*
29852990
* The lock serves a purpose in addition to locking: the new
29862991
* contents of .git/config will be written into it.
29872992
*/
2988-
fd = hold_lock_file_for_update(&lock, config_filename, 0);
2993+
fd = hold_lock_file_for_update_timeout(&lock, config_filename, 0,
2994+
timeout_ms);
29892995
if (fd < 0) {
29902996
error_errno(_("could not lock config file %s"), config_filename);
29912997
ret = CONFIG_NO_LOCK;

scalar.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ static int set_recommended_config(int reconfigure)
172172
{ "core.safeCRLF", "false" },
173173
{ "fetch.showForcedUpdates", "false" },
174174
{ "pack.usePathWalk", "true" },
175+
{ "core.configWriteLockTimeoutMS", "150" },
175176
{ NULL, NULL },
176177
};
177178
int i;
@@ -219,6 +220,11 @@ static int set_recommended_config(int reconfigure)
219220
*/
220221
static int toggle_maintenance(int enable)
221222
{
223+
unsigned long ul;
224+
225+
if (repo_config_get_ulong(the_repository, "core.configWriteLockTimeoutMS", &ul))
226+
git_config_push_parameter("core.configWriteLockTimeoutMS=150");
227+
222228
return run_git("maintenance",
223229
enable ? "start" : "unregister",
224230
enable ? NULL : "--force",
@@ -228,10 +234,14 @@ static int toggle_maintenance(int enable)
228234
static int add_or_remove_enlistment(int add)
229235
{
230236
int res;
237+
unsigned long ul;
231238

232239
if (!the_repository->worktree)
233240
die(_("Scalar enlistments require a worktree"));
234241

242+
if (repo_config_get_ulong(the_repository, "core.configWriteLockTimeoutMS", &ul))
243+
git_config_push_parameter("core.configWriteLockTimeoutMS=150");
244+
235245
res = run_git("config", "--global", "--get", "--fixed-value",
236246
"scalar.repo", the_repository->worktree, NULL);
237247

0 commit comments

Comments
 (0)