From 7fb6eb278b350f9f4caab5a3f72bfb70353fc40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 8 Oct 2013 11:54:50 +0200 Subject: [PATCH] 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. --- src/indexer.c | 70 +++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 21b993a28..2cda1a629 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -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;