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
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user