summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <carlos@cmartin.tk>2012-07-13 20:43:56 +0200
committerCarlos Martín Nieto <carlos@cmartin.tk>2012-07-14 22:29:11 +0200
commitd1af70b0509916abcb4724e0d8cdbee8ebf6bb2d (patch)
treef01f502be8a70c7f783ea6f7e62aad73317a6256
parent7b8c9e123d3925f4d7aaa614a591e4188a80d464 (diff)
downloadlibgit2-d1af70b0509916abcb4724e0d8cdbee8ebf6bb2d.tar.gz
indexer: delay resolving deltas
Not all delta bases are available on the first try. By delaying resolving all deltas until the end, we avoid decompressing some of the data twice or even more times, saving effort and time.
-rw-r--r--src/indexer.c46
1 files changed, 24 insertions, 22 deletions
diff --git a/src/indexer.c b/src/indexer.c
index 1f0ca82a2..797a58275 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -169,29 +169,14 @@ cleanup:
}
/* Try to store the delta so we can try to resolve it later */
-static int store_delta(git_indexer_stream *idx)
+static int store_delta(git_indexer_stream *idx, git_off_t entry_start, size_t entry_size, git_otype type)
{
- git_otype type;
git_mwindow *w = NULL;
- git_mwindow_file *mwf = &idx->pack->mwf;
- git_off_t entry_start = idx->off;
struct delta_info *delta;
- size_t entry_size;
git_rawobj obj;
int error;
- /*
- * ref-delta objects can refer to object that we haven't
- * found yet, so give it another opportunity
- */
- if (git_packfile_unpack_header(&entry_size, &type, mwf, &w, &idx->off) < 0)
- return -1;
-
- git_mwindow_close(&w);
-
- /* If it's not a delta, mark it as failure, we can't do anything with it */
- if (type != GIT_OBJ_REF_DELTA && type != GIT_OBJ_OFS_DELTA)
- return -1;
+ assert(type == GIT_OBJ_REF_DELTA || type == GIT_OBJ_OFS_DELTA);
if (type == GIT_OBJ_REF_DELTA) {
idx->off += GIT_OID_RAWSZ;
@@ -350,27 +335,44 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
while (processed < idx->nr_objects) {
git_rawobj obj;
git_off_t entry_start = idx->off;
+ size_t entry_size;
+ git_otype type;
+ git_mwindow *w = NULL;
if (idx->pack->mwf.size <= idx->off + 20)
return 0;
- error = git_packfile_unpack(&obj, idx->pack, &idx->off);
+ error = git_packfile_unpack_header(&entry_size, &type, mwf, &w, &idx->off);
if (error == GIT_EBUFS) {
idx->off = entry_start;
return 0;
}
+ if (error < 0)
+ return -1;
- if (error < 0) {
- idx->off = entry_start;
- error = store_delta(idx);
+ git_mwindow_close(&w);
- if (error == GIT_EBUFS)
+ if (type == GIT_OBJ_REF_DELTA || type == GIT_OBJ_OFS_DELTA) {
+ error = store_delta(idx, entry_start, entry_size, type);
+ if (error == GIT_EBUFS) {
+ idx->off = entry_start;
return 0;
+ }
if (error < 0)
return error;
+
continue;
}
+ idx->off = entry_start;
+ error = git_packfile_unpack(&obj, idx->pack, &idx->off);
+ if (error == GIT_EBUFS) {
+ idx->off = entry_start;
+ return 0;
+ }
+ if (error < 0)
+ return -1;
+
if (hash_and_save(idx, &obj, entry_start) < 0)
goto on_error;