summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2010-11-02 18:42:42 +0200
committerVicent Marti <tanoku@gmail.com>2010-11-02 18:42:42 +0200
commit6fd195d76c7f52baae5540e287affe2259900d36 (patch)
tree4dd644c5086dce17827f42b8c811049175da88f9 /src
parentd80e9d55aa2d0629f7f207db42762494075d7854 (diff)
downloadlibgit2-6fd195d76c7f52baae5540e287affe2259900d36.tar.gz
Change git_repository initialization to use a path
The constructor to git_repository is now called 'git_repository_open(path)' and takes a path to a git repository instead of an existing ODB object. Unit tests have been updated accordingly and the two test repositories have been merged into one. Signed-off-by: Vicent Marti <tanoku@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/fileops.c7
-rw-r--r--src/fileops.h1
-rw-r--r--src/git/index.h50
-rw-r--r--src/git/repository.h33
-rw-r--r--src/index.c18
-rw-r--r--src/index.h27
-rw-r--r--src/repository.c101
-rw-r--r--src/repository.h9
8 files changed, 205 insertions, 41 deletions
diff --git a/src/fileops.c b/src/fileops.c
index f101cec32..e0a5ff461 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -53,6 +53,13 @@ int gitfo_write(git_file fd, void *buf, size_t cnt)
return GIT_SUCCESS;
}
+int gitfo_isdir(const char *path)
+{
+ struct stat st;
+ return (path && gitfo_stat(path, &st) == 0 && S_ISDIR(st.st_mode)) ?
+ GIT_SUCCESS : GIT_ENOTFOUND;
+}
+
int gitfo_exists(const char *path)
{
return access(path, F_OK);
diff --git a/src/fileops.h b/src/fileops.h
index 2da4231d0..618bddd5b 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -57,6 +57,7 @@ typedef struct { /* file io buffer */
extern int gitfo_exists(const char *path);
extern int gitfo_open(const char *path, int flags);
extern int gitfo_creat(const char *path, int mode);
+extern int gitfo_isdir(const char *path);
#define gitfo_close(fd) close(fd)
extern int gitfo_read(git_file fd, void *buf, size_t cnt);
diff --git a/src/git/index.h b/src/git/index.h
index 46fccbd74..3b262355e 100644
--- a/src/git/index.h
+++ b/src/git/index.h
@@ -1,6 +1,7 @@
#ifndef INCLUDE_git_index_h__
#define INCLUDE_git_index_h__
+#include <stdint.h>
#include "common.h"
#include "oid.h"
@@ -16,18 +17,50 @@ GIT_BEGIN_DECL
/** Memory representation of an index file. */
typedef struct git_index git_index;
+
+/** Time used in a git index entry */
+typedef struct {
+ uint32_t seconds;
+ uint32_t nanoseconds;
+} git_index_time;
+
/** Memory representation of a file entry in the index. */
-typedef struct git_index_entry git_index_entry;
+typedef struct git_index_entry {
+ git_index_time ctime;
+ git_index_time mtime;
+
+ uint32_t dev;
+ uint32_t ino;
+ uint32_t mode;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t file_size;
+
+ git_oid oid;
+
+ uint16_t flags;
+ uint16_t flags_extended;
+
+ char *path;
+} git_index_entry;
/**
* Create a new Git index object as a memory representation
* of the Git index file in 'index_path'.
*
+ * The argument 'working_dir' is the root path of the indexed
+ * files in the index and is used to calculate the relative path
+ * when inserting new entries from existing files on disk.
+ *
+ * If 'working _dir' is NULL (e.g for bare repositories), the
+ * methods working on on-disk files will fail.
+ *
* @param index_path the path to the index file in disk
+ * @param working_dir working dir for the git repository
* @return the index object; NULL if the index could not be created
*/
-GIT_EXTERN(git_index *) git_index_alloc(const char *index_path);
+GIT_EXTERN(git_index *) git_index_alloc(const char *index_path, const char *working_dir);
/**
* Clear the contents (all the entries) of an index object.
@@ -83,6 +116,19 @@ GIT_EXTERN(int) git_index_find(git_index *index, const char *path);
*/
GIT_EXTERN(int) git_index_add(git_index *index, const char *path, int stage);
+/**
+ * Get a pointer to one of the entries in the index
+ *
+ * This entry can be modified, and the changes will be written
+ * back to disk on the next write() call.
+ *
+ * @param index an existing index object
+ * @param n the position of the entry
+ * @return a pointer to the entry; NULL if out of bounds
+ */
+GIT_EXTERN(git_index_entry *) git_index_get(git_index *index, int n);
+
+
/** @} */
GIT_END_DECL
#endif
diff --git a/src/git/repository.h b/src/git/repository.h
index 0a50fe1ef..058849b7f 100644
--- a/src/git/repository.h
+++ b/src/git/repository.h
@@ -4,6 +4,7 @@
#include "common.h"
#include "odb.h"
#include "commit.h"
+#include "index.h"
/**
* @file git/repository.h
@@ -15,15 +16,28 @@
GIT_BEGIN_DECL
/**
- * Allocate a new repository object.
+ * Open a git repository.
*
- * TODO: specify the repository's path instead
- * of its object database
+ * The 'path' argument must point to an existing git repository
+ * folder, e.g.
*
- * @param odb an existing object database to back the repo
+ * /path/to/my_repo/.git/ (normal repository)
+ * objects/
+ * index
+ * HEAD
+ *
+ * /path/to/bare_repo/ (bare repository)
+ * objects/
+ * index
+ * HEAD
+ *
+ * The method will automatically detect if 'path' is a normal
+ * or bare repository or fail is 'path' is neither.
+ *
+ * @param path the path to the repository
* @return the new repository handle; NULL on error
*/
-GIT_EXTERN(git_repository *) git_repository_alloc(git_odb *odb);
+GIT_EXTERN(git_repository *) git_repository_open(const char *path);
/**
@@ -58,6 +72,15 @@ GIT_EXTERN(git_object *) git_repository_lookup(git_repository *repo, const git_o
GIT_EXTERN(git_odb *) git_repository_database(git_repository *repo);
/**
+ * Get the Index file of a Git repository
+ *
+ * @param repo a repository object
+ * @return a pointer to the Index object;
+ * NULL if the index cannot be opened
+ */
+GIT_EXTERN(git_index *) git_repository_index(git_repository *rpeo);
+
+/**
* Create a new in-memory repository object with
* the given type.
*
diff --git a/src/index.c b/src/index.c
index 991f1b126..9996c50fe 100644
--- a/src/index.c
+++ b/src/index.c
@@ -97,7 +97,7 @@ 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 *);
-git_index *git_index_alloc(const char *index_path)
+git_index *git_index_alloc(const char *index_path, const char *work_dir)
{
git_index *index;
@@ -116,6 +116,9 @@ git_index *git_index_alloc(const char *index_path)
return NULL;
}
+ if (work_dir != NULL)
+ index->working_path = git__strdup(work_dir);
+
/* Check if index file is stored on disk already */
if (gitfo_exists(index->index_file_path) == 0)
index->on_disk = 1;
@@ -126,6 +129,9 @@ git_index *git_index_alloc(const char *index_path)
void git_index_clear(git_index *index)
{
unsigned int i;
+
+ assert(index);
+
for (i = 0; i < index->entry_count; ++i)
free(index->entries[i].path);
@@ -139,6 +145,9 @@ void git_index_clear(git_index *index)
void git_index_free(git_index *index)
{
+ if (index == NULL)
+ return;
+
git_index_clear(index);
free(index->entries);
index->entries = NULL;
@@ -213,6 +222,11 @@ int git_index_write(git_index *index)
return 0;
}
+git_index_entry *git_index_get(git_index *index, int n)
+{
+ return (n >= 0 && (unsigned int)n < index->entry_count) ? &index->entries[n] : NULL;
+}
+
int git_index_add(git_index *index, const char *filename, int stage)
{
git_index_entry entry;
@@ -225,7 +239,7 @@ int git_index_add(git_index *index, const char *filename, int stage)
if (path_length < GIT_IDXENTRY_NAMEMASK)
entry.flags |= path_length;
else
- entry.flags |= path_length;
+ entry.flags |= GIT_IDXENTRY_NAMEMASK;;
if (stage < 0 || stage > 3)
return GIT_ERROR;
diff --git a/src/index.h b/src/index.h
index 44da78f9b..6a3c11e82 100644
--- a/src/index.h
+++ b/src/index.h
@@ -12,31 +12,6 @@
#define GIT_IDXENTRY_VALID (0x8000)
#define GIT_IDXENTRY_STAGESHIFT 12
-typedef struct {
- uint32_t seconds;
- uint32_t nanoseconds;
-} git_index_time;
-
-struct git_index_entry {
- git_index_time ctime;
- git_index_time mtime;
-
- uint32_t dev;
- uint32_t ino;
- uint32_t mode;
- uint32_t uid;
- uint32_t gid;
- uint32_t file_size;
-
- git_oid oid;
-
- uint16_t flags;
- uint16_t flags_extended;
-
- char *path;
-};
-
-
struct git_index_tree {
char *name;
@@ -53,6 +28,8 @@ typedef struct git_index_tree git_index_tree;
struct git_index {
char *index_file_path;
+ char *working_path;
+
time_t last_modified;
git_index_entry *entries;
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;
diff --git a/src/repository.h b/src/repository.h
index 0ccfc5e92..ca76d4558 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -7,6 +7,7 @@
#include "git/repository.h"
#include "hashtable.h"
+#include "index.h"
typedef struct {
git_rawobj raw;
@@ -24,7 +25,15 @@ struct git_object {
struct git_repository {
git_odb *db;
+ git_index *index;
git_hashtable *objects;
+
+ char *path_repository;
+ char *path_index;
+ char *path_odb;
+ char *path_workdir;
+
+ unsigned is_bare:1;
};