summaryrefslogtreecommitdiff
path: root/src/repository.c
diff options
context:
space:
mode:
authorRussell Belfer <arrbee@arrbee.com>2011-11-30 11:27:15 -0800
committerRussell Belfer <arrbee@arrbee.com>2011-12-07 23:08:15 -0800
commit97769280ba9938ae27f6e06cbd0d5e8a768a86b9 (patch)
tree4fe43e99acb55f904f6b586bd7c5158610f9512f /src/repository.c
parenta22b14d32dd8d5f06f121aa154d45bac3b10a305 (diff)
downloadlibgit2-97769280ba9938ae27f6e06cbd0d5e8a768a86b9.tar.gz
Use git_buf for path storage instead of stack-based buffers
This converts virtually all of the places that allocate GIT_PATH_MAX buffers on the stack for manipulating paths to use git_buf objects instead. The patch is pretty careful not to touch the public API for libgit2, so there are a few places that still use GIT_PATH_MAX. This extends and changes some details of the git_buf implementation to add a couple of extra functions and to make error handling easier. This includes serious alterations to all the path.c functions, and several of the fileops.c ones, too. Also, there are a number of new functions that parallel existing ones except that use a git_buf instead of a stack-based buffer (such as git_config_find_global_r that exists alongsize git_config_find_global). This also modifies the win32 version of p_realpath to allocate whatever buffer size is needed to accommodate the realpath instead of hardcoding a GIT_PATH_MAX limit, but that change needs to be tested still.
Diffstat (limited to 'src/repository.c')
-rw-r--r--src/repository.c405
1 files changed, 224 insertions, 181 deletions
diff --git a/src/repository.c b/src/repository.c
index 0cd4a8123..67afa2ee2 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -75,21 +75,17 @@ void git_repository_free(git_repository *repo)
*
* Open a repository object from its path
*/
-static int quickcheck_repository_dir(const char *repository_path)
+static int quickcheck_repository_dir(git_buf *repository_path)
{
- char path_aux[GIT_PATH_MAX];
-
- /* Ensure HEAD file exists */
- git_path_join(path_aux, repository_path, GIT_HEAD_FILE);
- if (git_futils_isfile(path_aux) < 0)
+ /* Check OBJECTS_DIR first, since it will generate the longest path name */
+ if (git_futils_contains_dir(repository_path, GIT_OBJECTS_DIR, 0) < 0)
return GIT_ERROR;
- git_path_join(path_aux, repository_path, GIT_OBJECTS_DIR);
- if (git_futils_isdir(path_aux) < 0)
+ /* Ensure HEAD file exists */
+ if (git_futils_contains_file(repository_path, GIT_HEAD_FILE, 0) < 0)
return GIT_ERROR;
- git_path_join(path_aux, repository_path, GIT_REFS_DIR);
- if (git_futils_isdir(path_aux) < 0)
+ if (git_futils_contains_dir(repository_path, GIT_REFS_DIR, 0) < 0)
return GIT_ERROR;
return GIT_SUCCESS;
@@ -135,74 +131,74 @@ static int load_config_data(git_repository *repo)
static int load_workdir(git_repository *repo)
{
- if (!repo->is_bare) {
- char workdir_buf[GIT_PATH_MAX];
+ int error;
+ git_buf workdir_buf = GIT_BUF_INIT;
- if (git_path_dirname_r(workdir_buf, sizeof(workdir_buf), repo->path_repository) < 0)
- return git__throw(GIT_EOSERR,
- "Failed to resolved working directory");
+ if (repo->is_bare)
+ return GIT_SUCCESS;
- git_path_join(workdir_buf, workdir_buf, "");
+ git_path_dirname_r(&workdir_buf, repo->path_repository);
+ git_path_to_dir(&workdir_buf);
- repo->workdir = git__strdup(workdir_buf);
- if (repo->workdir == NULL)
- return GIT_ENOMEM;
- }
+ if ((error = git_buf_lasterror(&workdir_buf)) == GIT_SUCCESS)
+ repo->workdir = git_buf_detach(&workdir_buf);
- return GIT_SUCCESS;
+ git_buf_free(&workdir_buf);
+
+ return error;
}
int git_repository_open(git_repository **repo_out, const char *path)
{
int error = GIT_SUCCESS;
- char path_buf[GIT_PATH_MAX];
- size_t path_len;
+ git_buf path_buf = GIT_BUF_INIT;
git_repository *repo = NULL;
- error = git_path_prettify_dir(path_buf, path, NULL);
+ error = git_path_prettify_dir(&path_buf, path, NULL);
if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to open repository");
-
- path_len = strlen(path_buf);
+ goto cleanup;
/**
* Check if the path we've been given is actually the path
* of the working dir, by testing if it contains a `.git`
* folder inside of it.
*/
- git_path_join(path_buf, path_buf, DOT_GIT);
- if (git_futils_isdir(path_buf) < GIT_SUCCESS) {
- path_buf[path_len] = 0;
- }
+ git_futils_contains_dir(&path_buf, DOT_GIT, 1); /* append on success */
+ /* ignore error, since it just means `path/.git` doesn't exist */
- if (quickcheck_repository_dir(path_buf) < GIT_SUCCESS)
- return git__throw(GIT_ENOTAREPO,
+ if (quickcheck_repository_dir(&path_buf) < GIT_SUCCESS) {
+ error = git__throw(GIT_ENOTAREPO,
"The given path is not a valid Git repository");
+ goto cleanup;
+ }
repo = repository_alloc();
- if (repo == NULL)
- return GIT_ENOMEM;
+ if (repo == NULL) {
+ error = GIT_ENOMEM;
+ goto cleanup;
+ }
- repo->path_repository = git__strdup(path_buf);
+ repo->path_repository = git_buf_detach(&path_buf);
if (repo->path_repository == NULL) {
- git_repository_free(repo);
- return GIT_ENOMEM;
+ error = GIT_ENOMEM;
+ goto cleanup;
}
error = load_config_data(repo);
- if (error < GIT_SUCCESS) {
- git_repository_free(repo);
- return error;
- }
+ if (error < GIT_SUCCESS)
+ goto cleanup;
error = load_workdir(repo);
- if (error < GIT_SUCCESS) {
- git_repository_free(repo);
- return error;
- }
+ if (error < GIT_SUCCESS)
+ goto cleanup;
*repo_out = repo;
return GIT_SUCCESS;
+
+ cleanup:
+ git_repository_free(repo);
+ git_buf_free(&path_buf);
+ return error;
}
static int load_config(
@@ -211,7 +207,7 @@ static int load_config(
const char *global_config_path,
const char *system_config_path)
{
- char config_path[GIT_PATH_MAX];
+ git_buf config_path = GIT_BUF_INIT;
int error;
git_config *cfg = NULL;
@@ -221,8 +217,13 @@ static int load_config(
if (error < GIT_SUCCESS)
return error;
- git_path_join(config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO);
- error = git_config_add_file_ondisk(cfg, config_path, 3);
+ error = git_buf_joinpath(&config_path, repo->path_repository,
+ GIT_CONFIG_FILENAME_INREPO);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ error = git_config_add_file_ondisk(cfg, config_path.ptr, 3);
+ git_buf_free(&config_path); /* done with config_path now */
if (error < GIT_SUCCESS)
goto cleanup;
@@ -251,19 +252,22 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
{
if (repo->_config == NULL) {
int error;
-
- char buf_global[GIT_PATH_MAX], buf_system[GIT_PATH_MAX];
+ git_buf global_buf = GIT_BUF_INIT, system_buf = GIT_BUF_INIT;
const char *global_config_path = NULL;
const char *system_config_path = NULL;
- if (git_config_find_global(buf_global) == GIT_SUCCESS)
- global_config_path = buf_global;
+ if (git_config_find_global_r(&global_buf) == GIT_SUCCESS)
+ global_config_path = global_buf.ptr;
- if (git_config_find_system(buf_system) == GIT_SUCCESS)
- system_config_path = buf_system;
+ if (git_config_find_system_r(&system_buf) == GIT_SUCCESS)
+ system_config_path = system_buf.ptr;
error = load_config(&repo->_config, repo, global_config_path, system_config_path);
+
+ git_buf_free(&global_buf);
+ git_buf_free(&system_buf);
+
if (error < GIT_SUCCESS)
return error;
@@ -301,11 +305,14 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
if (repo->_odb == NULL) {
int error;
- char odb_path[GIT_PATH_MAX];
+ git_buf odb_path = GIT_BUF_INIT;
- git_path_join(odb_path, repo->path_repository, GIT_OBJECTS_DIR);
+ error = git_buf_joinpath(&odb_path, repo->path_repository, GIT_OBJECTS_DIR);
+ if (error < GIT_SUCCESS)
+ return error;
- error = git_odb_open(&repo->_odb, odb_path);
+ error = git_odb_open(&repo->_odb, odb_path.ptr);
+ git_buf_free(&odb_path); /* done with path */
if (error < GIT_SUCCESS)
return error;
@@ -346,11 +353,14 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
if (repo->_index == NULL) {
int error;
- char index_path[GIT_PATH_MAX];
+ git_buf index_path = GIT_BUF_INIT;
- git_path_join(index_path, repo->path_repository, GIT_INDEX_FILE);
+ error = git_buf_joinpath(&index_path, repo->path_repository, GIT_INDEX_FILE);
+ if (error < GIT_SUCCESS)
+ return error;
- error = git_index_open(&repo->_index, index_path);
+ error = git_index_open(&repo->_index, index_path.ptr);
+ git_buf_free(&index_path); /* done with path */
if (error < GIT_SUCCESS)
return error;
@@ -397,7 +407,17 @@ static int retrieve_device(dev_t *device_out, const char *path)
return GIT_SUCCESS;
}
-static int retrieve_ceiling_directories_offset(const char *path, const char *ceiling_directories)
+/*
+ * This function returns furthest offset into path where a ceiling dir
+ * is found, so we can stop processing the path at that point.
+ *
+ * Note: converting this to use git_bufs instead of GIT_PATH_MAX buffers on
+ * the stack could remove directories name limits, but at the cost of doing
+ * repeated malloc/frees inside the loop below, so let's not do it now.
+ */
+static int retrieve_ceiling_directories_offset(
+ const char *path,
+ const char *ceiling_directories)
{
char buf[GIT_PATH_MAX + 1];
char buf2[GIT_PATH_MAX + 1];
@@ -416,7 +436,7 @@ static int retrieve_ceiling_directories_offset(const char *path, const char *cei
for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
len = sep - ceil;
- if (len == 0 || len > GIT_PATH_MAX || git_path_root(ceil) == -1)
+ if (len == 0 || len >= (int)sizeof(buf) || git_path_root(ceil) == -1)
continue;
strncpy(buf, ceil, len);
@@ -440,45 +460,43 @@ static int retrieve_ceiling_directories_offset(const char *path, const char *cei
return max_len <= min_len ? min_len : max_len;
}
-static int read_gitfile(char *path_out, const char *file_path, const char *base_path)
+/*
+ * Read the contents of `file_path` and set `path_out` to the repo dir that
+ * it points to. Before calling, set `path_out` to the base directory that
+ * should be used if the contents of `file_path` are a relative path.
+ */
+static int read_gitfile(git_buf *path_out, const char *file_path, const char *base_path)
{
git_fbuffer file;
int error;
- size_t end_offset;
- char *data;
- assert(path_out && file_path && base_path);
+ assert(path_out && file_path);
error = git_futils_readbuffer(&file, file_path);
-
if (error < GIT_SUCCESS)
return error;
- data = (char*)(file.data);
-
- if (git__prefixcmp(data, GIT_FILE_CONTENT_PREFIX)) {
+ if (git__prefixcmp((char *)file.data, GIT_FILE_CONTENT_PREFIX)) {
git_futils_freebuffer(&file);
return git__throw(GIT_ENOTFOUND, "Invalid gitfile format `%s`", file_path);
}
- end_offset = strlen(data) - 1;
+ git_futils_fbuffer_rtrim(&file);
- for (;data[end_offset] == '\r' || data[end_offset] == '\n'; --end_offset);
- data[end_offset + 1] = '\0';
-
- if (strlen(GIT_FILE_CONTENT_PREFIX) == end_offset + 1) {
+ if (strlen(GIT_FILE_CONTENT_PREFIX) == file.len) {
git_futils_freebuffer(&file);
return git__throw(GIT_ENOTFOUND, "No path in git file `%s`", file_path);
}
- data = data + strlen(GIT_FILE_CONTENT_PREFIX);
- error = git_path_prettify_dir(path_out, data, base_path);
+ error = git_path_prettify_dir(path_out,
+ ((char *)file.data) + strlen(GIT_FILE_CONTENT_PREFIX), base_path);
+
git_futils_freebuffer(&file);
- if (error == 0 && git_futils_exists(path_out) == 0)
+ if (error == GIT_SUCCESS && git_futils_exists(path_out->ptr) == 0)
return GIT_SUCCESS;
- return git__throw(GIT_EOBJCORRUPTED, "The `.git` file points to an inexisting path");
+ return git__throw(GIT_EOBJCORRUPTED, "The `.git` file points to a nonexistent path");
}
int git_repository_discover(
@@ -489,54 +507,62 @@ int git_repository_discover(
const char *ceiling_dirs)
{
int error, ceiling_offset;
- char bare_path[GIT_PATH_MAX];
- char normal_path[GIT_PATH_MAX];
- char *found_path;
+ git_buf bare_path = GIT_BUF_INIT;
+ git_buf normal_path = GIT_BUF_INIT;
+ git_buf *found_path = NULL;
dev_t current_device = 0;
assert(start_path && repository_path);
- error = git_path_prettify_dir(bare_path, start_path, NULL);
+ *repository_path = '\0';
+
+ error = git_path_prettify_dir(&bare_path, start_path, NULL);
if (error < GIT_SUCCESS)
- return error;
+ goto cleanup;
if (!across_fs) {
- error = retrieve_device(&current_device, bare_path);
+ error = retrieve_device(&current_device, bare_path.ptr);
if (error < GIT_SUCCESS)
- return error;
+ goto cleanup;
}
- ceiling_offset = retrieve_ceiling_directories_offset(bare_path, ceiling_dirs);
- git_path_join(normal_path, bare_path, DOT_GIT);
+ ceiling_offset = retrieve_ceiling_directories_offset(bare_path.ptr, ceiling_dirs);
while(1) {
+ error = git_buf_joinpath(&normal_path, bare_path.ptr, DOT_GIT);
+ if (error < GIT_SUCCESS)
+ break;
+
/**
* If the `.git` file is regular instead of
* a directory, it should contain the path of the actual git repository
*/
- if (git_futils_isfile(normal_path) == GIT_SUCCESS) {
- error = read_gitfile(repository_path, normal_path, bare_path);
-
- if (error < GIT_SUCCESS)
- return git__rethrow(error,
- "Unable to read git file `%s`", normal_path);
+ if (git_futils_isfile(normal_path.ptr) == GIT_SUCCESS) {
+ git_buf gitfile_path = GIT_BUF_INIT;
- error = quickcheck_repository_dir(repository_path);
+ error = read_gitfile(&gitfile_path, normal_path.ptr, bare_path.ptr);
if (error < GIT_SUCCESS)
- return git__throw(GIT_ENOTFOUND,
- "The `.git` file found at '%s' points"
- "to an inexisting Git folder", normal_path);
+ git__rethrow(error, "Unable to read git file `%s`", normal_path.ptr);
+ else if ((error = quickcheck_repository_dir(&gitfile_path)) < GIT_SUCCESS)
+ git__throw(GIT_ENOTFOUND,
+ "The `.git` file found at '%s' points "
+ "to a nonexistent git folder", normal_path.ptr);
+ else {
+ git_buf_swap(&normal_path, &gitfile_path);
+ found_path = &normal_path;
+ }
- return GIT_SUCCESS;
+ git_buf_free(&gitfile_path);
+ break;
}
/**
* If the `.git` file is a folder, we check inside of it
*/
- if (git_futils_isdir(normal_path) == GIT_SUCCESS) {
- error = quickcheck_repository_dir(normal_path);
+ if (git_futils_isdir(normal_path.ptr) == GIT_SUCCESS) {
+ error = quickcheck_repository_dir(&normal_path);
if (error == GIT_SUCCESS) {
- found_path = normal_path;
+ found_path = &normal_path;
break;
}
}
@@ -545,44 +571,63 @@ int git_repository_discover(
* Otherwise, the repository may be bare, let's check
* the root anyway
*/
- error = quickcheck_repository_dir(bare_path);
+ error = quickcheck_repository_dir(&bare_path);
if (error == GIT_SUCCESS) {
- found_path = bare_path;
+ found_path = &bare_path;
break;
}
- if (git_path_dirname_r(normal_path, sizeof(normal_path), bare_path) < GIT_SUCCESS)
- return git__throw(GIT_EOSERR, "Failed to dirname '%s'", bare_path);
+ /**
+ * If we didn't find it, walk up the tree
+ */
+ error = git_path_dirname_r(&normal_path, bare_path.ptr);
+ if (error < GIT_SUCCESS) {
+ git__rethrow(GIT_EOSERR, "Failed to dirname '%s'", bare_path.ptr);
+ break;
+ }
+
+ git_buf_swap(&bare_path, &normal_path);
if (!across_fs) {
dev_t new_device;
- error = retrieve_device(&new_device, normal_path);
+ error = retrieve_device(&new_device, bare_path.ptr);
if (error < GIT_SUCCESS || current_device != new_device) {
- return git__throw(GIT_ENOTAREPO,
+ error = git__throw(GIT_ENOTAREPO,
"Not a git repository (or any parent up to mount parent %s)\n"
- "Stopping at filesystem boundary.", bare_path);
+ "Stopping at filesystem boundary.", normal_path.ptr);
+ break;
}
current_device = new_device;
}
- strcpy(bare_path, normal_path);
- git_path_join(normal_path, bare_path, DOT_GIT);
-
- // nothing has been found, lets try the parent directory
- if (bare_path[ceiling_offset] == '\0') {
- return git__throw(GIT_ENOTAREPO,
+ /* nothing has been found, lets try the parent directory
+ * but stop if we hit one of the ceiling directories
+ */
+ if (bare_path.ptr[ceiling_offset] == '\0') {
+ error = git__throw(GIT_ENOTAREPO,
"Not a git repository (or any of the parent directories): %s", start_path);
+ break;
}
}
- if (size < strlen(found_path) + 2) {
- return git__throw(GIT_ESHORTBUFFER,
- "The repository buffer is not long enough to handle the repository path `%s`", found_path);
+ assert(found_path || error != GIT_SUCCESS);
+
+ if (found_path) {
+ if ((error = git_path_to_dir(found_path)) < GIT_SUCCESS)
+ git__rethrow(error, "Could not convert git repository to directory");
+ else if (size < (size_t)(found_path->size + 1))
+ error = git__throw(GIT_ESHORTBUFFER,
+ "The repository buffer is not long enough to "
+ "handle the repository path `%s`", found_path->ptr);
+ else
+ git_buf_copy_cstr(repository_path, size, found_path);
}
- git_path_join(repository_path, found_path, "");
- return GIT_SUCCESS;
+cleanup:
+ git_buf_free(&bare_path);
+ git_buf_free(&normal_path);
+ return error;
}
static int repo_init_reinit(const char *repository_path, int is_bare)
@@ -596,21 +641,23 @@ static int repo_init_reinit(const char *repository_path, int is_bare)
static int repo_init_createhead(const char *git_dir)
{
- char ref_path[GIT_PATH_MAX];
+ int error;
+ git_buf ref_path = GIT_BUF_INIT;
git_filebuf ref = GIT_FILEBUF_INIT;
- git_path_join(ref_path, git_dir, GIT_HEAD_FILE);
-
- git_filebuf_open(&ref, ref_path, 0);
- git_filebuf_printf(&ref, "ref: refs/heads/master\n");
+ if (!(error = git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE)) &&
+ !(error = git_filebuf_open(&ref, ref_path.ptr, 0)) &&
+ !(error = git_filebuf_printf(&ref, "ref: refs/heads/master\n")))
+ error = git_filebuf_commit(&ref, GIT_REFS_FILE_MODE);
- return git_filebuf_commit(&ref, GIT_REFS_FILE_MODE);
+ git_buf_free(&ref_path);
+ return error;
}
static int repo_init_config(const char *git_dir, int is_bare)
{
- char cfg_path[GIT_PATH_MAX];
- git_config *config;
+ git_buf cfg_path = GIT_BUF_INIT;
+ git_config *config = NULL;
int error = GIT_SUCCESS;
#define SET_REPO_CONFIG(type, name, val) {\
@@ -619,29 +666,40 @@ static int repo_init_config(const char *git_dir, int is_bare)
goto cleanup;\
}
- git_path_join(cfg_path, git_dir, GIT_CONFIG_FILENAME_INREPO);
+ error = git_buf_joinpath(&cfg_path, git_dir, GIT_CONFIG_FILENAME_INREPO);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
- error = git_config_open_ondisk(&config, cfg_path);
+ error = git_config_open_ondisk(&config, cfg_path.ptr);
if (error < GIT_SUCCESS)
- return error;
+ goto cleanup;
SET_REPO_CONFIG(bool, "core.bare", is_bare);
SET_REPO_CONFIG(int32, "core.repositoryformatversion", 0);
/* TODO: what other defaults? */
cleanup:
+ git_buf_free(&cfg_path);
git_config_free(config);
return error;
}
static int repo_init_structure(const char *git_dir, int is_bare)
{
- int error;
-
- char temp_path[GIT_PATH_MAX];
-
- if (git_futils_mkdir_r(git_dir, is_bare ? GIT_BARE_DIR_MODE : GIT_DIR_MODE))
- return git__throw(GIT_ERROR, "Failed to initialize repository structure. Could not mkdir");
+ int error, i;
+ struct { const char *dir; mode_t mode; } dirs[] = {
+ { GIT_OBJECTS_INFO_DIR, GIT_OBJECT_DIR_MODE }, /* '/objects/info/' */
+ { GIT_OBJECTS_PACK_DIR, GIT_OBJECT_DIR_MODE }, /* '/objects/pack/' */
+ { GIT_REFS_HEADS_DIR, GIT_REFS_DIR_MODE }, /* '/refs/heads/' */
+ { GIT_REFS_TAGS_DIR, GIT_REFS_DIR_MODE }, /* '/refs/tags/' */
+ { NULL, 0 }
+ };
+
+ /* Make the base directory */
+ error = git_futils_mkdir_r(git_dir, NULL, is_bare ?
+ GIT_BARE_DIR_MODE : GIT_DIR_MODE);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to initialize repository structure. Could not mkdir");
/* Hides the ".git" directory */
if (!is_bare) {
@@ -652,67 +710,52 @@ static int repo_init_structure(const char *git_dir, int is_bare)
#endif
}
- /* Creates the '/objects/info/' directory */
- git_path_join(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
- error = git_futils_mkdir_r(temp_path, GIT_OBJECT_DIR_MODE);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to initialize repository structure");
-
- /* Creates the '/objects/pack/' directory */
- git_path_join(temp_path, git_dir, GIT_OBJECTS_PACK_DIR);
- error = p_mkdir(temp_path, GIT_OBJECT_DIR_MODE);
- if (error < GIT_SUCCESS)
- return git__throw(error, "Unable to create `%s` folder", temp_path);
-
- /* Creates the '/refs/heads/' directory */
- git_path_join(temp_path, git_dir, GIT_REFS_HEADS_DIR);
- error = git_futils_mkdir_r(temp_path, GIT_REFS_DIR_MODE);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to initialize repository structure");
-
- /* Creates the '/refs/tags/' directory */
- git_path_join(temp_path, git_dir, GIT_REFS_TAGS_DIR);
- error = p_mkdir(temp_path, GIT_REFS_DIR_MODE);
- if (error < GIT_SUCCESS)
- return git__throw(error, "Unable to create `%s` folder", temp_path);
+ /* Make subdirectories as needed */
+ for (i = 0; dirs[i].dir != NULL; ++i) {
+ error = git_futils_mkdir_r(dirs[i].dir, git_dir, dirs[i].mode);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error,
+ "Failed to create repository folder `%s`", dirs[i].dir);
+ }
/* TODO: what's left? templates? */
- return GIT_SUCCESS;
+ return error;
}
int git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare)
{
int error = GIT_SUCCESS;
git_repository *repo = NULL;
- char repository_path[GIT_PATH_MAX];
+ git_buf repository_path = GIT_BUF_INIT;
assert(repo_out && path);
- git_path_join(repository_path, path, is_bare ? "" : GIT_DIR);
+ error = git_buf_joinpath(&repository_path, path, is_bare ? "" : GIT_DIR);
+ if (error < GIT_SUCCESS)
+ return error;
- if (git_futils_isdir(repository_path)) {
- if (quickcheck_repository_dir(repository_path) == GIT_SUCCESS)
- return repo_init_reinit(repository_path, is_bare);
+ if (git_futils_isdir(repository_path.ptr) == GIT_SUCCESS) {
+ if (quickcheck_repository_dir(&repository_path) == GIT_SUCCESS) {
+ error = repo_init_reinit(repository_path.ptr, is_bare);
+ git_buf_free(&repository_path);
+ return error;
+ }
}
- error = repo_init_structure(repository_path, is_bare);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- error = repo_init_config(repository_path, is_bare);
- if (error < GIT_SUCCESS)
- goto cleanup;
+ if (!(error = repo_init_structure(repository_path.ptr, is_bare)) &&
+ !(error = repo_init_config(repository_path.ptr, is_bare)) &&
+ !(error = repo_init_createhead(repository_path.ptr)))
+ error = git_repository_open(repo_out, repository_path.ptr);
+ else
+ git_repository_free(repo);
- error = repo_init_createhead(repository_path);
- if (error < GIT_SUCCESS)
- goto cleanup;
+ git_buf_free(&repository_path);
- return git_repository_open(repo_out, repository_path);
+ if (error != GIT_SUCCESS)
+ git__rethrow(error, "Failed to (re)init the repository `%s`", path);
-cleanup:
- git_repository_free(repo);
- return git__rethrow(error, "Failed to (re)init the repository `%s`", path);
+ return error;
}
int git_repository_head_detached(git_repository *repo)