Add 'git_repository_open2' to customize repo folders Signed-off-by: Vicent Marti <tanoku@gmail.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
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;