Commit 40c44d2fb63dbe484824c9dbc7c098c797ad10a1

Vicent Marti 2010-12-19T22:50:20

Fix issues in repository initialization Implemented recursive directory creation Fix style issues Signed-off-by: Vicent Marti <tanoku@gmail.com>

diff --git a/src/fileops.c b/src/fileops.c
index 97b2f07..a25796a 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -313,13 +313,30 @@ int gitfo_dirent(
 
 int gitfo_mkdir_recurs(const char *path, int mode)
 {
-	//TODO: Implement recursive building of the parent tree structure (This would have to work on both Linux and Windows).
 	int error;
+	char *pp, *sp;
+    char *path_copy = git__strdup(path);
 
-	error = gitfo_mkdir(path, mode);
+	if (path_copy == NULL)
+		return GIT_ENOMEM;
 
-	if (errno == EEXIST)
-		return GIT_SUCCESS;
+    error = GIT_SUCCESS;
+    pp = path_copy;
+
+    while (error == 0 && (sp = strchr(pp, '/')) != 0) {
+        if (sp != pp && gitfo_isdir(path_copy) < GIT_SUCCESS) {
+            *sp = 0;
+            error = gitfo_mkdir(path_copy, mode);
+            *sp = '/';
+        }
+
+        pp = sp + 1;
+    }
 
-	return error;
-}
\ No newline at end of file
+    if (*(pp - 1) != '/' && error == GIT_SUCCESS)
+        error = gitfo_mkdir(path, mode);
+
+    free(path_copy);
+    return error;
+
+}
diff --git a/src/git2/repository.h b/src/git2/repository.h
index 4c7ba8d..4eaa6f2 100644
--- a/src/git2/repository.h
+++ b/src/git2/repository.h
@@ -163,20 +163,21 @@ GIT_EXTERN(int) git_repository_newobject(git_object **object, git_repository *re
 GIT_EXTERN(void) git_repository_free(git_repository *repo);
 
 /**
- * Creates a new Git repository.
+ * Creates a new Git repository in the given folder.
  *
- * Limits:
- *  - Reinit of an existing directory is not implemented yet. Will blindly return GIT_SUCCESS.
- *  - The parent directory structure of the repository has to already exist. Recursive building of the parent tree structure is not implemented yet.
- *  - Config file creation handling is not implemented yet.
+ * TODO:
+ *	- Reinit the repository
+ *	- Create config files
  *
  * @param repo_out pointer to the repo which will be created or reinitialized
  * @param path the path to the repository
- * @param is_bare if true, a Git repository without a working directory is created at the pointed path. 
- *		If false, provided path will be considered as the working directory into which the .git directory will be created.
+ * @param is_bare if true, a Git repository without a working directory is created 
+ *		at the pointed path. If false, provided path will be considered as the working 
+ *		directory into which the .git directory will be created.
+ *
  * @return 0 on success; error code otherwise
  */
-GIT_EXTERN(int) git_repository_init(git_repository** repo_out, const char* path, unsigned is_bare);
+GIT_EXTERN(int) git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare);
 
 /** @} */
 GIT_END_DECL
diff --git a/src/repository.c b/src/repository.c
index 94f67f4..3551b87 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -33,15 +33,16 @@
 #include "blob.h"
 #include "fileops.h"
 
-#define GIT_FOLDER "/.git/"
-#define GIT_OBJECTS_FOLDER "objects/"
-#define GIT_REFS_FOLDER "refs/"
+#define GIT_DIR "/.git/"
+#define GIT_OBJECTS_DIR "objects/"
+#define GIT_REFS_DIR "refs/"
+#define GIT_REFS_HEADS_DIR "refs/heads/"
+#define GIT_REFS_TAGS_DIR "refs/tags/"
+
 #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;
@@ -64,12 +65,11 @@ static struct {
 	{ "REF_DELTA", 0, 0					}   /* 7 = GIT_OBJ_REF_DELTA */
 };
 
-typedef struct git_repository_init_results {
+typedef struct {
 	char *path_repository;
-
-	unsigned is_bare:1;
-	unsigned has_been_reinit:1;
-} git_repository_init_results;
+	unsigned is_bare:1,
+			 has_been_reinit:1;
+} repo_init;
 
 /***********************************************************
  *
@@ -102,7 +102,7 @@ int git__objtable_haskey(void *object, const void *key)
 
 
 
-static int assign_repository_folders(git_repository *repo,
+static int assign_repository_DIRs(git_repository *repo,
 		const char *git_dir,
 		const char *git_object_directory,
 		const char *git_index_file,
@@ -131,7 +131,7 @@ static int assign_repository_folders(git_repository *repo,
 
 	/* store GIT_OBJECT_DIRECTORY */
 	if (git_object_directory == NULL)
-		strcpy(path_aux + path_len, GIT_OBJECTS_FOLDER);
+		strcpy(path_aux + path_len, GIT_OBJECTS_DIR);
 	else
 		strcpy(path_aux, git_object_directory);
 
@@ -162,9 +162,9 @@ static int assign_repository_folders(git_repository *repo,
 	return GIT_SUCCESS;
 }
 
-static int guess_repository_folders(git_repository *repo, const char *repository_path)
+static int guess_repository_DIRs(git_repository *repo, const char *repository_path)
 {
-	char path_aux[GIT_PATH_MAX], *last_folder;
+	char path_aux[GIT_PATH_MAX], *last_DIR;
 	int path_len;
 
 	if (gitfo_isdir(repository_path) < GIT_SUCCESS)
@@ -183,7 +183,7 @@ static int guess_repository_folders(git_repository *repo, const char *repository
 	repo->path_repository = git__strdup(path_aux);
 
 	/* objects database */
-	strcpy(path_aux + path_len, GIT_OBJECTS_FOLDER);
+	strcpy(path_aux + path_len, GIT_OBJECTS_DIR);
 	if (gitfo_isdir(path_aux) < GIT_SUCCESS)
 		return GIT_ENOTAREPO;
 	repo->path_odb = git__strdup(path_aux);
@@ -195,12 +195,12 @@ static int guess_repository_folders(git_repository *repo, const char *repository
 
 	path_aux[path_len] = 0;
 
-	last_folder = (path_aux + path_len - 2);
+	last_DIR = (path_aux + path_len - 2);
 
-	while (*last_folder != '/')
-		last_folder--;
+	while (*last_DIR != '/')
+		last_DIR--;
 
-	if (strcmp(last_folder, GIT_FOLDER) == 0) {
+	if (strcmp(last_DIR, GIT_DIR) == 0) {
 		repo->is_bare = 0;
 
 		/* index file */
@@ -208,7 +208,7 @@ static int guess_repository_folders(git_repository *repo, const char *repository
 		repo->path_index = git__strdup(path_aux);
 
 		/* working dir */
-		*(last_folder + 1) = 0;
+		*(last_DIR + 1) = 0;
 		repo->path_workdir = git__strdup(path_aux);
 
 	} else {
@@ -255,7 +255,7 @@ int git_repository_open2(git_repository **repo_out,
 	if (repo == NULL)
 		return GIT_ENOMEM;
 
-	error = assign_repository_folders(repo, 
+	error = assign_repository_DIRs(repo, 
 			git_dir, 
 			git_object_directory,
 			git_index_file,
@@ -287,7 +287,7 @@ int git_repository_open(git_repository **repo_out, const char *path)
 	if (repo == NULL)
 		return GIT_ENOMEM;
 
-	error = guess_repository_folders(repo, path);
+	error = guess_repository_DIRs(repo, path);
 	if (error < GIT_SUCCESS)
 		goto cleanup;
 
@@ -736,44 +736,41 @@ 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 */
 
+
+int repo_init_reinit(repo_init *results)
+{
+	/* TODO: reinit the repository */
 	results->has_been_reinit = 1;
 	return GIT_SUCCESS;
 }
 
-int git_repository_init__create_head(const char* head_path)
+int repo_init_createhead(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);
+	len = sprintf(head_symlink, "%s %s%s\n", GIT_SYMREF, GIT_REFS_HEADS_DIR, GIT_BRANCH_MASTER);
 	
-	if ((fd = gitfo_creat(head_path, S_IREAD | S_IWRITE)) < 0)
+	if ((fd = gitfo_creat(head_path, S_IREAD | S_IWRITE)) < GIT_SUCCESS)
 		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)
+int repo_init_structure(repo_init *results)
 {
-	char temp_path[GIT_PATH_MAX];
-	int path_len;
 	const int mode = 0755; /* or 0777 ? */
 
-	char* git_dir = results->path_repository;
+	char temp_path[GIT_PATH_MAX];
+	int path_len;
+	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;
 
@@ -783,49 +780,41 @@ int git_repository_init__create_structure_or_reinit(git_repository_init_results*
 	/* 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 (gitfo_exists(temp_path) == GIT_SUCCESS)
+		return repo_init_reinit(results);
 
-	if (git_repository_init__create_head(temp_path) < GIT_SUCCESS)
+	if (repo_init_createhead(temp_path) < GIT_SUCCESS)
 		return GIT_ERROR;
 
 	/* Creates the '/objects/' directory */
-	strcpy(temp_path + path_len, GIT_OBJECTS_FOLDER);
+	strcpy(temp_path + path_len, GIT_OBJECTS_DIR);
 	if (gitfo_mkdir(temp_path, mode))
 		return GIT_ERROR;
 
 	/* Creates the '/refs/' directory */
-	strcpy(temp_path + path_len, GIT_REFS_FOLDER);
+	strcpy(temp_path + path_len, GIT_REFS_DIR);
 	if (gitfo_mkdir(temp_path, mode))
 		return GIT_ERROR;
 
 	/* Creates the '/refs/heads/' directory */
-	strcpy(temp_path + path_len, GIT_REFS_HEADS);
+	strcpy(temp_path + path_len, GIT_REFS_HEADS_DIR);
 	if (gitfo_mkdir(temp_path, mode))
 		return GIT_ERROR;
 
 	/* Creates the '/refs/tags/' directory */
-	strcpy(temp_path + path_len, GIT_REFS_TAGS);
+	strcpy(temp_path + path_len, GIT_REFS_TAGS_DIR);
 	if (gitfo_mkdir(temp_path, mode))
 		return GIT_ERROR;
 
-
-	/* To be implemented */
+	/* TODO: what's left? templates? */
 
 	return GIT_SUCCESS;
 }
 
-int git_repository_init__assign_git_directory(git_repository_init_results* results, const char* path)
+int repo_init_find_dir(repo_init *results, const char* path)
 {
-	const int MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH = 66; // TODO: How many ?
+	const int MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH = 66;
+
 	char temp_path[GIT_PATH_MAX];
 	int path_len;
 
@@ -840,41 +829,40 @@ int git_repository_init__assign_git_directory(git_repository_init_results* resul
 		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 */
+	if (!results->is_bare) {
+		strcpy(temp_path + path_len - 1, GIT_DIR);
+		path_len = path_len + strlen(GIT_DIR) - 1; /* Skip the leading slash from the constant */
 	}
 
+	if (path_len >= GIT_PATH_MAX - MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH)
+		return GIT_ENOTAREPO;
+
 	results->path_repository = git__strdup(temp_path);
 
 	return GIT_SUCCESS;
 }
 
-int git_repository_init(git_repository** repo_out, const char* path, unsigned is_bare)
+int git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare)
 {
-	git_repository_init_results results;
 	int error = GIT_SUCCESS;
+	repo_init results;
 	
 	assert(repo_out && path);
 
+	results.path_repository = NULL;
 	results.is_bare = is_bare;
 
-	error = git_repository_init__assign_git_directory(&results, path);
+	error = repo_init_find_dir(&results, path);
 	if (error < GIT_SUCCESS)
 		goto cleanup;
 
-	error = git_repository_init__create_structure_or_reinit(&results);
+	error = repo_init_structure(&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
+}