Git fork

Merge branch 'jk/refs-double-abort'

A corner case bug in the refs API has been corrected.

* jk/refs-double-abort:
refs/files-backend: don't look at an aborted transaction
refs/files-backend: handle packed transaction prepare failure

+31 -1
+15 -1
refs/files-backend.c
··· 2701 2701 if (is_packed_transaction_needed(refs->packed_ref_store, 2702 2702 packed_transaction)) { 2703 2703 ret = ref_transaction_prepare(packed_transaction, err); 2704 + /* 2705 + * A failure during the prepare step will abort 2706 + * itself, but not free. Do that now, and disconnect 2707 + * from the files_transaction so it does not try to 2708 + * abort us when we hit the cleanup code below. 2709 + */ 2710 + if (ret) { 2711 + ref_transaction_free(packed_transaction); 2712 + backend_data->packed_transaction = NULL; 2713 + } 2704 2714 } else { 2705 2715 /* 2706 2716 * We can skip rewriting the `packed-refs` 2707 2717 * file. But we do need to leave it locked, so 2708 2718 * that somebody else doesn't pack a reference 2709 2719 * that we are trying to delete. 2720 + * 2721 + * We need to disconnect our transaction from 2722 + * backend_data, since the abort (whether successful or 2723 + * not) will free it. 2710 2724 */ 2725 + backend_data->packed_transaction = NULL; 2711 2726 if (ref_transaction_abort(packed_transaction, err)) { 2712 2727 ret = TRANSACTION_GENERIC_ERROR; 2713 2728 goto cleanup; 2714 2729 } 2715 - backend_data->packed_transaction = NULL; 2716 2730 } 2717 2731 } 2718 2732
+16
t/t1404-update-ref-errors.sh
··· 618 618 test_cmp unchanged actual 619 619 ' 620 620 621 + test_expect_success 'delete fails cleanly if packed-refs.new write fails' ' 622 + # Setup and expectations are similar to the test above. 623 + prefix=refs/failed-packed-refs && 624 + git update-ref $prefix/foo $C && 625 + git pack-refs --all && 626 + git update-ref $prefix/foo $D && 627 + git for-each-ref $prefix >unchanged && 628 + # This should not happen in practice, but it is an easy way to get a 629 + # reliable error (we open with create_tempfile(), which uses O_EXCL). 630 + : >.git/packed-refs.new && 631 + test_when_finished "rm -f .git/packed-refs.new" && 632 + test_must_fail git update-ref -d $prefix/foo && 633 + git for-each-ref $prefix >actual && 634 + test_cmp unchanged actual 635 + ' 636 + 621 637 test_done