summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/index.c102
-rw-r--r--src/repository.c23
-rw-r--r--src/repository.h1
3 files changed, 72 insertions, 54 deletions
diff --git a/src/index.c b/src/index.c
index 389780295..d3590da42 100644
--- a/src/index.c
+++ b/src/index.c
@@ -99,7 +99,7 @@ static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffe
static int read_header(struct index_header *dest, const void *buffer);
static int read_tree(git_index *index, const char *buffer, size_t buffer_size);
-static git_index_tree *read_tree_internal(const char **, const char *, git_index_tree *);
+static int read_tree_internal(git_index_tree **, const char **, const char *, git_index_tree *);
static int parse_index(git_index *index, const char *buffer, size_t buffer_size);
static int is_index_extended(git_index *index);
@@ -168,13 +168,19 @@ static int index_initialize(git_index **index_out, git_repository *owner, const
return git_index_read(index);
}
-int git_index_open_bare(git_index **index_out, const char *index_path)
+int git_index_open(git_index **index_out, const char *index_path)
{
+ assert(index_out && index_path);
return index_initialize(index_out, NULL, index_path);
}
-int git_index_open_inrepo(git_index **index_out, git_repository *repo)
+/*
+ * Moved from `repository.c`
+ */
+int git_repository_index(git_index **index_out, git_repository *repo)
{
+ assert(index_out && repo);
+
if (repo->is_bare)
return git__throw(GIT_EBAREINDEX, "Failed to open index. Repository is bare");
@@ -183,7 +189,7 @@ int git_index_open_inrepo(git_index **index_out, git_repository *repo)
void git_index_free(git_index *index)
{
- if (index == NULL || index->repository != NULL)
+ if (index == NULL)
return;
git_index_clear(index);
@@ -479,52 +485,81 @@ const git_index_entry_unmerged *git_index_get_unmerged(git_index *index, const c
}
-static git_index_tree *read_tree_internal(
+static int read_tree_internal(git_index_tree **out,
const char **buffer_in, const char *buffer_end, git_index_tree *parent)
{
git_index_tree *tree;
const char *name_start, *buffer;
long count;
+ int error = GIT_SUCCESS;
if ((tree = git__malloc(sizeof(git_index_tree))) == NULL)
- return NULL;
+ return GIT_ENOMEM;
memset(tree, 0x0, sizeof(git_index_tree));
tree->parent = parent;
buffer = name_start = *buffer_in;
- if ((buffer = memchr(buffer, '\0', buffer_end - buffer)) == NULL)
- goto error_cleanup;
+ if ((buffer = memchr(buffer, '\0', buffer_end - buffer)) == NULL) {
+ error = GIT_EOBJCORRUPTED;
+ goto cleanup;
+ }
/* NUL-terminated tree name */
tree->name = git__strdup(name_start);
- if (++buffer >= buffer_end)
- goto error_cleanup;
+ if (tree->name == NULL) {
+ error = GIT_ENOMEM;
+ goto cleanup;
+ }
+
+ if (++buffer >= buffer_end) {
+ error = GIT_EOBJCORRUPTED;
+ goto cleanup;
+ }
/* Blank-terminated ASCII decimal number of entries in this tree */
- if (git__strtol32(&count, buffer, &buffer, 10) < GIT_SUCCESS ||
- count < 0)
- goto error_cleanup;
+ if (git__strtol32(&count, buffer, &buffer, 10) < GIT_SUCCESS || count < -1) {
+ error = GIT_EOBJCORRUPTED;
+ goto cleanup;
+ }
+
+ /* Invalidated TREE. Free the tree but report success */
+ if (count == -1) {
+ /* FIXME: return buffer_end or the end position for
+ * this single tree entry */
+ *buffer_in = buffer_end;
+ *out = NULL;
+ free_tree(tree); /* Needs to be done manually */
+ return GIT_SUCCESS;
+ }
tree->entries = (size_t)count;
- if (*buffer != ' ' || ++buffer >= buffer_end)
- goto error_cleanup;
+ if (*buffer != ' ' || ++buffer >= buffer_end) {
+ error = GIT_EOBJCORRUPTED;
+ goto cleanup;
+ }
/* Number of children of the tree, newline-terminated */
if (git__strtol32(&count, buffer, &buffer, 10) < GIT_SUCCESS ||
- count < 0)
- goto error_cleanup;
+ count < 0) {
+ error = GIT_EOBJCORRUPTED;
+ goto cleanup;
+ }
tree->children_count = (size_t)count;
- if (*buffer != '\n' || ++buffer >= buffer_end)
- goto error_cleanup;
+ if (*buffer != '\n' || ++buffer >= buffer_end) {
+ error = GIT_EOBJCORRUPTED;
+ goto cleanup;
+ }
/* 160-bit SHA-1 for this tree and it's children */
- if (buffer + GIT_OID_RAWSZ > buffer_end)
- goto error_cleanup;
+ if (buffer + GIT_OID_RAWSZ > buffer_end) {
+ error = GIT_EOBJCORRUPTED;
+ goto cleanup;
+ }
git_oid_mkraw(&tree->oid, (const unsigned char *)buffer);
buffer += GIT_OID_RAWSZ;
@@ -532,33 +567,40 @@ static git_index_tree *read_tree_internal(
/* Parse children: */
if (tree->children_count > 0) {
unsigned int i;
+ int err;
tree->children = git__malloc(tree->children_count * sizeof(git_index_tree *));
if (tree->children == NULL)
- goto error_cleanup;
+ goto cleanup;
for (i = 0; i < tree->children_count; ++i) {
- tree->children[i] = read_tree_internal(&buffer, buffer_end, tree);
+ err = read_tree_internal(&tree->children[i], &buffer, buffer_end, tree);
- if (tree->children[i] == NULL)
- goto error_cleanup;
+ if (err < GIT_SUCCESS)
+ goto cleanup;
}
}
*buffer_in = buffer;
- return tree;
+ *out = tree;
+ return GIT_SUCCESS;
-error_cleanup:
+ cleanup:
free_tree(tree);
- return NULL;
+ return error;
}
static int read_tree(git_index *index, const char *buffer, size_t buffer_size)
{
const char *buffer_end = buffer + buffer_size;
+ int error;
+
+ error = read_tree_internal(&index->tree, &buffer, buffer_end, NULL);
- index->tree = read_tree_internal(&buffer, buffer_end, NULL);
- return (index->tree != NULL && buffer == buffer_end) ? GIT_SUCCESS : GIT_EOBJCORRUPTED;
+ if (buffer < buffer_end)
+ return GIT_EOBJCORRUPTED;
+
+ return error;
}
static int read_unmerged(git_index *index, const char *buffer, size_t size)
diff --git a/src/repository.c b/src/repository.c
index 2054999fc..32ca8dd79 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -315,32 +315,9 @@ void git_repository_free(git_repository *repo)
if (repo->db != NULL)
git_odb_close(repo->db);
- if (repo->index != NULL) {
- repo->index->repository = NULL;
- git_index_free(repo->index);
- }
-
free(repo);
}
-int git_repository_index(git_index **index_out, git_repository *repo)
-{
- int error;
-
- assert(index_out && repo);
-
- if (repo->index == NULL) {
- error = git_index_open_inrepo(&repo->index, repo); /* TODO: move index.c to new error handling */
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to open repository index");
-
- assert(repo->index != NULL);
- }
-
- *index_out = repo->index;
- return GIT_SUCCESS;
-}
-
git_odb *git_repository_database(git_repository *repo)
{
assert(repo);
diff --git a/src/repository.h b/src/repository.h
index 813cac942..bcf9b2bc8 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -25,7 +25,6 @@ struct git_object {
struct git_repository {
git_odb *db;
- git_index *index;
git_cache objects;
git_refcache references;