Skip to content

Commit 7bfa5bd

Browse files
committed
git_config_set_multivar_in_file_gently(): add a lock timeout
In particular when multiple processes want to write to the config simultaneously, it would come in handy to not fail immediately when another process locked the config, but to gently try again. This will help with Scalar's functional test suite which wants to register multiple repositories for maintenance semi-simultaneously. As not all code paths calling this function read the config (e.g. `git config`), we have to read the config setting via `git_config_get_ulong()`. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 3b87459 commit 7bfa5bd

File tree

2 files changed

+16
-1
lines changed

2 files changed

+16
-1
lines changed

Documentation/config/core.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,3 +755,12 @@ core.WSLCompat::
755755
The default value is false. When set to true, Git will set the mode
756756
bits of the file in the way of wsl, so that the executable flag of
757757
files can be set or read correctly.
758+
759+
core.configWriteLockTimeoutMS::
760+
When processes try to write to the config concurrently, it is likely
761+
that one process "wins" and the other process(es) fail to lock the
762+
config file. By configuring a timeout larger than zero, Git can be
763+
told to try to lock the config again a couple times within the
764+
specified timeout. If the timeout is configure to zero (which is the
765+
default), Git will fail immediately when the config is already
766+
locked.

config.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3324,6 +3324,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
33243324
const char *value_pattern,
33253325
unsigned flags)
33263326
{
3327+
static unsigned long timeout_ms = ULONG_MAX;
33273328
int fd = -1, in_fd = -1;
33283329
int ret;
33293330
struct lock_file lock = LOCK_INIT;
@@ -3342,11 +3343,16 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
33423343
if (!config_filename)
33433344
config_filename = filename_buf = git_pathdup("config");
33443345

3346+
if ((long)timeout_ms < 0 &&
3347+
git_config_get_ulong("core.configWriteLockTimeoutMS", &timeout_ms))
3348+
timeout_ms = 0;
3349+
33453350
/*
33463351
* The lock serves a purpose in addition to locking: the new
33473352
* contents of .git/config will be written into it.
33483353
*/
3349-
fd = hold_lock_file_for_update(&lock, config_filename, 0);
3354+
fd = hold_lock_file_for_update_timeout(&lock, config_filename, 0,
3355+
timeout_ms);
33503356
if (fd < 0) {
33513357
error_errno(_("could not lock config file %s"), config_filename);
33523358
ret = CONFIG_NO_LOCK;

0 commit comments

Comments
 (0)