mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-08 06:15:02 +00:00
indexer: inject one base at a time
There may be multiple deltas referencing the same base as well as OFS deltas which rely on a thin delta. Deal with both at the same time by injecting a single object and going back up to the main delta-resolving loop.
This commit is contained in:
parent
b4342b116d
commit
7fb6eb278b
@ -683,51 +683,59 @@ cleanup:
|
||||
|
||||
static int fix_thin_pack(git_indexer_stream *idx, git_transfer_progress *stats)
|
||||
{
|
||||
int error;
|
||||
int error, found_ref_delta = 0;
|
||||
unsigned int i;
|
||||
struct delta_info *delta;
|
||||
size_t size;
|
||||
git_otype type;
|
||||
git_mwindow *w = NULL;
|
||||
git_off_t curpos;
|
||||
unsigned char *base_info;
|
||||
unsigned int left = 0;
|
||||
git_oid base;
|
||||
|
||||
assert(git_vector_length(&idx->deltas) > 0);
|
||||
|
||||
if (idx->odb == NULL) {
|
||||
giterr_set(GITERR_INDEXER, "cannot fix a thin pack without an ODB");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Loop until we find the first REF delta */
|
||||
git_vector_foreach(&idx->deltas, i, delta) {
|
||||
size_t size;
|
||||
git_otype type;
|
||||
git_mwindow *w = NULL;
|
||||
git_off_t curpos = delta->delta_off;
|
||||
unsigned char *base_info;
|
||||
unsigned int left = 0;
|
||||
git_oid base;
|
||||
|
||||
curpos = delta->delta_off;
|
||||
error = git_packfile_unpack_header(&size, &type, &idx->pack->mwf, &w, &curpos);
|
||||
git_mwindow_close(&w);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
if (type != GIT_OBJ_REF_DELTA) {
|
||||
giterr_set(GITERR_INDEXER, "delta with missing base is not REF_DELTA");
|
||||
return -1;
|
||||
if (type == GIT_OBJ_REF_DELTA) {
|
||||
found_ref_delta = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* curpos now points to the base information, which is an OID */
|
||||
base_info = git_mwindow_open(&idx->pack->mwf, &w, curpos, GIT_OID_RAWSZ, &left);
|
||||
if (base_info == NULL) {
|
||||
giterr_set(GITERR_INDEXER, "failed to map delta information");
|
||||
return -1;
|
||||
}
|
||||
|
||||
git_oid_fromraw(&base, base_info);
|
||||
git_mwindow_close(&w);
|
||||
|
||||
if (inject_object(idx, &base) < 0)
|
||||
return -1;
|
||||
|
||||
stats->total_objects++;
|
||||
stats->local_objects++;
|
||||
}
|
||||
|
||||
if (!found_ref_delta) {
|
||||
giterr_set(GITERR_INDEXER, "no REF_DELTA found, cannot inject object");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* curpos now points to the base information, which is an OID */
|
||||
base_info = git_mwindow_open(&idx->pack->mwf, &w, curpos, GIT_OID_RAWSZ, &left);
|
||||
if (base_info == NULL) {
|
||||
giterr_set(GITERR_INDEXER, "failed to map delta information");
|
||||
return -1;
|
||||
}
|
||||
|
||||
git_oid_fromraw(&base, base_info);
|
||||
git_mwindow_close(&w);
|
||||
|
||||
if (inject_object(idx, &base) < 0)
|
||||
return -1;
|
||||
|
||||
stats->total_objects++;
|
||||
stats->local_objects++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -764,8 +772,10 @@ static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats)
|
||||
i--;
|
||||
}
|
||||
|
||||
if (!progressed && (fix_thin_pack(idx, stats) < 0))
|
||||
return -1;
|
||||
if (!progressed && (fix_thin_pack(idx, stats) < 0)) {
|
||||
giterr_set(GITERR_INDEXER, "missing delta bases");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user