Skip to content

Commit 4941087

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 <[email protected]>
2 parents d79cbdd + 550ef67 commit 4941087

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
@@ -776,3 +776,12 @@ core.WSLCompat::
776776
The default value is false. When set to true, Git will set the mode
777777
bits of the file in the way of wsl, so that the executable flag of
778778
files can be set or read correctly.
779+
780+
core.configWriteLockTimeoutMS::
781+
When processes try to write to the config concurrently, it is likely
782+
that one process "wins" and the other process(es) fail to lock the
783+
config file. By configuring a timeout larger than zero, Git can be
784+
told to try to lock the config again a couple times within the
785+
specified timeout. If the timeout is configure to zero (which is the
786+
default), Git will fail immediately when the config is already
787+
locked.

config.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2660,6 +2660,7 @@ int repo_config_set_multivar_in_file_gently(struct repository *r,
26602660
const char *comment,
26612661
unsigned flags)
26622662
{
2663+
static unsigned long timeout_ms = ULONG_MAX;
26632664
int fd = -1, in_fd = -1;
26642665
int ret;
26652666
struct lock_file lock = LOCK_INIT;
@@ -2680,11 +2681,16 @@ int repo_config_set_multivar_in_file_gently(struct repository *r,
26802681
if (!config_filename)
26812682
config_filename = filename_buf = repo_git_path(r, "config");
26822683

2684+
if ((long)timeout_ms < 0 &&
2685+
repo_config_get_ulong(r, "core.configWriteLockTimeoutMS", &timeout_ms))
2686+
timeout_ms = 0;
2687+
26832688
/*
26842689
* The lock serves a purpose in addition to locking: the new
26852690
* contents of .git/config will be written into it.
26862691
*/
2687-
fd = hold_lock_file_for_update(&lock, config_filename, 0);
2692+
fd = hold_lock_file_for_update_timeout(&lock, config_filename, 0,
2693+
timeout_ms);
26882694
if (fd < 0) {
26892695
error_errno(_("could not lock config file %s"), config_filename);
26902696
ret = CONFIG_NO_LOCK;

scalar.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ static int set_recommended_config(int reconfigure)
171171
{ "core.safeCRLF", "false" },
172172
{ "fetch.showForcedUpdates", "false" },
173173
{ "pack.usePathWalk", "true" },
174+
{ "core.configWriteLockTimeoutMS", "150" },
174175
{ NULL, NULL },
175176
};
176177
int i;
@@ -218,6 +219,11 @@ static int set_recommended_config(int reconfigure)
218219
*/
219220
static int toggle_maintenance(int enable)
220221
{
222+
unsigned long ul;
223+
224+
if (repo_config_get_ulong(the_repository, "core.configWriteLockTimeoutMS", &ul))
225+
git_config_push_parameter("core.configWriteLockTimeoutMS=150");
226+
221227
return run_git("maintenance",
222228
enable ? "start" : "unregister",
223229
enable ? NULL : "--force",
@@ -227,10 +233,14 @@ static int toggle_maintenance(int enable)
227233
static int add_or_remove_enlistment(int add)
228234
{
229235
int res;
236+
unsigned long ul;
230237

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

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

0 commit comments

Comments
 (0)