files_transaction_commit(): clean up empty directories
When deleting/pruning references, remove any directories that are made empty by the deletion of loose references or of reflogs. Otherwise such empty directories can survive forever and accumulate over time. (Even 'pack-refs', which is smart enough to remove the parent directories of loose references that it prunes, leaves directories that were already empty.) And now that files_transaction_commit() takes care of deleting the parent directories of loose references that it prunes, we don't have to do that in prune_ref() anymore. This change would be unwise if the *creation* of these directories could race with our deletion of them. But the earlier changes in this patch series made the creation paths robust against races, so now it is safe to tidy them up more aggressively. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
a8f0db2d99
commit
446397774a
@ -2346,7 +2346,6 @@ static void prune_ref(struct ref_to_prune *r)
|
||||
}
|
||||
ref_transaction_free(transaction);
|
||||
strbuf_release(&err);
|
||||
try_remove_empty_parents(r->name, REMOVE_EMPTY_PARENTS_REF);
|
||||
}
|
||||
|
||||
static void prune_refs(struct ref_to_prune *r)
|
||||
@ -3794,6 +3793,7 @@ static int files_transaction_commit(struct ref_store *ref_store,
|
||||
ret = TRANSACTION_GENERIC_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
update->flags |= REF_DELETED_LOOSE;
|
||||
}
|
||||
|
||||
if (!(update->flags & REF_ISPRUNING))
|
||||
@ -3806,16 +3806,38 @@ static int files_transaction_commit(struct ref_store *ref_store,
|
||||
ret = TRANSACTION_GENERIC_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
for_each_string_list_item(ref_to_delete, &refs_to_delete)
|
||||
unlink_or_warn(git_path("logs/%s", ref_to_delete->string));
|
||||
|
||||
/* Delete the reflogs of any references that were deleted: */
|
||||
for_each_string_list_item(ref_to_delete, &refs_to_delete) {
|
||||
if (!unlink_or_warn(git_path("logs/%s", ref_to_delete->string)))
|
||||
try_remove_empty_parents(ref_to_delete->string,
|
||||
REMOVE_EMPTY_PARENTS_REFLOG);
|
||||
}
|
||||
|
||||
clear_loose_ref_cache(refs);
|
||||
|
||||
cleanup:
|
||||
transaction->state = REF_TRANSACTION_CLOSED;
|
||||
|
||||
for (i = 0; i < transaction->nr; i++)
|
||||
if (transaction->updates[i]->backend_data)
|
||||
unlock_ref(transaction->updates[i]->backend_data);
|
||||
for (i = 0; i < transaction->nr; i++) {
|
||||
struct ref_update *update = transaction->updates[i];
|
||||
struct ref_lock *lock = update->backend_data;
|
||||
|
||||
if (lock)
|
||||
unlock_ref(lock);
|
||||
|
||||
if (update->flags & REF_DELETED_LOOSE) {
|
||||
/*
|
||||
* The loose reference was deleted. Delete any
|
||||
* empty parent directories. (Note that this
|
||||
* can only work because we have already
|
||||
* removed the lockfile.)
|
||||
*/
|
||||
try_remove_empty_parents(update->refname,
|
||||
REMOVE_EMPTY_PARENTS_REF);
|
||||
}
|
||||
}
|
||||
|
||||
string_list_clear(&refs_to_delete, 0);
|
||||
free(head_ref);
|
||||
string_list_clear(&affected_refnames, 0);
|
||||
|
Reference in New Issue
Block a user