[PATCH 07/32] tree.c: find_subtree() to search for a tree
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
tree.c | 35 +++++++++++++++++++++++++++++++++++
tree.h | 1 +
2 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/tree.c b/tree.c
index 434bf56..684afb5 100644
--- a/tree.c
+++ b/tree.c
@@ -328,3 +328,38 @@ void clear_tree_marks(struct tree *tree, unsigned mark)
}
free(buffer);
}
+
+int find_tree(const unsigned char *sha1, unsigned char *newsha1, const char *path)
+{
+ struct name_entry entry;
+ struct tree_desc desc;
+ enum object_type type;
+ unsigned long size;
+ void *buffer;
+ const char *slash;
+ int len;
+
+ buffer = read_sha1_file(sha1, &type, &size);
+ if (!buffer || type != OBJ_TREE)
+ die("%s is not a tree", sha1_to_hex(sha1));
+
+ slash = strchr(path, '/');
+ len = slash ? slash - path : strlen(path);
+
+ init_tree_desc(&desc, buffer, size);
+ while (tree_entry(&desc, &entry)) {
+ if (!S_ISDIR(entry.mode))
+ continue;
+ if (!strncmp(entry.path, path, len)) {
+ free(buffer);
+ if (slash)
+ return find_tree(entry.sha1, newsha1, slash+1);
+ else {
+ hashcpy(newsha1, entry.sha1);
+ return 1;
+ }
+ }
+ }
+ free(buffer);
+ return 0;
+}
diff --git a/tree.h b/tree.h
index 4376a3a..6ba1034 100644
--- a/tree.h
+++ b/tree.h
@@ -32,5 +32,6 @@ extern int read_tree(struct tree *tree, int stage, const char **paths);
extern void set_tree_marks(struct tree *tree, unsigned mark);
extern void clear_tree_marks(struct tree *tree, unsigned mark);
+extern int find_tree(const unsigned char *sha1, unsigned char *newsha1, const char *path);
#endif /* TREE_H */
--
1.7.1.rc1.69.g24c2f7