Best "explained" with an example
void walk(const unsigned char *sha1)
{
struct pv4_tree_desc desc;
/*
* Start pv4_tree_desc from an SHA-1. If it's a v4 tree, v4 walker
* will be used. Otherwise v2 is walked.
*/
pv4_tree_desc_from_sha1(&desc, sha1, 0);
recurse(&desc);
pv4_release_tree_desc(&desc);
}
void recurse(struct pv4_tree_desc *desc)
{
/*
* Then you can go over entries, one by one, similar to the
* current tree walker. Current entry is in desc->v2.entry.
* Pathlen in desc->pathlen. Do not use tree_entry_len() because
* that one is only correct for v2 entries
*/
while (pv4_get_entry(desc)) {
printf("%s %s\n", sha1_to_hex(desc->v2.entry.sha1),
desc->v2.entry.path);
/*
* Once you have an initialized pv4_tree_desc you may skip the
* SHA-1 lookup step if the next tree is in the same pack.
*/
if (S_ISDIR(desc->v2.entry.mode)) {
struct pv4_tree_desc new_desc;
pv4_tree_desc_from_entry(&new_desc, desc);
recurse(&new_desc);
/* Finally release everything */
pv4_release_tree_desc(&new_desc);
}
}
}
Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]>
---
packv4-parse.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
packv4-parse.h | 12 +++++++++
2 files changed, 92 insertions(+)
diff --git a/packv4-parse.c b/packv4-parse.c
index f222456..7d257af 100644
--- a/packv4-parse.c
+++ b/packv4-parse.c
@@ -732,3 +732,83 @@ unsigned long pv4_unpack_object_header_buffer(const
unsigned char *base,
*sizep = val >> 4;
return cp - base;
}
+
+int pv4_tree_desc_from_sha1(struct pv4_tree_desc *desc,
+ const unsigned char *sha1,
+ unsigned flags)
+{
+ unsigned long size;
+ enum object_type type;
+ void *data;
+ struct object_info oi;
+
+ assert(!(flags & ~0xff) &&
+ "you are not supposed to set these from outside!");
+
+ memset(desc, 0, sizeof(*desc));
+ strbuf_init(&desc->buf, 0);
+
+ memset(&oi, 0, sizeof(oi));
+ if (!sha1_object_info_extended(sha1, &oi) &&
+ oi.whence == OI_PACKED &&
+ oi.u.packed.real_type == OBJ_PV4_TREE &&
+ oi.u.packed.pack->version >= 4) {
+ desc->p = oi.u.packed.pack;
+ desc->obj_offset = oi.u.packed.offset;
+ desc->flags = flags;
+ return 0;
+ }
+
+ data = read_sha1_file(sha1, &type, &size);
+ if (!data || type != OBJ_TREE) {
+ free(data);
+ return -1;
+ }
+ desc->flags = flags;
+ desc->flags |= PV4_TREE_CANONICAL;
+ init_tree_desc(&desc->v2, data, size);
+ /*
+ * we can attach to strbuf because read_sha1_file always
+ * appends NUL at the end
+ */
+ strbuf_attach(&desc->buf, data, size, size + 1);
+ return 0;
+}
+
+int pv4_tree_desc_from_entry(struct pv4_tree_desc *desc,
+ const struct pv4_tree_desc *src,
+ unsigned flags)
+{
+ if (!src->sha1_index)
+ return pv4_tree_desc_from_sha1(desc,
+ src->v2.entry.sha1,
+ flags);
+ assert(!(flags & ~0xff) &&
+ "you are not supposed to set these from outside!");
+ memset(desc, 0, sizeof(*desc));
+ strbuf_init(&desc->buf, 0);
+ desc->p = src->p;
+ desc->obj_offset =
+ nth_packed_object_offset(desc->p, src->sha1_index - 1);
+ desc->flags = flags;
+ return 0;
+}
+
+void pv4_release_tree_desc(struct pv4_tree_desc *desc)
+{
+ strbuf_release(&desc->buf);
+ unuse_pack(&desc->w_curs);
+}
+
+int pv4_tree_entry(struct pv4_tree_desc *desc)
+{
+ if (desc->flags & PV4_TREE_CANONICAL) {
+ if (!desc->v2.size)
+ return 0;
+ if (desc->start)
+ update_tree_entry(&desc->v2);
+ desc->start++;
+ return 1;
+ }
+ return !decode_entries(desc, desc->obj_offset, desc->start++, 1);
+}
diff --git a/packv4-parse.h b/packv4-parse.h
index fe0ea38..874f57c 100644
--- a/packv4-parse.h
+++ b/packv4-parse.h
@@ -36,6 +36,8 @@ struct pv4_tree_desc {
/* v4 entry */
struct packed_git *p;
struct pack_window *w_curs;
+ off_t obj_offset;
+ unsigned start;
unsigned int sha1_index;
int pathlen;
@@ -46,4 +48,14 @@ struct pv4_tree_desc {
struct strbuf buf;
};
+int pv4_tree_desc_from_sha1(struct pv4_tree_desc *desc,
+ const unsigned char *sha1,
+ unsigned flags);
+int pv4_tree_desc_from_entry(struct pv4_tree_desc *desc,
+ const struct pv4_tree_desc *src,
+ unsigned flags);
+void pv4_release_tree_desc(struct pv4_tree_desc *desc);
+
+int pv4_tree_entry(struct pv4_tree_desc *desc);
+
#endif
--
1.8.2.83.gc99314b
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html