Usage of snprintf() is possibly not the most efficient approach. For example we could simply copy the needed strings and generate the SHA1 hex strings directly into the destination buffer. But such optimizations may come later. Signed-off-by: Nicolas Pitre <nico@xxxxxxxxxxx> --- packv4-parse.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/packv4-parse.c b/packv4-parse.c index 074e107..bca1a97 100644 --- a/packv4-parse.c +++ b/packv4-parse.c @@ -129,3 +129,77 @@ const unsigned char *get_nameref(struct packed_git *p, const unsigned char **src } return p->name_dict->data + p->name_dict->offsets[index]; } + +void *pv4_get_commit(struct packed_git *p, struct pack_window **w_curs, + off_t offset, unsigned long size) +{ + unsigned long avail; + git_zstream stream; + int len, st; + unsigned int nb_parents; + unsigned char *dst, *dcp; + const unsigned char *src, *scp, *sha1, *name; + unsigned long time; + int16_t tz; + + dst = xmallocz(size); + dcp = dst; + + src = use_pack(p, w_curs, offset, &avail); + scp = src; + + sha1 = get_sha1ref(p, &scp); + len = snprintf((char *)dcp, size, "tree %s\n", sha1_to_hex(sha1)); + dcp += len; + size -= len; + + nb_parents = decode_varint(&scp); + while (nb_parents--) { + sha1 = get_sha1ref(p, &scp); + len = snprintf((char *)dcp, size, "parent %s\n", sha1_to_hex(sha1)); + if (len >= size) + die("overflow in %s", __func__); + dcp += len; + size -= len; + } + + name = get_nameref(p, &scp); + tz = (name[0] << 8) | name[1]; + time = decode_varint(&scp); + len = snprintf((char *)dcp, size, "author %s %lu %+05d\n", name+2, time, tz); + if (len >= size) + die("overflow in %s", __func__); + dcp += len; + size -= len; + + name = get_nameref(p, &scp); + tz = (name[0] << 8) | name[1]; + time = decode_varint(&scp); + len = snprintf((char *)dcp, size, "committer %s %lu %+05d\n", name+2, time, tz); + if (len >= size) + die("overflow in %s", __func__); + dcp += len; + size -= len; + + if (scp - src > avail) + die("overflow in %s", __func__); + offset += scp - src; + + memset(&stream, 0, sizeof(stream)); + stream.next_out = dcp; + stream.avail_out = size + 1; + git_inflate_init(&stream); + do { + src = use_pack(p, w_curs, offset, &stream.avail_in); + stream.next_in = (unsigned char *)src; + st = git_inflate(&stream, Z_FINISH); + offset += stream.next_in - src; + } while ((st == Z_OK || st == Z_BUF_ERROR) && stream.avail_out); + git_inflate_end(&stream); + if (st != Z_STREAM_END || stream.total_out != size) { + free(dst); + return NULL; + } + + return dst; +} -- 1.8.4.38.g317e65b -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html