Commit 691aa96817b9b4c6ad3a43b2d31d6e96a918a999

Vicent Marti 2010-12-02T18:35:38

Add 'git_repository_open2' to customize repo folders Signed-off-by: Vicent Marti <tanoku@gmail.com>

diff --git a/src/git/repository.h b/src/git/repository.h
index 81eb1ea..6610347 100644
--- a/src/git/repository.h
+++ b/src/git/repository.h
@@ -36,12 +36,45 @@ GIT_BEGIN_DECL
  *
  * @param repository pointer to the repo which will be opened
  * @param path the path to the repository
- * @return the new repository handle; NULL on error
+ * @return 0 on sucess; error code otherwise
  */
 GIT_EXTERN(int) git_repository_open(git_repository **repository, const char *path);
 
 
 /**
+ * Open a git repository by manually specifying all its paths
+ *
+ * @param repository pointer to the repo which will be opened
+ *
+ * @param git_dir The full path to the repository folder
+ *		e.g. a '.git' folder for live repos, any folder for bare
+ *		Equivalent to $GIT_DIR. 
+ *		Cannot be NULL.
+ *
+ * @param git_object_directory The full path to the ODB folder.
+ *		the folder where all the loose and packed objects are stored
+ *		Equivalent to $GIT_OBJECT_DIRECTORY.
+ *		If NULL, "$GIT_DIR/objects/" is assumed.
+ *
+ * @param git_index_file The full path to the index (dircache) file
+ *		Equivalent to $GIT_INDEX_FILE.
+ *		If NULL, "$GIT_DIR/index" is assumed.
+ *
+ * @param git_work_tree The full path to the working tree of the repository,
+ *		if the repository is not bare.
+ *		Equivalent to $GIT_WORK_TREE.
+ *		If NULL, the repository is assumed to be bare.
+ *
+ * @return 0 on sucess; error code otherwise
+ */
+GIT_EXTERN(int) git_repository_open2(git_repository **repository,
+		const char *git_dir,
+		const char *git_object_directory,
+		const char *git_index_file,
+		const char *git_work_tree);
+
+
+/**
  * Lookup a reference to one of the objects in the repostory.
  *
  * The generated reference is owned by the repository and
diff --git a/src/repository.c b/src/repository.c
index dbf3407..c915ddd 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -31,6 +31,11 @@
 #include "blob.h"
 #include "fileops.h"
 
+#define GIT_FOLDER "/.git/"
+#define GIT_OBJECTS_FOLDER "objects/"
+#define GIT_INDEX_FILE "index"
+#define GIT_HEAD_FILE "HEAD"
+
 static const int default_table_size = 32;
 static const double max_load_factor = 0.65;
 
@@ -66,7 +71,70 @@ int git__objtable_haskey(void *object, const void *key)
 	return (git_oid_cmp(oid, &obj->id) == 0);
 }
 
-static int parse_repository_folders(git_repository *repo, const char *repository_path)
+
+
+static int assign_repository_folders(git_repository *repo,
+		const char *git_dir,
+		const char *git_object_directory,
+		const char *git_index_file,
+		const char *git_work_tree)
+{
+	char path_aux[GIT_PATH_MAX];
+	size_t path_len;
+
+	assert(repo);
+
+	if (git_dir == NULL || gitfo_isdir(git_dir) < 0)
+		return GIT_ENOTFOUND;
+
+
+	/* store GIT_DIR */
+	path_len = strlen(git_dir);
+	strcpy(path_aux, git_dir);
+
+	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);
+
+	/* store GIT_OBJECT_DIRECTORY */
+	if (git_object_directory == NULL)
+		strcpy(path_aux + path_len, GIT_OBJECTS_FOLDER);
+	else
+		strcpy(path_aux, git_object_directory);
+
+	if (gitfo_isdir(path_aux) < 0)
+		return GIT_ENOTFOUND;
+
+	repo->path_odb = git__strdup(path_aux);
+
+
+	/* store GIT_INDEX_FILE */
+	if (git_index_file == NULL)
+		strcpy(path_aux + path_len, GIT_INDEX_FILE);
+	else
+		strcpy(path_aux, git_index_file); 
+
+	if (gitfo_exists(path_aux) < 0)
+		return GIT_ENOTFOUND;
+
+	repo->path_index = git__strdup(path_aux);
+
+
+	/* store GIT_WORK_TREE */
+	if (git_work_tree == NULL)
+		repo->is_bare = 1;
+	else
+		repo->path_workdir = git__strdup(git_work_tree);
+
+	return GIT_SUCCESS;
+}
+
+static int guess_repository_folders(git_repository *repo, const char *repository_path)
 {
 	char path_aux[GIT_PATH_MAX], *last_folder;
 	int path_len;
@@ -87,13 +155,13 @@ static int parse_repository_folders(git_repository *repo, const char *repository
 	repo->path_repository = git__strdup(path_aux);
 
 	/* objects database */
-	strcpy(path_aux + path_len, "objects/");
+	strcpy(path_aux + path_len, GIT_OBJECTS_FOLDER);
 	if (gitfo_isdir(path_aux) < 0)
 		return GIT_ENOTAREPO;
 	repo->path_odb = git__strdup(path_aux);
 
 	/* HEAD file */
-	strcpy(path_aux + path_len, "HEAD");
+	strcpy(path_aux + path_len, GIT_HEAD_FILE);
 	if (gitfo_exists(path_aux) < 0)
 		return GIT_ENOTAREPO;
 
@@ -104,11 +172,11 @@ static int parse_repository_folders(git_repository *repo, const char *repository
 	while (*last_folder != '/')
 		last_folder--;
 
-	if (strcmp(last_folder, "/.git/") == 0) {
+	if (strcmp(last_folder, GIT_FOLDER) == 0) {
 		repo->is_bare = 0;
 
 		/* index file */
-		strcpy(path_aux + path_len, "index");
+		strcpy(path_aux + path_len, GIT_INDEX_FILE);
 		repo->path_index = git__strdup(path_aux);
 
 		/* working dir */
@@ -144,6 +212,42 @@ git_repository *git_repository__alloc()
 	return repo;
 }
 
+int git_repository_open2(git_repository **repo_out,
+		const char *git_dir,
+		const char *git_object_directory,
+		const char *git_index_file,
+		const char *git_work_tree)
+{
+	git_repository *repo;
+	int error = GIT_SUCCESS;
+
+	assert(repo_out);
+
+	repo = git_repository__alloc();
+	if (repo == NULL)
+		return GIT_ENOMEM;
+
+	error = assign_repository_folders(repo, 
+			git_dir, 
+			git_object_directory,
+			git_index_file,
+			git_work_tree);
+
+	if (error < 0)
+		goto cleanup;
+
+	error = git_odb_open(&repo->db, repo->path_odb);
+	if (error < 0)
+		goto cleanup;
+
+	*repo_out = repo;
+	return GIT_SUCCESS;
+
+cleanup:
+	git_repository_free(repo);
+	return error;
+}
+
 int git_repository_open(git_repository **repo_out, const char *path)
 {
 	git_repository *repo;
@@ -155,7 +259,7 @@ int git_repository_open(git_repository **repo_out, const char *path)
 	if (repo == NULL)
 		return GIT_ENOMEM;
 
-	error = parse_repository_folders(repo, path);
+	error = guess_repository_folders(repo, path);
 	if (error < 0)
 		goto cleanup;