Add parsing of tree file contents. The basic information (pointed trees and blobs) of each tree object in a revision pool can now be parsed and queried. Signed-off-by: Vicent Marti <tanoku@gmail.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
diff --git a/src/commit.c b/src/commit.c
index 6b0b661..e4e5611 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -83,6 +83,7 @@ git_commit *git_commit_parse(git_revpool *pool, const git_oid *id)
return commit;
error_cleanup:
+ /* FIXME: do not free; the commit is owned by the revpool */
free(commit);
return NULL;
}
diff --git a/src/git/tree.h b/src/git/tree.h
index d5f668c..9a4973b 100644
--- a/src/git/tree.h
+++ b/src/git/tree.h
@@ -28,6 +28,18 @@ typedef struct git_tree git_tree;
GIT_EXTERN(git_tree *) git_tree_lookup(git_revpool *pool, const git_oid *id);
/**
+ * Locate a reference to a tree object and parse its
+ * contents.
+ * The generated tree object is owned by the revision
+ * pool and shall not be freed by the user.
+ *
+ * @param pool the pool to use when locating the tree.
+ * @param id identity of the tree to locate.
+ * @return the tree; NULL if the tree could not be created
+ */
+GIT_EXTERN(git_tree *) git_tree_parse(git_revpool *pool, const git_oid *id);
+
+/**
* Get the id of a tree.
* @param tree a previously loaded tree.
* @return object identity for the tree.
diff --git a/src/tree.c b/src/tree.c
index 2ba363e..47b0273 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -65,3 +65,77 @@ git_tree *git_tree_lookup(git_revpool *pool, const git_oid *id)
return tree;
}
+
+
+git_tree *git_tree_parse(git_revpool *pool, const git_oid *id)
+{
+ git_tree *tree = NULL;
+
+ if ((tree = git_tree_lookup(pool, id)) == NULL)
+ return NULL;
+
+ if (git_tree__parse(tree) < 0)
+ goto error_cleanup;
+
+ return tree;
+
+error_cleanup:
+ /* FIXME: do not free; the tree is owned by the revpool */
+ free(tree);
+ return NULL;
+}
+
+int git_tree__parse(git_tree *tree)
+{
+ static const char tree_header[] = {'t', 'r', 'e', 'e', ' '};
+
+ int error = 0;
+ git_obj odb_object;
+ char *buffer, *buffer_end;
+
+ error = git_odb_read(&odb_object, tree->object.pool->db, &tree->object.id);
+ if (error < 0)
+ return error;
+
+ buffer = odb_object.data;
+ buffer_end = odb_object.data + odb_object.len;
+
+ if (memcmp(buffer, tree_header, 5) != 0)
+ return GIT_EOBJCORRUPTED;
+
+ buffer += 5;
+
+ tree->byte_size = strtol(buffer, &buffer, 10);
+
+ if (*buffer++ != 0)
+ return GIT_EOBJCORRUPTED;
+
+ while (buffer < buffer_end) {
+ git_tree_entry *entry;
+
+ entry = git__malloc(sizeof(git_tree_entry));
+ entry->next = tree->entries;
+
+ entry->attr = strtol(buffer, &buffer, 10);
+
+ if (*buffer++ != ' ') {
+ error = GIT_EOBJCORRUPTED;
+ break;
+ }
+
+ entry->filename = git__strdup(buffer);
+
+ if (entry->filename == NULL) {
+ error = GIT_EOBJCORRUPTED;
+ break;
+ }
+ buffer += strlen(entry->filename);
+
+ git_oid_mkraw(&entry->oid, (const unsigned char *)buffer);
+ buffer += GIT_OID_RAWSZ;
+
+ tree->entries = entry;
+ }
+
+ return error;
+}
diff --git a/src/tree.h b/src/tree.h
index 532a2f4..3733456 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -4,10 +4,26 @@
#include <git/tree.h>
#include "revobject.h"
+struct git_tree_entry {
+
+ unsigned int attr;
+ char *filename;
+ git_oid oid;
+
+ struct git_tree_entry *next;
+};
+
+typedef struct git_tree_entry git_tree_entry;
+
struct git_tree {
git_revpool_object object;
+
+ size_t byte_size;
+ git_tree_entry *entries;
+ unsigned int entry_count;
};
void git_tree__free(git_tree *tree);
+int git_tree__parse(git_tree *tree);
#endif