streaming: read non-delta incrementally from a pack
Helped-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
de6182db67
commit
7ef2d9a260
105
streaming.c
105
streaming.c
@ -51,6 +51,8 @@ static open_istream_fn open_istream_tbl[] = {
|
|||||||
struct git_istream {
|
struct git_istream {
|
||||||
const struct stream_vtbl *vtbl;
|
const struct stream_vtbl *vtbl;
|
||||||
unsigned long size; /* inflated size of full object */
|
unsigned long size; /* inflated size of full object */
|
||||||
|
z_stream z;
|
||||||
|
enum { z_unused, z_used, z_done, z_error } z_state;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
@ -64,8 +66,8 @@ struct git_istream {
|
|||||||
} loose;
|
} loose;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int fd; /* open for reading */
|
struct packed_git *pack;
|
||||||
/* NEEDSWORK: what else? */
|
off_t pos;
|
||||||
} in_pack;
|
} in_pack;
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
@ -128,6 +130,20 @@ struct git_istream *open_istream(const unsigned char *sha1,
|
|||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************
|
||||||
|
*
|
||||||
|
* Common helpers
|
||||||
|
*
|
||||||
|
*****************************************************************/
|
||||||
|
|
||||||
|
static void close_deflated_stream(struct git_istream *st)
|
||||||
|
{
|
||||||
|
if (st->z_state == z_used)
|
||||||
|
git_inflate_end(&st->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************
|
/*****************************************************************
|
||||||
*
|
*
|
||||||
* Loose object stream
|
* Loose object stream
|
||||||
@ -146,9 +162,92 @@ static open_method_decl(loose)
|
|||||||
*
|
*
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
|
||||||
|
static read_method_decl(pack_non_delta)
|
||||||
|
{
|
||||||
|
size_t total_read = 0;
|
||||||
|
|
||||||
|
switch (st->z_state) {
|
||||||
|
case z_unused:
|
||||||
|
memset(&st->z, 0, sizeof(st->z));
|
||||||
|
git_inflate_init(&st->z);
|
||||||
|
st->z_state = z_used;
|
||||||
|
break;
|
||||||
|
case z_done:
|
||||||
|
return 0;
|
||||||
|
case z_error:
|
||||||
|
return -1;
|
||||||
|
case z_used:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (total_read < sz) {
|
||||||
|
int status;
|
||||||
|
struct pack_window *window = NULL;
|
||||||
|
unsigned char *mapped;
|
||||||
|
|
||||||
|
mapped = use_pack(st->u.in_pack.pack, &window,
|
||||||
|
st->u.in_pack.pos, &st->z.avail_in);
|
||||||
|
|
||||||
|
st->z.next_out = (unsigned char *)buf + total_read;
|
||||||
|
st->z.avail_out = sz - total_read;
|
||||||
|
st->z.next_in = mapped;
|
||||||
|
status = git_inflate(&st->z, Z_FINISH);
|
||||||
|
|
||||||
|
st->u.in_pack.pos += st->z.next_in - mapped;
|
||||||
|
total_read = st->z.next_out - (unsigned char *)buf;
|
||||||
|
unuse_pack(&window);
|
||||||
|
|
||||||
|
if (status == Z_STREAM_END) {
|
||||||
|
git_inflate_end(&st->z);
|
||||||
|
st->z_state = z_done;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (status != Z_OK && status != Z_BUF_ERROR) {
|
||||||
|
git_inflate_end(&st->z);
|
||||||
|
st->z_state = z_error;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static close_method_decl(pack_non_delta)
|
||||||
|
{
|
||||||
|
close_deflated_stream(st);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct stream_vtbl pack_non_delta_vtbl = {
|
||||||
|
close_istream_pack_non_delta,
|
||||||
|
read_istream_pack_non_delta,
|
||||||
|
};
|
||||||
|
|
||||||
static open_method_decl(pack_non_delta)
|
static open_method_decl(pack_non_delta)
|
||||||
{
|
{
|
||||||
return -1; /* for now */
|
struct pack_window *window;
|
||||||
|
enum object_type in_pack_type;
|
||||||
|
|
||||||
|
st->u.in_pack.pack = oi->u.packed.pack;
|
||||||
|
st->u.in_pack.pos = oi->u.packed.offset;
|
||||||
|
window = NULL;
|
||||||
|
|
||||||
|
in_pack_type = unpack_object_header(st->u.in_pack.pack,
|
||||||
|
&window,
|
||||||
|
&st->u.in_pack.pos,
|
||||||
|
&st->size);
|
||||||
|
unuse_pack(&window);
|
||||||
|
switch (in_pack_type) {
|
||||||
|
default:
|
||||||
|
return -1; /* we do not do deltas for now */
|
||||||
|
case OBJ_COMMIT:
|
||||||
|
case OBJ_TREE:
|
||||||
|
case OBJ_BLOB:
|
||||||
|
case OBJ_TAG:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
st->z_state = z_unused;
|
||||||
|
st->vtbl = &pack_non_delta_vtbl;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user