summaryrefslogtreecommitdiff
path: root/src/repository.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/repository.c')
-rw-r--r--src/repository.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/repository.c b/src/repository.c
index 098d09858..94f67f497 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -35,9 +35,15 @@
#define GIT_FOLDER "/.git/"
#define GIT_OBJECTS_FOLDER "objects/"
+#define GIT_REFS_FOLDER "refs/"
#define GIT_INDEX_FILE "index"
#define GIT_HEAD_FILE "HEAD"
+#define GIT_SYMREF "ref: "
+#define GIT_REFS_HEADS "refs/heads/"
+#define GIT_REFS_TAGS "refs/tags/"
+#define GIT_BRANCH_MASTER "master"
+
static const int default_table_size = 32;
static const double max_load_factor = 0.65;
@@ -58,6 +64,13 @@ static struct {
{ "REF_DELTA", 0, 0 } /* 7 = GIT_OBJ_REF_DELTA */
};
+typedef struct git_repository_init_results {
+ char *path_repository;
+
+ unsigned is_bare:1;
+ unsigned has_been_reinit:1;
+} git_repository_init_results;
+
/***********************************************************
*
* MISCELANEOUS HELPER FUNCTIONS
@@ -722,3 +735,146 @@ int git_object_typeisloose(git_otype type)
return git_objects_table[type].loose;
}
+
+int git_repository_init__reinit(git_repository_init_results* results)
+{
+ /* To be implemented */
+
+ results->has_been_reinit = 1;
+ return GIT_SUCCESS;
+}
+
+int git_repository_init__create_head(const char* head_path)
+{
+ git_file fd;
+ int error = GIT_SUCCESS;
+ char head_symlink[50];
+ int len;
+
+ len = sprintf(head_symlink, "%s %s%s\n", GIT_SYMREF, GIT_REFS_HEADS, GIT_BRANCH_MASTER);
+
+ if ((fd = gitfo_creat(head_path, S_IREAD | S_IWRITE)) < 0)
+ return GIT_ERROR;
+
+ error = gitfo_write(fd, (void*)head_symlink, strlen(head_symlink));
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+cleanup:
+ gitfo_close(fd);
+ return error;
+}
+
+int git_repository_init__create_structure_or_reinit(git_repository_init_results* results)
+{
+ char temp_path[GIT_PATH_MAX];
+ int path_len;
+ const int mode = 0755; /* or 0777 ? */
+
+ char* git_dir = results->path_repository;
+
+ //TODO : Ensure the parent tree structure already exists by recursively building it through gitfo_mkdir_recurs().
+ if (gitfo_mkdir_recurs(git_dir, mode))
+ return GIT_ERROR;
+
+ path_len = strlen(git_dir);
+ strcpy(temp_path, git_dir);
+
+ /* Does HEAD file already exist ? */
+ strcpy(temp_path + path_len, GIT_HEAD_FILE);
+
+ if (!gitfo_exists(temp_path) && gitfo_isdir(temp_path) < GIT_SUCCESS)
+ {
+ /* Something very wrong has happened to this repository :-) */
+ return GIT_ERROR;
+ }
+
+ if (!gitfo_exists(temp_path))
+ {
+ return git_repository_init__reinit(results);
+ }
+
+ if (git_repository_init__create_head(temp_path) < GIT_SUCCESS)
+ return GIT_ERROR;
+
+ /* Creates the '/objects/' directory */
+ strcpy(temp_path + path_len, GIT_OBJECTS_FOLDER);
+ if (gitfo_mkdir(temp_path, mode))
+ return GIT_ERROR;
+
+ /* Creates the '/refs/' directory */
+ strcpy(temp_path + path_len, GIT_REFS_FOLDER);
+ if (gitfo_mkdir(temp_path, mode))
+ return GIT_ERROR;
+
+ /* Creates the '/refs/heads/' directory */
+ strcpy(temp_path + path_len, GIT_REFS_HEADS);
+ if (gitfo_mkdir(temp_path, mode))
+ return GIT_ERROR;
+
+ /* Creates the '/refs/tags/' directory */
+ strcpy(temp_path + path_len, GIT_REFS_TAGS);
+ if (gitfo_mkdir(temp_path, mode))
+ return GIT_ERROR;
+
+
+ /* To be implemented */
+
+ return GIT_SUCCESS;
+}
+
+int git_repository_init__assign_git_directory(git_repository_init_results* results, const char* path)
+{
+ const int MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH = 66; // TODO: How many ?
+ char temp_path[GIT_PATH_MAX];
+ int path_len;
+
+ path_len = strlen(path);
+ strcpy(temp_path, path);
+
+ /* Ensure path has a trailing slash */
+ if (temp_path[path_len - 1] != '/') {
+ temp_path[path_len] = '/';
+ temp_path[path_len + 1] = 0;
+
+ path_len = path_len + 1;
+ }
+
+ assert(path_len < GIT_PATH_MAX - MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH);
+
+ if (!results->is_bare)
+ {
+ strcpy(temp_path + path_len - 1, GIT_FOLDER);
+ path_len = path_len + strlen(GIT_FOLDER) - 1; /* Skip the leading slash from the constant */
+ }
+
+ results->path_repository = git__strdup(temp_path);
+
+ return GIT_SUCCESS;
+}
+
+int git_repository_init(git_repository** repo_out, const char* path, unsigned is_bare)
+{
+ git_repository_init_results results;
+ int error = GIT_SUCCESS;
+
+ assert(repo_out && path);
+
+ results.is_bare = is_bare;
+
+ error = git_repository_init__assign_git_directory(&results, path);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ error = git_repository_init__create_structure_or_reinit(&results);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ error = git_repository_open(repo_out, results.path_repository);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+cleanup:
+ free(results.path_repository);
+ return error;
+} \ No newline at end of file