diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2013-10-02 14:22:54 +0400 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2013-10-04 12:18:20 +0400 |
commit | cf0582b43ce591e7923637d2c8925028aaa5977b (patch) | |
tree | f8f615e178b16967fd9f89c8bb155f531294bdcf /src/indexer.c | |
parent | 71e33d2649f990086237a6cd0fdb7f7d6f742b51 (diff) |
indexer: do multiple passes over the delta list
Though unusual, a packfile may contain a delta whose base is a delta
that comes later. In order index such a packfile, we must not give up
on the first failure to resolve a delta, but keep it around.
If there is a pass which makes no progress, this indicates that the
packfile is broken, so fail accordingly.
Diffstat (limited to 'src/indexer.c')
-rw-r--r-- | src/indexer.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/src/indexer.c b/src/indexer.c index 3b160df5d..10b6929ee 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -594,20 +594,38 @@ static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats) { unsigned int i; struct delta_info *delta; + int progressed = 0; + + while (idx->deltas.length > 0) { + progressed = 0; + git_vector_foreach(&idx->deltas, i, delta) { + git_rawobj obj; + + idx->off = delta->delta_off; + if (git_packfile_unpack(&obj, idx->pack, &idx->off) < 0) + continue; + + if (hash_and_save(idx, &obj, delta->delta_off) < 0) + continue; + + git__free(obj.data); + stats->indexed_objects++; + progressed = 1; + do_progress_callback(idx, stats); + + /* + * Remove this delta from the list and + * decrease i so we don't skip over the next + * delta. + */ + git_vector_remove(&idx->deltas, i); + i--; + } - git_vector_foreach(&idx->deltas, i, delta) { - git_rawobj obj; - - idx->off = delta->delta_off; - if (git_packfile_unpack(&obj, idx->pack, &idx->off) < 0) - return -1; - - if (hash_and_save(idx, &obj, delta->delta_off) < 0) + if (!progressed) { + giterr_set(GITERR_INDEXER, "the packfile is missing bases"); return -1; - - git__free(obj.data); - stats->indexed_objects++; - do_progress_callback(idx, stats); + } } return 0; |