Commit 4d384d6b by Edward Thomson

Merge pull request #3759 from libgit2/cmn/faster-header

odb: avoid inflating the full delta to read the header
parents d24425fa a97b769a
...@@ -49,6 +49,37 @@ int git__delta_read_header( ...@@ -49,6 +49,37 @@ int git__delta_read_header(
return 0; return 0;
} }
#define DELTA_HEADER_BUFFER_LEN 16
int git__delta_read_header_fromstream(size_t *base_sz, size_t *res_sz, git_packfile_stream *stream)
{
static const size_t buffer_len = DELTA_HEADER_BUFFER_LEN;
unsigned char buffer[DELTA_HEADER_BUFFER_LEN];
const unsigned char *delta, *delta_end;
size_t len;
ssize_t read;
len = read = 0;
while (len < buffer_len) {
read = git_packfile_stream_read(stream, &buffer[len], buffer_len - len);
if (read == 0)
break;
if (read == GIT_EBUFS)
continue;
len += read;
}
delta = buffer;
delta_end = delta + len;
if ((hdr_sz(base_sz, &delta, delta_end) < 0) ||
(hdr_sz(res_sz, &delta, delta_end) < 0))
return -1;
return 0;
}
int git__delta_apply( int git__delta_apply(
git_rawobj *out, git_rawobj *out,
const unsigned char *base, const unsigned char *base,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define INCLUDE_delta_apply_h__ #define INCLUDE_delta_apply_h__
#include "odb.h" #include "odb.h"
#include "pack.h"
/** /**
* Apply a git binary delta to recover the original content. * Apply a git binary delta to recover the original content.
...@@ -47,4 +48,15 @@ extern int git__delta_read_header( ...@@ -47,4 +48,15 @@ extern int git__delta_read_header(
size_t *base_sz, size_t *base_sz,
size_t *res_sz); size_t *res_sz);
/**
* Read the header of a git binary delta
*
* This variant reads just enough from the packfile stream to read the
* delta header.
*/
extern int git__delta_read_header_fromstream(
size_t *base_sz,
size_t *res_sz,
git_packfile_stream *stream);
#endif #endif
...@@ -499,15 +499,14 @@ int git_packfile_resolve_header( ...@@ -499,15 +499,14 @@ int git_packfile_resolve_header(
if (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) { if (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
size_t base_size; size_t base_size;
git_rawobj delta; git_packfile_stream stream;
base_offset = get_delta_base(p, &w_curs, &curpos, type, offset); base_offset = get_delta_base(p, &w_curs, &curpos, type, offset);
git_mwindow_close(&w_curs); git_mwindow_close(&w_curs);
error = packfile_unpack_compressed(&delta, p, &w_curs, &curpos, size, type); if ((error = git_packfile_stream_open(&stream, p, curpos)) < 0)
git_mwindow_close(&w_curs);
if (error < 0)
return error; return error;
error = git__delta_read_header(delta.data, delta.len, &base_size, size_p); error = git__delta_read_header_fromstream(&base_size, size_p, &stream);
git__free(delta.data); git_packfile_stream_free(&stream);
if (error < 0) if (error < 0)
return error; return error;
} else } else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment