diff options
author | Vicent Marti <tanoku@gmail.com> | 2010-11-02 18:42:42 +0200 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2010-11-02 18:42:42 +0200 |
commit | 6fd195d76c7f52baae5540e287affe2259900d36 (patch) | |
tree | 4dd644c5086dce17827f42b8c811049175da88f9 /src | |
parent | d80e9d55aa2d0629f7f207db42762494075d7854 (diff) | |
download | libgit2-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.c | 7 | ||||
-rw-r--r-- | src/fileops.h | 1 | ||||
-rw-r--r-- | src/git/index.h | 50 | ||||
-rw-r--r-- | src/git/repository.h | 33 | ||||
-rw-r--r-- | src/index.c | 18 | ||||
-rw-r--r-- | src/index.h | 27 | ||||
-rw-r--r-- | src/repository.c | 101 | ||||
-rw-r--r-- | src/repository.h | 9 |
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; }; |