Re [bug] pull --prune could not delete references due to lock file already exists error
First off thanks for reporting the bug :) So I cannot test this bug as my files system is case sensitive but to just read the code and give a thought in a direction (Assuming that the bug is recreatable)
int refs_delete_refs(struct ref_store *refs, const char *logmsg,
struct string_list *refnames, unsigned int flags)
{
...
struct ref_transaction *transaction;
...
for_each_string_list_item(item, refnames) { transaction = ref_store_transaction_begin(refs, 0, &err);
if (!transaction) {
warning(_("could not begin transaction to delete %s: %s"),
item->string, err.buf);
strbuf_reset(&err);
failures = 1;
continue;
} ret = ref_transaction_delete(transaction, item->string,
NULL, NULL, flags, msg, &err);
if (ret) {
warning(_("could not delete reference %s: %s"),
item->string, err.buf);
strbuf_reset(&err);
ref_transaction_free(transaction);
failures = 1;
continue;
} ret = ref_transaction_commit(transaction, &err);
if (ret) {
warning(_("could not commit deletion of %s: %s"),
item->string, err.buf);
strbuf_reset(&err);
failures = 1;
} ref_transaction_free(transaction);
}
if (failures)
ret = -1;
strbuf_release(&err);
free(msg);
return ret;
}
The original implementation: Starts a single transaction using ref_store_transaction_begin(). Adds all deletions to that transaction. Commits the transaction. If any deletion fails, the entire transaction is aborted. On case-insensitive file systems, two refs like: may conflict at the file system level (e.g. both mapped to the same file or directory). If Git tries to delete both in one go, the transaction fails due to a lock file or unlink error. (Above are my assumptions till now).
What has changed is: Deletes each reference in its own transaction struct ref_transaction *transaction = ref_store_transaction_begin(...); ref_transaction_delete(transaction, ...); ref_transaction_commit(transaction, ...); ref_transaction_free(transaction); If one deletion fails due to a case conflict, the others still proceed. It avoids rolling back the entire prune operation just because of a single failure. Keeps failure count and returns appropriately Signals that something went wrong, but Git can now give partial success feedback.
The question I have is If this approach seems viable or perhaps any solution, would it be possible to write a test case for this scenario?
Thank you
- Jayatheerth