]> git.ipfire.org Git - thirdparty/git.git/blobdiff - streaming.c
The sixth batch
[thirdparty/git.git] / streaming.c
index d1e6b2dce6877cb1407ac9d38e65d8b2bae25daa..800f07a52cc850d7f972d7c651a8641eda2dfe38 100644 (file)
@@ -16,6 +16,7 @@ enum input_source {
 };
 
 typedef int (*open_istream_fn)(struct git_istream *,
+                              struct repository *,
                               struct object_info *,
                               const struct object_id *,
                               enum object_type *);
@@ -29,8 +30,8 @@ struct stream_vtbl {
 
 #define open_method_decl(name) \
        int open_istream_ ##name \
-       (struct git_istream *st, struct object_info *oi, \
-        const struct object_id *oid, \
+       (struct git_istream *st, struct repository *r, \
+        struct object_info *oi, const struct object_id *oid, \
         enum object_type *type)
 
 #define close_method_decl(name) \
@@ -108,7 +109,8 @@ ssize_t read_istream(struct git_istream *st, void *buf, size_t sz)
        return st->vtbl->read(st, buf, sz);
 }
 
-static enum input_source istream_source(const struct object_id *oid,
+static enum input_source istream_source(struct repository *r,
+                                       const struct object_id *oid,
                                        enum object_type *type,
                                        struct object_info *oi)
 {
@@ -117,7 +119,7 @@ static enum input_source istream_source(const struct object_id *oid,
 
        oi->typep = type;
        oi->sizep = &size;
-       status = oid_object_info_extended(the_repository, oid, oi, 0);
+       status = oid_object_info_extended(r, oid, oi, 0);
        if (status < 0)
                return stream_error;
 
@@ -133,22 +135,23 @@ static enum input_source istream_source(const struct object_id *oid,
        }
 }
 
-struct git_istream *open_istream(const struct object_id *oid,
+struct git_istream *open_istream(struct repository *r,
+                                const struct object_id *oid,
                                 enum object_type *type,
                                 unsigned long *size,
                                 struct stream_filter *filter)
 {
        struct git_istream *st;
        struct object_info oi = OBJECT_INFO_INIT;
-       const struct object_id *real = lookup_replace_object(the_repository, oid);
-       enum input_source src = istream_source(real, type, &oi);
+       const struct object_id *real = lookup_replace_object(r, oid);
+       enum input_source src = istream_source(r, real, type, &oi);
 
        if (src < 0)
                return NULL;
 
        st = xmalloc(sizeof(*st));
-       if (open_istream_tbl[src](st, &oi, real, type)) {
-               if (open_istream_incore(st, &oi, real, type)) {
+       if (open_istream_tbl[src](st, r, &oi, real, type)) {
+               if (open_istream_incore(st, r, &oi, real, type)) {
                        free(st);
                        return NULL;
                }
@@ -338,16 +341,15 @@ static struct stream_vtbl loose_vtbl = {
 
 static open_method_decl(loose)
 {
-       st->u.loose.mapped = map_sha1_file(the_repository,
-                                          oid->hash, &st->u.loose.mapsize);
+       st->u.loose.mapped = map_loose_object(r, oid, &st->u.loose.mapsize);
        if (!st->u.loose.mapped)
                return -1;
-       if ((unpack_sha1_header(&st->z,
-                               st->u.loose.mapped,
-                               st->u.loose.mapsize,
-                               st->u.loose.hdr,
-                               sizeof(st->u.loose.hdr)) < 0) ||
-           (parse_sha1_header(st->u.loose.hdr, &st->size) < 0)) {
+       if ((unpack_loose_header(&st->z,
+                                st->u.loose.mapped,
+                                st->u.loose.mapsize,
+                                st->u.loose.hdr,
+                                sizeof(st->u.loose.hdr)) < 0) ||
+           (parse_loose_header(st->u.loose.hdr, &st->size) < 0)) {
                git_inflate_end(&st->z);
                munmap(st->u.loose.mapped, st->u.loose.mapsize);
                return -1;
@@ -408,6 +410,15 @@ static read_method_decl(pack_non_delta)
                        st->z_state = z_done;
                        break;
                }
+
+               /*
+                * Unlike the loose object case, we do not have to worry here
+                * about running out of input bytes and spinning infinitely. If
+                * we get Z_BUF_ERROR due to too few input bytes, then we'll
+                * replenish them in the next use_pack() call when we loop. If
+                * we truly hit the end of the pack (i.e., because it's corrupt
+                * or truncated), then use_pack() catches that and will die().
+                */
                if (status != Z_OK && status != Z_BUF_ERROR) {
                        git_inflate_end(&st->z);
                        st->z_state = z_error;
@@ -490,7 +501,7 @@ static struct stream_vtbl incore_vtbl = {
 
 static open_method_decl(incore)
 {
-       st->u.incore.buf = read_object_file_extended(oid, type, &st->size, 0);
+       st->u.incore.buf = read_object_file_extended(r, oid, type, &st->size, 0);
        st->u.incore.read_ptr = 0;
        st->vtbl = &incore_vtbl;
 
@@ -511,7 +522,7 @@ int stream_blob_to_fd(int fd, const struct object_id *oid, struct stream_filter
        ssize_t kept = 0;
        int result = -1;
 
-       st = open_istream(oid, &type, &sz, filter);
+       st = open_istream(the_repository, oid, &type, &sz, filter);
        if (!st) {
                if (filter)
                        free_stream_filter(filter);