summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2010-07-10 16:51:15 -0700
committerVicent Marti <tanoku@gmail.com>2010-07-15 23:41:49 +0200
commitd8603ed901d4af4d0d2b493d1164c74eae34f147 (patch)
tree12b66564dafa01d8a13b8ecf53474b1d305ea771
parent3e590fb2221ea3c117b7347956843d24132ac22b (diff)
downloadlibgit2-d8603ed901d4af4d0d2b493d1164c74eae34f147.tar.gz
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>
-rw-r--r--src/commit.c1
-rw-r--r--src/git/tree.h12
-rw-r--r--src/tree.c74
-rw-r--r--src/tree.h16
4 files changed, 103 insertions, 0 deletions
diff --git a/src/commit.c b/src/commit.c
index 6b0b66190..e4e56117d 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 d5f668c54..9a4973ba6 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 2ba363e58..47b027322 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 532a2f46e..373345663 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