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@xxxxxxxxxxxx> --- refs.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/refs.c b/refs.c index 5386077..19afc4d 100644 --- a/refs.c +++ b/refs.c @@ -2823,9 +2823,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; @@ -2834,6 +2851,8 @@ int delete_refs(struct string_list *refnames) result |= error(_("could not remove reference %s"), refname); } +out: + strbuf_release(&err); return result; } -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe git" in