diff options
author | Sebastian Henke <s.henke@henke-informatik.de> | 2019-10-11 12:44:09 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2020-03-26 16:20:18 +0100 |
commit | fceedda5dc212d9653992ce623f18b6869944919 (patch) | |
tree | d3f4a830286f11fa83d46f9080ea7814ac354718 | |
parent | 5aca2444e670df0d32925a8f0c97866ac121d618 (diff) | |
download | libgit2-fceedda5dc212d9653992ce623f18b6869944919.tar.gz |
refs: unlock unmodified refs on transaction commit
Refs which are locked in a transaction without an altered target,
still should to be unlocked on `git_transaction_commit`.
`git_transaction_free` also unlocks refs but the moment of calling of `git_transaction_free`
cannot be controlled in all situations.
Some binding libs call `git_transaction_free` on garbage collection or not at all if the
application exits before and don't provide public access to `git_transaction_free`.
It is better to release locks as soon as possible.
-rw-r--r-- | src/transaction.c | 8 | ||||
-rw-r--r-- | tests/refs/transactions.c | 26 |
2 files changed, 33 insertions, 1 deletions
diff --git a/src/transaction.c b/src/transaction.c index d8e38d803..b7a8b6301 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -339,7 +339,13 @@ int git_transaction_commit(git_transaction *tx) return error; } - if (node->ref_type != GIT_REFERENCE_INVALID) { + if (node->ref_type == GIT_REFERENCE_INVALID) { + /* ref was locked but not modified */ + if ((error = git_refdb_unlock(tx->db, node->payload, false, false, NULL, NULL, NULL)) < 0) { + return error; + } + node->committed = true; + } else { if ((error = update_target(tx->db, node)) < 0) return error; } diff --git a/tests/refs/transactions.c b/tests/refs/transactions.c index d4ddf459f..50c102ad0 100644 --- a/tests/refs/transactions.c +++ b/tests/refs/transactions.c @@ -129,3 +129,29 @@ void test_refs_transactions__error_on_locking_locked_ref(void) git_transaction_free(g_tx_with_lock); git_repository_free(g_repo_with_locking_tx); } + +void test_refs_transactions__commit_unlocks_unmodified_ref(void) +{ + git_transaction *second_tx; + + cl_git_pass(git_transaction_new(&second_tx, g_repo)); + cl_git_pass(git_transaction_lock_ref(second_tx, "refs/heads/master")); + cl_git_pass(git_transaction_commit(second_tx)); + + /* a transaction must now be able to get the lock */ + cl_git_pass(git_transaction_lock_ref(g_tx, "refs/heads/master")); + + git_transaction_free(second_tx); +} + +void test_refs_transactions__free_unlocks_unmodified_ref(void) +{ + git_transaction *second_tx; + + cl_git_pass(git_transaction_new(&second_tx, g_repo)); + cl_git_pass(git_transaction_lock_ref(second_tx, "refs/heads/master")); + git_transaction_free(second_tx); + + /* a transaction must now be able to get the lock */ + cl_git_pass(git_transaction_lock_ref(g_tx, "refs/heads/master")); +} |