Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- builtin/pack-objects.c | 85 ++++++++++++++++++++++++++++++++++++++++++++------ pack.h | 2 +- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index daa4349..f6586a1 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -254,8 +254,10 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent enum object_type type; void *buf; struct git_istream *st = NULL; + char *result = "OK"; - if (!usable_delta) { + if (!usable_delta || + (pack_version == 4 || entry->type == OBJ_TREE)) { if (entry->type == OBJ_BLOB && entry->size > big_file_threshold && (st = open_istream(entry->idx.sha1, &type, &size, NULL)) != NULL) @@ -287,7 +289,37 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent if (st) /* large blob case, just assume we don't compress well */ datalen = size; - else if (entry->z_delta_size) + else if (pack_version == 4 && entry->type == OBJ_COMMIT) { + datalen = size; + result = pv4_encode_commit(&v4, buf, &datalen); + if (result) { + free(buf); + buf = result; + type = OBJ_PV4_COMMIT; + } + } else if (pack_version == 4 && entry->type == OBJ_TREE) { + datalen = size; + if (usable_delta) { + unsigned long base_size; + char *base_buf; + base_buf = read_sha1_file(entry->delta->idx.sha1, &type, + &base_size); + if (!base_buf || type != OBJ_TREE) + die("unable to read %s", + sha1_to_hex(entry->delta->idx.sha1)); + result = pv4_encode_tree(&v4, buf, &datalen, + base_buf, base_size, + entry->delta->idx.sha1); + free(base_buf); + } else + result = pv4_encode_tree(&v4, buf, &datalen, + NULL, 0, NULL); + if (result) { + free(buf); + buf = result; + type = OBJ_PV4_TREE; + } + } else if (entry->z_delta_size) datalen = entry->z_delta_size; else datalen = do_compress(&buf, size); @@ -296,7 +328,10 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent * The object header is a byte of 'type' followed by zero or * more bytes of length. */ - hdrlen = encode_in_pack_object_header(type, size, header); + if (pack_version < 4) + hdrlen = encode_in_pack_object_header(type, size, header); + else + hdrlen = pv4_encode_in_pack_object_header(type, size, header); if (type == OBJ_OFS_DELTA) { /* @@ -318,7 +353,7 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent sha1write(f, header, hdrlen); sha1write(f, dheader + pos, sizeof(dheader) - pos); hdrlen += sizeof(dheader) - pos; - } else if (type == OBJ_REF_DELTA) { + } else if (type == OBJ_REF_DELTA && pack_version < 4) { /* * Deltas with a base reference contain * an additional 20 bytes for the base sha1. @@ -332,6 +367,10 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent sha1write(f, header, hdrlen); sha1write(f, entry->delta->idx.sha1, 20); hdrlen += 20; + } else if (type == OBJ_REF_DELTA && pack_version == 4) { + hdrlen += encode_sha1ref(&v4, entry->delta->idx.sha1, + header + hdrlen); + sha1write(f, header, hdrlen); } else { if (limit && hdrlen + datalen + 20 >= limit) { if (st) @@ -341,14 +380,26 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent } sha1write(f, header, hdrlen); } + if (st) { datalen = write_large_blob_data(st, f, entry->idx.sha1); close_istream(st); - } else { - sha1write(f, buf, datalen); - free(buf); + return hdrlen + datalen; } + if (!result) { + warning(_("can't convert %s object %s"), + typename(entry->type), + sha1_to_hex(entry->idx.sha1)); + free(buf); + buf = read_sha1_file(entry->idx.sha1, &type, &size); + if (!buf) + die(_("unable to read %s"), + sha1_to_hex(entry->idx.sha1)); + datalen = do_compress(&buf, size); + } + sha1write(f, buf, datalen); + free(buf); return hdrlen + datalen; } @@ -368,7 +419,10 @@ static unsigned long write_reuse_object(struct sha1file *f, struct object_entry if (entry->delta) type = (allow_ofs_delta && entry->delta->idx.offset) ? OBJ_OFS_DELTA : OBJ_REF_DELTA; - hdrlen = encode_in_pack_object_header(type, entry->size, header); + if (pack_version < 4) + hdrlen = encode_in_pack_object_header(type, entry->size, header); + else + hdrlen = pv4_encode_in_pack_object_header(type, entry->size, header); offset = entry->in_pack_offset; revidx = find_pack_revindex(p, offset); @@ -404,7 +458,7 @@ static unsigned long write_reuse_object(struct sha1file *f, struct object_entry sha1write(f, dheader + pos, sizeof(dheader) - pos); hdrlen += sizeof(dheader) - pos; reused_delta++; - } else if (type == OBJ_REF_DELTA) { + } else if (type == OBJ_REF_DELTA && pack_version < 4) { if (limit && hdrlen + 20 + datalen + 20 >= limit) { unuse_pack(&w_curs); return 0; @@ -413,6 +467,11 @@ static unsigned long write_reuse_object(struct sha1file *f, struct object_entry sha1write(f, entry->delta->idx.sha1, 20); hdrlen += 20; reused_delta++; + } else if (type == OBJ_REF_DELTA && pack_version == 4) { + hdrlen += encode_sha1ref(&v4, entry->delta->idx.sha1, + header + hdrlen); + sha1write(f, header, hdrlen); + reused_delta++; } else { if (limit && hdrlen + datalen + 20 >= limit) { unuse_pack(&w_curs); @@ -477,7 +536,9 @@ static unsigned long write_object(struct sha1file *f, * and we do not need to deltify it. */ - if (!to_reuse) + if (!to_reuse || + (pack_version == 4 && + (entry->type == OBJ_TREE || entry->type == OBJ_COMMIT))) len = write_no_reuse_object(f, entry, limit, usable_delta); else len = write_reuse_object(f, entry, limit, usable_delta); @@ -742,6 +803,8 @@ static void write_pack_file(void) offset = write_pack_header(f, pack_version, nr_remaining); if (!offset) die_errno("unable to write pack header"); + if (pack_version == 4) + offset += packv4_write_tables(f, &v4); nr_written = 0; for (; i < nr_objects; i++) { struct object_entry *e = write_order[i]; @@ -2083,6 +2146,8 @@ static void prepare_pack(int window, int depth) sort_dict_entries_by_hits(v4.commit_ident_table); sort_dict_entries_by_hits(v4.tree_path_table); prepare_sha1_table(); + pack_idx_opts.version = 3; + allow_ofs_delta = 0; } get_object_details(); diff --git a/pack.h b/pack.h index 38f869d..fde60ec 100644 --- a/pack.h +++ b/pack.h @@ -8,7 +8,7 @@ * Packed object header */ #define PACK_SIGNATURE 0x5041434b /* "PACK" */ -#define pack_version_ok(v) ((v) == htonl(2) || (v) == htonl(3)) +#define pack_version_ok(v) ((v) == htonl(2) || (v) == htonl(3) || (v) == htonl(4)) struct pack_header { uint32_t hdr_signature; uint32_t hdr_version; -- 1.8.2.83.gc99314b -- 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