summaryrefslogtreecommitdiff
path: root/src/repository.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/repository.c')
-rw-r--r--src/repository.c101
1 files changed, 94 insertions, 7 deletions
diff --git a/src/repository.c b/src/repository.c
index fe7b870fe..433e72916 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -28,6 +28,7 @@
#include "repository.h"
#include "commit.h"
#include "tag.h"
+#include "fileops.h"
static const int default_table_size = 32;
static const double max_load_factor = 0.65;
@@ -43,7 +44,7 @@ static const size_t object_sizes[] = {
};
-uint32_t git_object_hash(const void *key)
+uint32_t git__objtable_hash(const void *key)
{
uint32_t r;
git_oid *id;
@@ -53,7 +54,7 @@ uint32_t git_object_hash(const void *key)
return r;
}
-int git_object_haskey(void *object, const void *key)
+int git__objtable_haskey(void *object, const void *key)
{
git_object *obj;
git_oid *oid;
@@ -64,7 +65,62 @@ int git_object_haskey(void *object, const void *key)
return (git_oid_cmp(oid, &obj->id) == 0);
}
-git_repository *git_repository_alloc(git_odb *odb)
+static int parse_repository_folders(git_repository *repo, const char *repository_path)
+{
+ char path_aux[GIT_PATH_MAX];
+ int path_len, i;
+
+ if (gitfo_isdir(repository_path) < 0)
+ return GIT_ERROR;
+
+ path_len = strlen(repository_path);
+ strcpy(path_aux, repository_path);
+
+ if (path_aux[path_len - 1] != '/') {
+ path_aux[path_len] = '/';
+ path_aux[path_len + 1] = 0;
+
+ path_len = path_len + 1;
+ }
+
+ repo->path_repository = git__strdup(path_aux);
+
+ /* objects database */
+ strcpy(path_aux + path_len, "objects/");
+ if (gitfo_isdir(path_aux) < 0)
+ return GIT_ERROR;
+ repo->path_odb = git__strdup(path_aux);
+
+ /* index file */
+ strcpy(path_aux + path_len, "index");
+ if (gitfo_exists(path_aux) < 0)
+ return GIT_ERROR;
+ repo->path_index = git__strdup(path_aux);
+
+ /* HEAD file */
+ strcpy(path_aux + path_len, "HEAD");
+ if (gitfo_exists(path_aux) < 0)
+ return GIT_ERROR;
+
+ i = path_len - 2;
+ while (path_aux[i] != '/')
+ i--;
+
+ if (strcmp(path_aux, "/.git/") == 0) {
+ repo->is_bare = 0;
+
+ path_aux[i + 1] = 0;
+ repo->path_workdir = git__strdup(path_aux);
+
+ } else {
+ repo->is_bare = 1;
+ repo->path_workdir = NULL;
+ }
+
+ return GIT_SUCCESS;
+}
+
+git_repository *git_repository__alloc()
{
git_repository *repo = git__malloc(sizeof(git_repository));
if (!repo)
@@ -74,15 +130,30 @@ git_repository *git_repository_alloc(git_odb *odb)
repo->objects = git_hashtable_alloc(
default_table_size,
- git_object_hash,
- git_object_haskey);
+ git__objtable_hash,
+ git__objtable_haskey);
if (repo->objects == NULL) {
free(repo);
return NULL;
}
- repo->db = odb; /* TODO: create ODB manually! */
+ return repo;
+}
+
+git_repository *git_repository_open(const char *path)
+{
+ git_repository *repo;
+
+ repo = git_repository__alloc();
+ if (repo == NULL)
+ return NULL;
+
+ if (parse_repository_folders(repo, path) < 0 ||
+ git_odb_open(&repo->db, repo->path_odb) < 0) {
+ git_repository_free(repo);
+ return NULL;
+ }
return repo;
}
@@ -92,6 +163,11 @@ void git_repository_free(git_repository *repo)
git_hashtable_iterator it;
git_object *object;
+ free(repo->path_workdir);
+ free(repo->path_index);
+ free(repo->path_repository);
+ free(repo->path_odb);
+
git_hashtable_iterator_init(repo->objects, &it);
while ((object = (git_object *)
@@ -99,10 +175,21 @@ void git_repository_free(git_repository *repo)
git_object_free(object);
git_hashtable_free(repo->objects);
- /* TODO: free odb */
+ git_odb_close(repo->db);
+ git_index_free(repo->index);
free(repo);
}
+git_index *git_repository_index(git_repository *repo)
+{
+ if (repo->index == NULL) {
+ repo->index = git_index_alloc(repo->path_index, repo->path_workdir);
+ assert(repo->index && repo->index->on_disk);
+ }
+
+ return repo->index;
+}
+
static int source_resize(git_odb_source *src)
{
size_t write_offset, new_size;