summaryrefslogtreecommitdiff
path: root/builtin/index-pack.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2025-05-12 14:22:49 -0700
committerJunio C Hamano <gitster@pobox.com>2025-05-12 14:22:49 -0700
commit6dbc41631d1ee65e1c12be7e3844e671b6bc44ea (patch)
tree2db2c90aa3b38f58aecc86238a92aa67348352a5 /builtin/index-pack.c
parenta9d67d67e3fe0d3a31470f1f425549a2ebb4b4e0 (diff)
parent98f8854c948340e77532a3fe6978c005cf8f05e3 (diff)
Merge branch 'ds/fix-thin-fix'
"git index-pack --fix-thin" used to abort to prevent a cycle in delta chains from forming in a corner case even when there is no such cycle. * ds/fix-thin-fix: index-pack: allow revisiting REF_DELTA chains t5309: create failing test for 'git index-pack' test-tool: add pack-deltas helper
Diffstat (limited to 'builtin/index-pack.c')
-rw-r--r--builtin/index-pack.c58
1 files changed, 32 insertions, 26 deletions
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 147e9b8b47..bb7925bd29 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1108,8 +1108,8 @@ static void *threaded_second_pass(void *data)
set_thread_data(data);
for (;;) {
struct base_data *parent = NULL;
- struct object_entry *child_obj;
- struct base_data *child;
+ struct object_entry *child_obj = NULL;
+ struct base_data *child = NULL;
counter_lock();
display_progress(progress, nr_resolved_deltas);
@@ -1136,15 +1136,18 @@ static void *threaded_second_pass(void *data)
parent = list_first_entry(&work_head, struct base_data,
list);
- if (parent->ref_first <= parent->ref_last) {
+ while (parent->ref_first <= parent->ref_last) {
int offset = ref_deltas[parent->ref_first++].obj_no;
child_obj = objects + offset;
- if (child_obj->real_type != OBJ_REF_DELTA)
- die("REF_DELTA at offset %"PRIuMAX" already resolved (duplicate base %s?)",
- (uintmax_t) child_obj->idx.offset,
- oid_to_hex(&parent->obj->idx.oid));
+ if (child_obj->real_type != OBJ_REF_DELTA) {
+ child_obj = NULL;
+ continue;
+ }
child_obj->real_type = parent->obj->real_type;
- } else {
+ break;
+ }
+
+ if (!child_obj && parent->ofs_first <= parent->ofs_last) {
child_obj = objects +
ofs_deltas[parent->ofs_first++].obj_no;
assert(child_obj->real_type == OBJ_OFS_DELTA);
@@ -1177,29 +1180,32 @@ static void *threaded_second_pass(void *data)
}
work_unlock();
- if (parent) {
- child = resolve_delta(child_obj, parent);
- if (!child->children_remaining)
- FREE_AND_NULL(child->data);
- } else {
- child = make_base(child_obj, NULL);
- if (child->children_remaining) {
- /*
- * Since this child has its own delta children,
- * we will need this data in the future.
- * Inflate now so that future iterations will
- * have access to this object's data while
- * outside the work mutex.
- */
- child->data = get_data_from_pack(child_obj);
- child->size = child_obj->size;
+ if (child_obj) {
+ if (parent) {
+ child = resolve_delta(child_obj, parent);
+ if (!child->children_remaining)
+ FREE_AND_NULL(child->data);
+ } else{
+ child = make_base(child_obj, NULL);
+ if (child->children_remaining) {
+ /*
+ * Since this child has its own delta children,
+ * we will need this data in the future.
+ * Inflate now so that future iterations will
+ * have access to this object's data while
+ * outside the work mutex.
+ */
+ child->data = get_data_from_pack(child_obj);
+ child->size = child_obj->size;
+ }
}
}
work_lock();
if (parent)
parent->retain_data--;
- if (child->data) {
+
+ if (child && child->data) {
/*
* This child has its own children, so add it to
* work_head.
@@ -1208,7 +1214,7 @@ static void *threaded_second_pass(void *data)
base_cache_used += child->size;
prune_base_data(NULL);
free_base_data(child);
- } else {
+ } else if (child) {
/*
* This child does not have its own children. It may be
* the last descendant of its ancestors; free those