When PV4_TREE_CANONICAL is passed, decode_entries() generates <count>
tree entries in canonical format. When this flag is not passed _and_
count is 1, decode_entries fills struct name_entry and saves
sha1_index.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 packv4-parse.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
 packv4-parse.h | 10 ++++++++++
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/packv4-parse.c b/packv4-parse.c
index f5c486e..f222456 100644
--- a/packv4-parse.c
+++ b/packv4-parse.c
@@ -365,6 +365,12 @@ static int copy_canonical_tree_entries(struct 
pv4_tree_desc *v4, off_t offset,
        while (start--)
                update_tree_entry(desc);
 
+       if (!(v4->flags & PV4_TREE_CANONICAL)) {
+               v4->sha1_index = 0;
+               v4->pathlen = tree_entry_len(&desc->entry);
+               return 0;
+       }
+
        from = desc->buffer;
        while (count--)
                update_tree_entry(desc);
@@ -462,6 +468,33 @@ static int generate_tree_entry(struct pv4_tree_desc *desc,
        return 0;
 }
 
+static int get_tree_entry_v4(struct pv4_tree_desc *desc,
+                            const unsigned char **bufp,
+                            int what)
+{
+       const unsigned char *path;
+
+       path = get_pathref(desc->p, what >> 1, &desc->pathlen);
+       if (!path)
+               return -1;
+       desc->v2.entry.mode = (path[0] << 8) | path[1];
+       desc->v2.entry.path = (const char *)path + 2;
+
+       if (**bufp) {
+               desc->sha1_index = decode_varint(bufp);
+               if (desc->sha1_index < 1 ||
+                   desc->sha1_index - 1 > desc->p->num_objects)
+                       return error("bad index in get_sha1ref");
+               desc->v2.entry.sha1 = desc->p->sha1_table + (desc->sha1_index - 
1) * 20;
+       } else {
+               desc->sha1_index = 0;
+               desc->v2.entry.sha1 = *bufp + 1;
+               *bufp += 21;
+       }
+
+       return 0;
+}
+
 static int decode_entries(struct pv4_tree_desc *desc, off_t obj_offset,
                          unsigned int start, unsigned int count)
 {
@@ -561,8 +594,14 @@ static int decode_entries(struct pv4_tree_desc *desc, 
off_t obj_offset,
                        /*
                         * This is an actual tree entry to recreate.
                         */
-                       if (generate_tree_entry(desc, &scp, what))
-                               return -1;
+                       if (desc->flags & PV4_TREE_CANONICAL) {
+                               if (generate_tree_entry(desc, &scp, what))
+                                       return -1;
+                       } else if (count == 1) {
+                               if (get_tree_entry_v4(desc, &scp, what))
+                                       return -1;
+                       } else
+                               die("generating multiple v4 entries is not 
supported");
                        count--;
                        curpos++;
                } else if (what & 1) {
@@ -668,6 +707,7 @@ void *pv4_get_tree(struct packed_git *p, struct pack_window 
**w_curs,
        int ret;
 
        memset(&desc, 0, sizeof(desc));
+       desc.flags = PV4_TREE_CANONICAL;
        desc.p = p;
        desc.w_curs = *w_curs;
        strbuf_init(&desc.buf, size);
diff --git a/packv4-parse.h b/packv4-parse.h
index 04b9a59..fe0ea38 100644
--- a/packv4-parse.h
+++ b/packv4-parse.h
@@ -24,10 +24,20 @@ void *pv4_get_commit(struct packed_git *p, struct 
pack_window **w_curs,
 void *pv4_get_tree(struct packed_git *p, struct pack_window **w_curs,
                   off_t obj_offset, unsigned long size);
 
+/*
+ * These are private flags, never pass them directly to
+ * pv4_tree_desc_*
+ */
+#define PV4_TREE_CANONICAL   0x800
+
 struct pv4_tree_desc {
+       unsigned flags;
+
        /* v4 entry */
        struct packed_git *p;
        struct pack_window *w_curs;
+       unsigned int sha1_index;
+       int pathlen;
 
        /* v2 entry */
        struct tree_desc v2;
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to