Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2013-10-02 14:22:54 +0400
committerCarlos Martín Nieto <cmn@dwim.me>2013-10-04 12:18:20 +0400
commitcf0582b43ce591e7923637d2c8925028aaa5977b (patch)
treef8f615e178b16967fd9f89c8bb155f531294bdcf /src/indexer.c
parent71e33d2649f990086237a6cd0fdb7f7d6f742b51 (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.c42
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;