Commit fceedda5 by Sebastian Henke Committed by Patrick Steinhardt

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.
parent 5aca2444
...@@ -339,7 +339,13 @@ int git_transaction_commit(git_transaction *tx) ...@@ -339,7 +339,13 @@ int git_transaction_commit(git_transaction *tx)
return error; 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) if ((error = update_target(tx->db, node)) < 0)
return error; return error;
} }
......
...@@ -129,3 +129,29 @@ void test_refs_transactions__error_on_locking_locked_ref(void) ...@@ -129,3 +129,29 @@ void test_refs_transactions__error_on_locking_locked_ref(void)
git_transaction_free(g_tx_with_lock); git_transaction_free(g_tx_with_lock);
git_repository_free(g_repo_with_locking_tx); 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"));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment