delete_refs(): bail early if the packed-refs file cannot be rewritten

If we fail to delete the doomed references from the packed-refs file,
then it is unsafe to delete their loose references, because doing so
might expose a value from the packed-refs file that is obsolete and
perhaps even points at an object that has been garbage collected.

So if repack_without_refs() fails, emit a more explicit error message
and bail.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Michael Haggerty 2015-06-22 16:02:57 +02:00 коммит произвёл Junio C Hamano
Родитель 5d97861b9b
Коммит 7fa7dc8904
1 изменённых файлов: 22 добавлений и 3 удалений

25
refs.c
Просмотреть файл

@ -2835,9 +2835,26 @@ int delete_refs(struct string_list *refnames)
struct strbuf err = STRBUF_INIT;
int i, result = 0;
if (repack_without_refs(refnames, &err))
result |= error("%s", err.buf);
strbuf_release(&err);
if (!refnames->nr)
return 0;
result = repack_without_refs(refnames, &err);
if (result) {
/*
* If we failed to rewrite the packed-refs file, then
* it is unsafe to try to remove loose refs, because
* doing so might expose an obsolete packed value for
* a reference that might even point at an object that
* has been garbage collected.
*/
if (refnames->nr == 1)
error(_("could not delete reference %s: %s"),
refnames->items[0].string, err.buf);
else
error(_("could not delete references: %s"), err.buf);
goto out;
}
for (i = 0; i < refnames->nr; i++) {
const char *refname = refnames->items[i].string;
@ -2846,6 +2863,8 @@ int delete_refs(struct string_list *refnames)
result |= error(_("could not remove reference %s"), refname);
}
out:
strbuf_release(&err);
return result;
}