if (!refnames->nr)
return 0;
- result = repack_without_refs(refs->packed_ref_store, 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);
+ if (packed_refs_lock(refs->packed_ref_store, 0, &err))
+ goto error;
- goto out;
+ if (repack_without_refs(refs->packed_ref_store, refnames, &err)) {
+ packed_refs_unlock(refs->packed_ref_store);
+ goto error;
}
+ packed_refs_unlock(refs->packed_ref_store);
+
for (i = 0; i < refnames->nr; i++) {
const char *refname = refnames->items[i].string;
result |= error(_("could not remove reference %s"), refname);
}
-out:
strbuf_release(&err);
return result;
+
+error:
+ /*
+ * 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);
+
+ strbuf_release(&err);
+ return -1;
}
/*
}
}
+ if (packed_refs_lock(refs->packed_ref_store, 0, err)) {
+ ret = TRANSACTION_GENERIC_ERROR;
+ goto cleanup;
+ }
+
if (repack_without_refs(refs->packed_ref_store, &refs_to_delete, err)) {
ret = TRANSACTION_GENERIC_ERROR;
+ packed_refs_unlock(refs->packed_ref_store);
goto cleanup;
}
+ packed_refs_unlock(refs->packed_ref_store);
+
/* Delete the reflogs of any references that were deleted: */
for_each_string_list_item(ref_to_delete, &refs_to_delete) {
strbuf_reset(&sb);
return -1;
}
-/*
- * Rollback the lockfile for the packed-refs file, and discard the
- * in-memory packed reference cache. (The packed-refs file will be
- * read anew if it is needed again after this function is called.)
- */
-static void rollback_packed_refs(struct packed_ref_store *refs)
-{
- packed_assert_main_repository(refs, "rollback_packed_refs");
-
- if (!is_lock_file_locked(&refs->lock))
- die("BUG: packed-refs not locked");
- packed_refs_unlock(&refs->base);
- clear_packed_ref_cache(refs);
-}
-
/*
* Rewrite the packed-refs file, omitting any refs listed in
* 'refnames'. On error, leave packed-refs unchanged, write an error
- * message to 'err', and return a nonzero value.
+ * message to 'err', and return a nonzero value. The packed refs lock
+ * must be held when calling this function; it will still be held when
+ * the function returns.
*
* The refs in 'refnames' needn't be sorted. `err` must not be NULL.
*/
struct ref_dir *packed;
struct string_list_item *refname;
int needs_repacking = 0, removed = 0;
- int ret;
packed_assert_main_repository(refs, "repack_without_refs");
assert(err);
+ if (!is_lock_file_locked(&refs->lock))
+ die("BUG: repack_without_refs called without holding lock");
+
/* Look for a packed ref */
for_each_string_list_item(refname, refnames) {
if (get_packed_ref(refs, refname->string)) {
if (!needs_repacking)
return 0; /* no refname exists in packed refs */
- if (packed_refs_lock(&refs->base, 0, err))
- return -1;
-
packed = get_packed_refs(refs);
/* Remove refnames from the cache */
* All packed entries disappeared while we were
* acquiring the lock.
*/
- rollback_packed_refs(refs);
+ clear_packed_ref_cache(refs);
return 0;
}
/* Write what remains */
- ret = commit_packed_refs(&refs->base, err);
- packed_refs_unlock(ref_store);
- return ret;
+ return commit_packed_refs(&refs->base, err);
}
static int packed_init_db(struct ref_store *ref_store, struct strbuf *err)