Browse Source

sparse-checkout: write using lockfile

If two 'git sparse-checkout set' subcommands are launched at the
same time, the behavior can be unexpected as they compete to write
the sparse-checkout file and update the working directory.

Take a lockfile around the writes to the sparse-checkout file. In
addition, acquire this lock around the working directory update
to avoid two commands updating the working directory in different
ways.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Derrick Stolee 5 years ago committed by Junio C Hamano
parent
commit
fb10ca5b54
  1. 15
      builtin/sparse-checkout.c
  2. 7
      t/t1091-sparse-checkout-builtin.sh

15
builtin/sparse-checkout.c

@ -170,25 +170,32 @@ static int write_patterns_and_update(struct pattern_list *pl) @@ -170,25 +170,32 @@ static int write_patterns_and_update(struct pattern_list *pl)
{
char *sparse_filename;
FILE *fp;
int fd;
struct lock_file lk = LOCK_INIT;
int result;

result = update_working_directory(pl);
sparse_filename = get_sparse_checkout_filename();
fd = hold_lock_file_for_update(&lk, sparse_filename,
LOCK_DIE_ON_ERROR);

result = update_working_directory(pl);
if (result) {
rollback_lock_file(&lk);
free(sparse_filename);
clear_pattern_list(pl);
update_working_directory(NULL);
return result;
}

sparse_filename = get_sparse_checkout_filename();
fp = fopen(sparse_filename, "w");
fp = xfdopen(fd, "w");

if (core_sparse_checkout_cone)
write_cone_to_file(fp, pl);
else
write_patterns_to_file(fp, pl);

fclose(fp);
fflush(fp);
commit_lock_file(&lk);

free(sparse_filename);
clear_pattern_list(pl);

7
t/t1091-sparse-checkout-builtin.sh

@ -277,4 +277,11 @@ test_expect_success 'revert to old sparse-checkout on empty update' ' @@ -277,4 +277,11 @@ test_expect_success 'revert to old sparse-checkout on empty update' '
)
'

test_expect_success 'fail when lock is taken' '
test_when_finished rm -rf repo/.git/info/sparse-checkout.lock &&
touch repo/.git/info/sparse-checkout.lock &&
test_must_fail git -C repo sparse-checkout set deep 2>err &&
test_i18ngrep "File exists" err
'

test_done

Loading…
Cancel
Save