summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: de6182d)
raw | patch | inline | side by side (parent: de6182d)
author | Junio C Hamano <gitster@pobox.com> | |
Fri, 13 May 2011 22:34:58 +0000 (15:34 -0700) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Sat, 21 May 2011 06:16:53 +0000 (23:16 -0700) |
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
streaming.c | patch | blob | history |
diff --git a/streaming.c b/streaming.c
index 13cbce7aabd1ad8552b2948c9935a77d96fc6dcb..4fdd567a36a3f6b22a934838b46f6b2cd71fc3ec 100644 (file)
--- a/streaming.c
+++ b/streaming.c
struct git_istream {
const struct stream_vtbl *vtbl;
unsigned long size; /* inflated size of full object */
+ z_stream z;
+ enum { z_unused, z_used, z_done, z_error } z_state;
union {
struct {
} loose;
struct {
- int fd; /* open for reading */
- /* NEEDSWORK: what else? */
+ struct packed_git *pack;
+ off_t pos;
} in_pack;
} u;
};
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
*
*****************************************************************/
+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)
{
- 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;
}