Skip to content

Commit 20fe798

Browse files
committed
Merge branch 'ms/worktree-add-atomic-mkdir'
"git worktree add" used to do a "find an available name with stat and then mkdir", which is race-prone. This has been fixed by using mkdir and reacting to EEXIST in a loop. * ms/worktree-add-atomic-mkdir: worktree: fix worktree add race
2 parents 31df2c1 + 7af01f2 commit 20fe798

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

builtin/worktree.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,10 @@ static int add_worktree(const char *path, const char *refname,
268268
struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;
269269
struct strbuf sb = STRBUF_INIT;
270270
const char *name;
271-
struct stat st;
272271
struct child_process cp = CHILD_PROCESS_INIT;
273272
struct argv_array child_env = ARGV_ARRAY_INIT;
274-
int counter = 0, len, ret;
273+
unsigned int counter = 0;
274+
int len, ret;
275275
struct strbuf symref = STRBUF_INIT;
276276
struct commit *commit = NULL;
277277
int is_branch = 0;
@@ -295,8 +295,12 @@ static int add_worktree(const char *path, const char *refname,
295295
if (safe_create_leading_directories_const(sb_repo.buf))
296296
die_errno(_("could not create leading directories of '%s'"),
297297
sb_repo.buf);
298-
while (!stat(sb_repo.buf, &st)) {
298+
299+
while (mkdir(sb_repo.buf, 0777)) {
299300
counter++;
301+
if ((errno != EEXIST) || !counter /* overflow */)
302+
die_errno(_("could not create directory of '%s'"),
303+
sb_repo.buf);
300304
strbuf_setlen(&sb_repo, len);
301305
strbuf_addf(&sb_repo, "%d", counter);
302306
}
@@ -306,8 +310,6 @@ static int add_worktree(const char *path, const char *refname,
306310
atexit(remove_junk);
307311
sigchain_push_common(remove_junk_on_signal);
308312

309-
if (mkdir(sb_repo.buf, 0777))
310-
die_errno(_("could not create directory of '%s'"), sb_repo.buf);
311313
junk_git_dir = xstrdup(sb_repo.buf);
312314
is_junk = 1;
313315

0 commit comments

Comments
 (0)