summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/errors.c5
-rw-r--r--src/git2/common.h14
-rw-r--r--src/git2/repository.h16
-rw-r--r--src/git2/types.h16
-rw-r--r--src/refs.c547
-rw-r--r--src/refs.h48
-rw-r--r--src/repository.c29
-rw-r--r--src/repository.h2
8 files changed, 670 insertions, 7 deletions
diff --git a/src/errors.c b/src/errors.c
index 41c4a8d3a..34a15b258 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -20,6 +20,11 @@ static struct {
{GIT_EZLIB, "The Z library failed to inflate/deflate an object's data"},
{GIT_EBUSY, "The queried object is currently busy"},
{GIT_EINVALIDPATH, "The path is invalid"},
+ {GIT_EBAREINDEX, "The index file is not backed up by an existing repository"},
+ {GIT_EINVALIDREFNAME, "The name of the reference is not valid"},
+ {GIT_EREFCORRUPTED, "The specified reference has its data corrupted"},
+ {GIT_ETOONESTEDSYMREF, "The specified symbolic reference is too deeply nested"},
+ {GIT_EPACKEDREFSCORRUPTED, "The pack-refs file is either corrupted of its format is not currently supported"}
};
const char *git_strerror(int num)
diff --git a/src/git2/common.h b/src/git2/common.h
index 350429f5c..aae707cb6 100644
--- a/src/git2/common.h
+++ b/src/git2/common.h
@@ -134,7 +134,19 @@
#define GIT_EBUSY (GIT_ERROR - 13)
/** The index file is not backed up by an existing repository */
-#define GIT_EBAREINDEX (GIT_ERROR -14)
+#define GIT_EBAREINDEX (GIT_ERROR - 14)
+
+/** The name of the reference is not valid */
+#define GIT_EINVALIDREFNAME (GIT_ERROR - 15)
+
+/** The specified reference has its data corrupted */
+#define GIT_EREFCORRUPTED (GIT_ERROR - 16)
+
+/** The specified symbolic reference is too deeply nested */
+#define GIT_ETOONESTEDSYMREF (GIT_ERROR - 17)
+
+/** The pack-refs file is either corrupted of its format is not currently supported */
+#define GIT_EPACKEDREFSCORRUPTED (GIT_ERROR - 18)
/** The path is invalid */
#define GIT_EINVALIDPATH (GIT_ERROR - 19)
diff --git a/src/git2/repository.h b/src/git2/repository.h
index 37a541f24..129d3bb5f 100644
--- a/src/git2/repository.h
+++ b/src/git2/repository.h
@@ -215,6 +215,22 @@ GIT_EXTERN(void) git_repository_free(git_repository *repo);
*/
GIT_EXTERN(int) git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare);
+/**
+ * Lookup a reference by its name in the repository.
+ *
+ * The generated reference is owned by the repository and
+ * should not be freed by the user.
+ *
+ * TODO:
+ * - Ensure the reference name is valid
+ *
+ * @param reference_out pointer to the looked-up reference
+ * @param repo the repository to look up the reference
+ * @param name the long name for the reference (e.g. HEAD, ref/heads/master, refs/tags/v0.1.0, ...)
+ * @return a reference to the reference
+ */
+GIT_EXTERN(int) git_repository_reference_lookup(git_reference **reference_out, git_repository *repo, const char *name);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/src/git2/types.h b/src/git2/types.h
index cfc0cf379..389f32868 100644
--- a/src/git2/types.h
+++ b/src/git2/types.h
@@ -135,6 +135,22 @@ typedef struct git_signature {
git_time when; /** time when the action happened */
} git_signature;
+/** In-memory representation of a reference. */
+typedef struct git_reference git_reference;
+
+/** In-memory representation of a reference to an object id. */
+typedef struct git_reference_object_id git_reference_object_id;
+
+/** In-memory representation of a reference which points at another reference. The target reference is embedded. */
+typedef struct git_reference_symbolic git_reference_symbolic;
+
+/** Basic type of any Git reference. */
+typedef enum {
+ GIT_REF_ANY = -2, /** Reference can be any of the following */
+ GIT_REF_OBJECT_ID = 0, /** A reference which points at an object id */
+ GIT_REF_SYMBOLIC = 1, /** A reference which points at another reference */
+} git_rtype;
+
/** @} */
GIT_END_DECL
diff --git a/src/refs.c b/src/refs.c
new file mode 100644
index 000000000..91f13aed0
--- /dev/null
+++ b/src/refs.c
@@ -0,0 +1,547 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file. (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "refs.h"
+#include "hash.h"
+#include "repository.h"
+#include "fileops.h"
+
+#define HASH_SEED 2147483647
+#define MAX_NESTING_LEVEL 5
+
+static const int default_table_size = 32;
+
+static struct {
+ size_t size; /* size in bytes of the object structure */
+} git_references_table[] = {
+ {sizeof(git_reference_object_id)}, /* 0 = GIT_REF_OBJECT_ID */
+ {sizeof(git_reference_symbolic)}, /* 1 = GIT_REF_SYMBOLIC */
+};
+
+static uint32_t reftable_hash(const void *key)
+{
+ return git__hash(key, strlen((const char *)key), HASH_SEED);
+}
+
+static int reftable_haskey(void *reference, const void *key)
+{
+ git_reference *ref;
+ char *name;
+
+ ref = (git_reference *)reference;
+ name = (char *)key;
+
+ return strcmp(name, ref->name) == 0;
+}
+
+git_reference_database *git_reference_database__alloc()
+{
+ git_reference_database *ref_database = git__malloc(sizeof(git_reference_database));
+ if (!ref_database)
+ return NULL;
+
+ memset(ref_database, 0x0, sizeof(git_reference_database));
+
+ ref_database->references = git_hashtable_alloc(
+ default_table_size,
+ reftable_hash,
+ reftable_haskey);
+
+ if (ref_database->references == NULL) {
+ free(ref_database);
+ return NULL;
+ }
+
+ return ref_database;
+}
+
+static void reference__free(git_reference *reference)
+{
+ assert(reference);
+
+ switch (reference->type) {
+ case GIT_REF_SYMBOLIC:
+ // The target of the symbolic ref has to be freed by itself.
+
+ /* Fallthrough */
+
+ case GIT_REF_ANY:
+ case GIT_REF_OBJECT_ID:
+ if (reference->name)
+ free(reference->name);
+
+ /* Fallthrough */
+
+ default:
+ free(reference);
+ break;
+ }
+}
+
+void git_reference_database__free(git_reference_database *ref_database)
+{
+ git_hashtable_iterator it;
+ git_reference *reference;
+
+ assert(ref_database);
+
+ git_hashtable_iterator_init(ref_database->references, &it);
+
+ while ((reference = (git_reference *)git_hashtable_iterator_next(&it)) != NULL) {
+ git_hashtable_remove(ref_database->references, reference->name);
+ reference__free(reference);
+ }
+
+ git_hashtable_free(ref_database->references);
+ free(ref_database);
+}
+
+
+static int check_refname_validity(const char *name) {
+ int error = GIT_SUCCESS;
+
+ // TODO : To be implemented
+
+ return error;
+}
+
+static int reference_newobject(git_reference **reference_out, git_rtype type, const char *name)
+{
+ git_reference *reference = NULL;
+
+ assert(reference_out && name);
+
+ *reference_out = NULL;
+
+ switch (type) {
+ case GIT_REF_OBJECT_ID:
+ case GIT_REF_SYMBOLIC:
+ break;
+
+ default:
+ return GIT_EINVALIDTYPE;
+ }
+
+ reference = git__malloc(git_references_table[type].size);
+
+ if (reference == NULL)
+ return GIT_ENOMEM;
+
+ memset(reference, 0x0, git_references_table[type].size);
+
+ reference->name = git__malloc(strlen(name) + 1);
+ strcpy(reference->name, name);
+
+ reference->type = type;
+
+
+ *reference_out = reference;
+
+ return GIT_SUCCESS;
+}
+
+static int symbolic_reference_target_name__parse(char *target_name_out, const char *name, gitfo_buf *buffer) {
+ int error = GIT_SUCCESS;
+ char *refname_start, *refname_end;
+ const char *buffer_end;
+ int refname_len;
+
+ refname_start = (char *)buffer->data;
+ buffer_end = (const char *)(buffer->data) + buffer->len;
+
+ if (git__prefixcmp(refname_start, GIT_SYMREF))
+ return GIT_EREFCORRUPTED;
+
+ refname_start += strlen(GIT_SYMREF);
+
+ /* Skip the potential white spaces */
+ while (isspace(refname_start[0]) && refname_start < buffer_end)
+ refname_start++;
+
+ refname_end = refname_start;
+
+ /* Seek the end of the target reference name */
+ while(!isspace(refname_end[0]) && refname_end < buffer_end)
+ refname_end++;
+
+ refname_len = refname_end - refname_start;
+
+ memcpy(target_name_out, refname_start, refname_len);
+ target_name_out[refname_len] = 0;
+
+ return error;
+}
+
+static int object_id_reference__parse(git_reference **reference_out, const char *name, gitfo_buf *buffer) {
+ int error = GIT_SUCCESS;
+ git_oid target_oid;
+ git_reference *reference;
+ char *buffer_start;
+ const char *buffer_end;
+
+ buffer_start = (char *)buffer->data;
+ buffer_end = (const char *)(buffer_start) + buffer->len;
+
+ /* Is this a valid object id ? */
+ error = git__parse_oid(&target_oid, &buffer_start, buffer_end, "");
+ if (error < GIT_SUCCESS)
+ return error;
+
+ error = reference_newobject(&reference, GIT_REF_OBJECT_ID, name);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ git_oid_cpy(&((git_reference_object_id *)reference)->id, &target_oid);
+
+ *reference_out = reference;
+
+ return error;
+}
+
+static int read_loose_reference(gitfo_buf *file_content, const char *name, const char *path_repository)
+{
+ int error = GIT_SUCCESS;
+ char ref_path[GIT_PATH_MAX];
+
+ /* Determine the full path of the ref */
+ strcpy(ref_path, path_repository);
+ strcat(ref_path, name);
+
+ /* Does it even exist ? */
+ if (gitfo_exists(ref_path) < GIT_SUCCESS)
+ return GIT_ENOTFOUND;
+
+ /* A ref can not be a directory */
+ if (!gitfo_isdir(ref_path))
+ return GIT_EINVALIDREFNAME;
+
+ error = gitfo_read_file(file_content, ref_path);
+
+ return error;
+}
+
+static int try_to_find_an_existing_loose_reference(git_reference **reference_out, git_reference_database *ref_database, const char *name, const char *path_repository, int *nesting_level)
+{
+ int error = GIT_SUCCESS;
+ gitfo_buf file_content = GITFO_BUF_INIT;
+ git_reference *reference, *target_reference;
+ git_reference_symbolic *peeled_reference;
+ char target_name[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
+
+
+ error = read_loose_reference(&file_content, name, path_repository);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ /* Does this look like a symbolic ref ? */
+ if (!git__prefixcmp((const char *)(file_content.data), GIT_SYMREF)) {
+ error = symbolic_reference_target_name__parse(target_name, name, &file_content);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ error = git_reference_lookup(&target_reference, ref_database, target_name, path_repository, nesting_level);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ error = reference_newobject((git_reference **)&peeled_reference, GIT_REF_SYMBOLIC, name);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ peeled_reference->target = target_reference;
+
+ reference = (git_reference *)peeled_reference;
+
+ goto found;
+ }
+
+ if (object_id_reference__parse(&reference, name, &file_content) < GIT_SUCCESS) {
+ error = GIT_EREFCORRUPTED;
+ goto cleanup;
+ }
+
+found:
+ *reference_out = reference;
+
+cleanup:
+ if (file_content.data)
+ gitfo_free_buf(&file_content);
+
+ return error;
+}
+
+static int read_packed_refs_content(gitfo_buf *file_content, const char *path_repository)
+{
+ int error = GIT_SUCCESS;
+ char ref_path[GIT_PATH_MAX];
+
+ /* Determine the full path of the file */
+ strcpy(ref_path, path_repository);
+ strcat(ref_path, GIT_PACKEDREFS_FILE);
+
+ /* Does it even exist ? */
+ if (gitfo_exists(ref_path) < GIT_SUCCESS)
+ return GIT_ENOTFOUND;
+
+ error = gitfo_read_file(file_content, ref_path);
+
+ return error;
+}
+
+static int packed_tag_peeled_reference__parse(git_oid *peeled_oid_out, git_reference *tag_reference, char** buffer_out, const char *buffer_end)
+{
+ int error = GIT_SUCCESS;
+
+ /* Ensure it's not the first entry of the file */
+ if (tag_reference == NULL)
+ return GIT_EPACKEDREFSCORRUPTED;
+
+ /* Ensure reference is a tag */
+ if (git__prefixcmp(tag_reference->name, GIT_REFS_TAGS_DIR))
+ return GIT_EPACKEDREFSCORRUPTED;
+
+ /* Is this a valid object id ? */
+ if (git__parse_oid(peeled_oid_out, buffer_out, buffer_end, "^") < GIT_SUCCESS) {
+ error = GIT_EPACKEDREFSCORRUPTED;
+ }
+
+ return error;
+}
+
+static int packed_reference__parse(git_oid *oid_out, char *reference_name_out, char** buffer_out, const char *buffer_end)
+{
+ int error = GIT_SUCCESS;
+ char *refname_end;
+ int refname_len;
+
+ /* This should be the beginning of a line containing an object id, a space and its name */
+ if ((*buffer_out + GIT_OID_HEXSZ)[0] != ' ')
+ return GIT_EPACKEDREFSCORRUPTED;
+
+ /* Slight hack to reuse git__parse_oid() which assumes that the id is LF terminated */
+ (*buffer_out + GIT_OID_HEXSZ)[0] = '\n';
+
+ /* Is this a valid object id ? */
+ if (git__parse_oid(oid_out, buffer_out, buffer_end, "") < GIT_SUCCESS)
+ return GIT_EPACKEDREFSCORRUPTED;
+
+ /* We should be at the begining of the name of the reference */
+ if (isspace(*buffer_out[0]))
+ return GIT_EPACKEDREFSCORRUPTED;
+
+ refname_end = *buffer_out;
+
+ /* Seek the end of the target reference name */
+ while(!isspace(refname_end[0]) && refname_end < buffer_end)
+ refname_end++;
+
+ refname_len = refname_end - *buffer_out;
+
+ memcpy(reference_name_out, *buffer_out, refname_len);
+ reference_name_out[refname_len] = 0;
+
+ *buffer_out = refname_end + 1;
+
+ return error;
+}
+
+static int packed_reference_file__parse(git_reference **reference_out, git_reference_database *ref_database, const char *name, const char *path_repository, int *nesting_level)
+{
+ int error = GIT_SUCCESS;
+ gitfo_buf file_content = GITFO_BUF_INIT;
+ char *buffer_start;
+ const char *buffer_end;
+ char reference_name[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
+ git_oid oid, peeled_oid;
+ git_reference *reference = NULL, *found_reference = NULL;
+
+ error = read_packed_refs_content(&file_content, path_repository);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ buffer_start = (char *)file_content.data;
+ buffer_end = (const char *)(buffer_start) + file_content.len;
+
+ /* Does the header look like valid ? */
+ if (git__prefixcmp((const char *)(buffer_start), GIT_PACKEDREFS_HEADER)) {
+ error = GIT_EPACKEDREFSCORRUPTED;
+ goto cleanup;
+ }
+
+ /* Let's skip the header */
+ buffer_start += strlen(GIT_PACKEDREFS_HEADER);
+
+ while (buffer_start < buffer_end) {
+ /* Is it a peeled reference pointed at by a tag ? */
+ if (buffer_start[0] == '^') {
+ error = packed_tag_peeled_reference__parse(&peeled_oid, reference, &buffer_start, buffer_end);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ /* As we do not _currently_ need the peeled object pointed at by the tag, we just don't use the parsed object id. Maybe later ? */
+
+ /* Reinit the reference to catch potential successive lines starting by '^' */
+ reference = NULL;
+
+ continue;
+ }
+
+ error = packed_reference__parse(&oid, reference_name, &buffer_start, buffer_end);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ /* Does a more up-to-date loose reference exist ? */
+ reference = git_hashtable_lookup(ref_database->references, reference_name);
+ if (reference == NULL) {
+ error = reference_newobject(&reference, GIT_REF_OBJECT_ID, reference_name);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ reference->is_packed = 1;
+
+ git_oid_cpy(&((git_reference_object_id *)reference)->id, &oid);
+
+ git_hashtable_insert(ref_database->references, reference->name, reference);
+
+ /* Is it the reference we're looking for ? */
+ if (!strcmp(reference_name, name))
+ found_reference = reference; // TODO : Should we guard against two found references in the same packed-refs file ?
+ }
+ }
+
+ ref_database->have_packed_refs_been_parsed = 1;
+
+ if (found_reference == NULL) {
+ error = GIT_ENOTFOUND;
+ goto cleanup;
+ }
+
+ *reference_out = found_reference;
+
+cleanup:
+ if (file_content.data)
+ gitfo_free_buf(&file_content);
+
+ return error;
+}
+
+int git_reference_lookup(git_reference **reference_out, git_reference_database *ref_database, const char *name, const char *path_repository, int *nesting_level)
+{
+ int error = GIT_SUCCESS;
+ git_reference *reference, *packed_reference = NULL;
+
+ if (*nesting_level == MAX_NESTING_LEVEL) {
+ return GIT_ETOONESTEDSYMREF;
+ }
+
+ error = check_refname_validity(name);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ /* Has the ref already been previously parsed ? */
+ reference = git_hashtable_lookup(ref_database->references, name);
+
+ /* Has a loose reference been found ? */
+ if (reference != NULL && !reference->is_packed) {
+ *reference_out = reference;
+ return GIT_SUCCESS;
+ }
+
+ /* Has every available ref already been parsed ? */
+ if (ref_database->is_fully_loaded) {
+
+ if (reference == NULL) {
+ return GIT_ENOTFOUND;
+ } else {
+ /* Is is safe to consider the packed reference as the most up-to-date reference */
+ assert(reference->is_packed);
+ *reference_out = reference;
+ return GIT_SUCCESS;
+ }
+ }
+
+ /* We temporarily store the packed reference until we're sure no more up-to-date loose reference exists. */
+ if (reference != NULL) {
+ assert(reference->is_packed);
+ packed_reference = reference;
+ }
+
+ if (*nesting_level == 0) {
+ /* Is the database being populated */
+ if (ref_database->is_busy)
+ return GIT_EBUSY;
+
+ ref_database->is_busy = 1;
+ }
+
+ (*nesting_level)++;
+
+ /* Does the reference exist as a loose file based reference ? */
+ error = try_to_find_an_existing_loose_reference(&reference, ref_database, name, path_repository, nesting_level);
+
+ /* Have we found a more up-to-date loose reference than the packed reference we stored ? */
+ if (error == GIT_SUCCESS && packed_reference != NULL) {
+ git_hashtable_remove(ref_database->references, packed_reference->name);
+ reference__free(packed_reference);
+ }
+
+ if (error == GIT_SUCCESS) {
+ git_hashtable_insert(ref_database->references, reference->name, reference);
+ goto found;
+ }
+
+ if (error != GIT_ENOTFOUND)
+ goto cleanup;
+
+ /* Nothing has been found in the loose refs */
+ assert(error == GIT_ENOTFOUND);
+
+ /* If we've stored a pack reference, now is the time to return it */
+ if (packed_reference != NULL) {
+ reference = packed_reference;
+ error = GIT_SUCCESS;
+ goto found;
+ }
+
+ /* Have the dormant references already been parsed ? */
+ if (ref_database->have_packed_refs_been_parsed)
+ return GIT_ENOTFOUND;
+
+ /* has the reference previously been packed ? */
+ error = packed_reference_file__parse(&reference, ref_database, name, path_repository, nesting_level);
+ if (error < GIT_SUCCESS) {
+ goto cleanup;
+ }
+
+found:
+ *reference_out = reference;
+
+cleanup:
+ (*nesting_level)--;
+
+ if (*nesting_level == 0)
+ ref_database->is_busy = 0;
+
+ return error;
+}
diff --git a/src/refs.h b/src/refs.h
new file mode 100644
index 000000000..3cfd46d58
--- /dev/null
+++ b/src/refs.h
@@ -0,0 +1,48 @@
+#ifndef INCLUDE_refs_h__
+#define INCLUDE_refs_h__
+
+#include "common.h"
+#include "git2/oid.h"
+#include "hashtable.h"
+
+#define GIT_REFS_DIR "refs/"
+#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
+#define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/"
+
+#define GIT_SYMREF "ref:"
+#define GIT_PACKEDREFS_FILE "packed-refs"
+#define GIT_PACKEDREFS_HEADER "# pack-refs with: peeled \n"
+#define MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH 100
+
+struct git_reference {
+ git_rtype type;
+ char *name;
+
+ unsigned is_packed:1;
+};
+
+struct git_reference_object_id {
+ git_reference base;
+
+ git_oid id;
+};
+
+struct git_reference_symbolic {
+ git_reference base;
+
+ git_reference *target;
+};
+
+typedef struct {
+ git_hashtable *references;
+
+ unsigned is_fully_loaded:1;
+ unsigned have_packed_refs_been_parsed:1;
+ unsigned is_busy:1;
+} git_reference_database;
+
+git_reference_database *git_reference_database__alloc();
+void git_reference_database__free(git_reference_database *ref_database);
+int git_reference_lookup(git_reference **reference_out, git_reference_database *ref_database, const char *name, const char *path_repository, int *nesting_level);
+
+#endif \ No newline at end of file
diff --git a/src/repository.c b/src/repository.c
index 349afba9f..6fc67e409 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -33,18 +33,16 @@
#include "blob.h"
#include "fileops.h"
+#include "refs.h"
+
#define GIT_DIR "/.git/"
#define GIT_OBJECTS_DIR "objects/"
#define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/"
#define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
-#define GIT_REFS_DIR "refs/"
-#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
-#define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/"
#define GIT_INDEX_FILE "index"
#define GIT_HEAD_FILE "HEAD"
-#define GIT_SYMREF "ref: "
#define GIT_BRANCH_MASTER "master"
static const int OBJECT_TABLE_SIZE = 32;
@@ -229,6 +227,13 @@ static git_repository *repository_alloc()
return NULL;
}
+ repo->ref_database = git_reference_database__alloc();
+ if (repo->ref_database == NULL) {
+ git_hashtable_free(repo->objects);
+ free(repo);
+ return NULL;
+ }
+
return repo;
}
@@ -359,6 +364,8 @@ void git_repository_free(git_repository *repo)
git_hashtable_free(repo->objects);
+ git_reference_database__free(repo->ref_database);
+
if (repo->db != NULL)
git_odb_close(repo->db);
@@ -579,8 +586,6 @@ static int repo_init_structure(repo_init *results)
static int repo_init_find_dir(repo_init *results, const char* path)
{
- const int MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH = 66;
-
char temp_path[GIT_PATH_MAX];
int path_len;
int error = GIT_SUCCESS;
@@ -628,3 +633,15 @@ cleanup:
free(results.path_repository);
return error;
}
+
+int git_repository_reference_lookup(git_reference **reference_out, git_repository *repo, const char *name)
+{
+ int error = GIT_SUCCESS;
+ int nesting_level = 0;
+
+ assert(repo && reference_out && name);
+
+ error = git_reference_lookup(reference_out, repo->ref_database, name, repo->path_repository, &nesting_level);
+
+ return error;
+}
diff --git a/src/repository.h b/src/repository.h
index 44b37e1d0..1e9e0a5b9 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -8,6 +8,7 @@
#include "hashtable.h"
#include "index.h"
+#include "refs.h"
typedef struct {
git_rawobj raw;
@@ -27,6 +28,7 @@ struct git_repository {
git_odb *db;
git_index *index;
git_hashtable *objects;
+ git_reference_database *ref_database;
char *path_repository;
char *path_index;