aboutsummaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/refs.c b/refs.c
index d884f7d78..002daebf6 100644
--- a/refs.c
+++ b/refs.c
@@ -1902,8 +1902,41 @@ static int repack_without_ref_fn(struct ref_entry *entry, void *cb_data)
if (!strcmp(data->refname, entry->name))
return 0;
- if (!ref_resolves_to_object(entry))
- return 0; /* Skip broken refs */
+ if (entry->flag & REF_ISBROKEN) {
+ /* This shouldn't happen to packed refs. */
+ error("%s is broken!", entry->name);
+ return 0;
+ }
+ if (!has_sha1_file(entry->u.value.sha1)) {
+ unsigned char sha1[20];
+ int flags;
+
+ if (read_ref_full(entry->name, sha1, 0, &flags))
+ /* We should at least have found the packed ref. */
+ die("Internal error");
+ if ((flags & REF_ISSYMREF) || !(flags & REF_ISPACKED))
+ /*
+ * This packed reference is overridden by a
+ * loose reference, so it is OK that its value
+ * is no longer valid; for example, it might
+ * refer to an object that has been garbage
+ * collected. For this purpose we don't even
+ * care whether the loose reference itself is
+ * invalid, broken, symbolic, etc. Silently
+ * omit the packed reference from the output.
+ */
+ return 0;
+ /*
+ * There is no overriding loose reference, so the fact
+ * that this reference doesn't refer to a valid object
+ * indicates some kind of repository corruption.
+ * Report the problem, then omit the reference from
+ * the output.
+ */
+ error("%s does not point to a valid object!", entry->name);
+ return 0;
+ }
+
len = snprintf(line, sizeof(line), "%s %s\n",
sha1_to_hex(entry->u.value.sha1), entry->name);
/* this should not happen but just being defensive */