Re [bug] pull --prune could not delete references due to lock file already exists error

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux