mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 17:05:49 +00:00
error-handling: Repository
This also includes droping `git_buf_lasterror` because it makes no sense in the new system. Note that in most of the places were it has been dropped, the code needs cleanup. I.e. GIT_ENOMEM is going away, so instead it should return a generic `-1` and obviously not throw anything.
This commit is contained in:
parent
9d160ba855
commit
cb8a79617b
@ -125,7 +125,7 @@ typedef enum {
|
|||||||
GITERR_OS,
|
GITERR_OS,
|
||||||
GITERR_REFERENCE,
|
GITERR_REFERENCE,
|
||||||
GITERR_ZLIB,
|
GITERR_ZLIB,
|
||||||
|
GITERR_REPOSITORY,
|
||||||
} git_error_class;
|
} git_error_class;
|
||||||
|
|
||||||
#define GITERR_CHECK_ALLOC(ptr) if (ptr == NULL) { return -1; }
|
#define GITERR_CHECK_ALLOC(ptr) if (ptr == NULL) { return -1; }
|
||||||
|
@ -70,7 +70,7 @@ int git_buf_try_grow(git_buf *buf, size_t target_size)
|
|||||||
|
|
||||||
new_ptr = git__realloc(new_ptr, new_size);
|
new_ptr = git__realloc(new_ptr, new_size);
|
||||||
if (!new_ptr)
|
if (!new_ptr)
|
||||||
return GIT_ENOMEM;
|
return -1;
|
||||||
|
|
||||||
buf->asize = new_size;
|
buf->asize = new_size;
|
||||||
buf->ptr = new_ptr;
|
buf->ptr = new_ptr;
|
||||||
@ -100,16 +100,11 @@ void git_buf_clear(git_buf *buf)
|
|||||||
buf->ptr[0] = '\0';
|
buf->ptr[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_buf_oom(const git_buf *buf)
|
bool git_buf_oom(const git_buf *buf)
|
||||||
{
|
{
|
||||||
return (buf->ptr == &git_buf__oom);
|
return (buf->ptr == &git_buf__oom);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_buf_lasterror(const git_buf *buf)
|
|
||||||
{
|
|
||||||
return (buf->ptr == &git_buf__oom) ? GIT_ENOMEM : GIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int git_buf_set(git_buf *buf, const char *data, size_t len)
|
int git_buf_set(git_buf *buf, const char *data, size_t len)
|
||||||
{
|
{
|
||||||
if (len == 0 || data == NULL) {
|
if (len == 0 || data == NULL) {
|
||||||
|
11
src/buffer.h
11
src/buffer.h
@ -57,15 +57,10 @@ void git_buf_attach(git_buf *buf, char *ptr, size_t asize);
|
|||||||
* further calls to modify the buffer will fail. Check git_buf_oom() at the
|
* further calls to modify the buffer will fail. Check git_buf_oom() at the
|
||||||
* end of your sequence and it will be true if you ran out of memory at any
|
* end of your sequence and it will be true if you ran out of memory at any
|
||||||
* point with that buffer.
|
* point with that buffer.
|
||||||
* @return 0 if no error, 1 if allocation error.
|
*
|
||||||
|
* @return false if no error, true if allocation error
|
||||||
*/
|
*/
|
||||||
int git_buf_oom(const git_buf *buf);
|
bool git_buf_oom(const git_buf *buf);
|
||||||
|
|
||||||
/**
|
|
||||||
* Just like git_buf_oom, except returns appropriate error code.
|
|
||||||
* @return GIT_ENOMEM if allocation error, GIT_SUCCESS if not.
|
|
||||||
*/
|
|
||||||
int git_buf_lasterror(const git_buf *buf);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The functions below that return int values, will return GIT_ENOMEM
|
* The functions below that return int values, will return GIT_ENOMEM
|
||||||
|
@ -129,7 +129,7 @@ int git_commit_create(
|
|||||||
git_buf_puts(&commit, message);
|
git_buf_puts(&commit, message);
|
||||||
|
|
||||||
if (git_buf_oom(&commit)) {
|
if (git_buf_oom(&commit)) {
|
||||||
error = git__throw(git_buf_lasterror(&commit),
|
error = git__throw(GIT_ENOMEM,
|
||||||
"Not enough memory to build the commit data");
|
"Not enough memory to build the commit data");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -128,8 +128,7 @@ static int drop_crlf(git_buf *dest, const git_buf *source)
|
|||||||
|
|
||||||
/* Copy remaining input into dest */
|
/* Copy remaining input into dest */
|
||||||
git_buf_put(dest, scan, scan_end - scan);
|
git_buf_put(dest, scan, scan_end - scan);
|
||||||
|
return 0;
|
||||||
return git_buf_lasterror(dest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int crlf_apply_to_odb(git_filter *self, git_buf *dest, const git_buf *source)
|
static int crlf_apply_to_odb(git_filter *self, git_buf *dest, const git_buf *source)
|
||||||
|
@ -482,8 +482,8 @@ static int print_compact(void *data, git_diff_delta *delta, float progress)
|
|||||||
else
|
else
|
||||||
git_buf_printf(pi->buf, "%c\t%s\n", code, delta->old.path);
|
git_buf_printf(pi->buf, "%c\t%s\n", code, delta->old.path);
|
||||||
|
|
||||||
if (git_buf_lasterror(pi->buf) != GIT_SUCCESS)
|
if (git_buf_oom(pi->buf) == true)
|
||||||
return git_buf_lasterror(pi->buf);
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr);
|
return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr);
|
||||||
}
|
}
|
||||||
@ -534,7 +534,10 @@ static int print_oid_range(diff_print_info *pi, git_diff_delta *delta)
|
|||||||
git_buf_printf(pi->buf, "index %s..%s\n", start_oid, end_oid);
|
git_buf_printf(pi->buf, "index %s..%s\n", start_oid, end_oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return git_buf_lasterror(pi->buf);
|
if (git_buf_oom(pi->buf))
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int print_patch_file(void *data, git_diff_delta *delta, float progress)
|
static int print_patch_file(void *data, git_diff_delta *delta, float progress)
|
||||||
@ -567,8 +570,8 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress)
|
|||||||
git_buf_printf(pi->buf, "+++ %s%s\n", newpfx, newpath);
|
git_buf_printf(pi->buf, "+++ %s%s\n", newpfx, newpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (git_buf_lasterror(pi->buf) != GIT_SUCCESS)
|
if (git_buf_oom(pi->buf))
|
||||||
return git_buf_lasterror(pi->buf);
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
error = pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr);
|
error = pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr);
|
||||||
if (error != GIT_SUCCESS || delta->binary != 1)
|
if (error != GIT_SUCCESS || delta->binary != 1)
|
||||||
@ -578,8 +581,8 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress)
|
|||||||
git_buf_printf(
|
git_buf_printf(
|
||||||
pi->buf, "Binary files %s%s and %s%s differ\n",
|
pi->buf, "Binary files %s%s and %s%s differ\n",
|
||||||
oldpfx, oldpath, newpfx, newpath);
|
oldpfx, oldpath, newpfx, newpath);
|
||||||
if (git_buf_lasterror(pi->buf) != GIT_SUCCESS)
|
if (git_buf_oom(pi->buf))
|
||||||
return git_buf_lasterror(pi->buf);
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_BINARY, pi->buf->ptr);
|
return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_BINARY, pi->buf->ptr);
|
||||||
}
|
}
|
||||||
@ -601,7 +604,7 @@ static int print_patch_hunk(
|
|||||||
if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) == GIT_SUCCESS)
|
if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) == GIT_SUCCESS)
|
||||||
return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_HUNK_HDR, pi->buf->ptr);
|
return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_HUNK_HDR, pi->buf->ptr);
|
||||||
else
|
else
|
||||||
return git_buf_lasterror(pi->buf);
|
return GIT_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int print_patch_line(
|
static int print_patch_line(
|
||||||
@ -624,8 +627,8 @@ static int print_patch_line(
|
|||||||
else if (content_len > 0)
|
else if (content_len > 0)
|
||||||
git_buf_printf(pi->buf, "%.*s", (int)content_len, content);
|
git_buf_printf(pi->buf, "%.*s", (int)content_len, content);
|
||||||
|
|
||||||
if (git_buf_lasterror(pi->buf) != GIT_SUCCESS)
|
if (git_buf_oom(pi->buf))
|
||||||
return git_buf_lasterror(pi->buf);
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
return pi->print_cb(pi->cb_data, line_origin, pi->buf->ptr);
|
return pi->print_cb(pi->cb_data, line_origin, pi->buf->ptr);
|
||||||
}
|
}
|
||||||
|
@ -211,20 +211,21 @@ void git_futils_mmap_free(git_map *out)
|
|||||||
|
|
||||||
int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode)
|
int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode)
|
||||||
{
|
{
|
||||||
int error, root_path_offset;
|
int root_path_offset;
|
||||||
git_buf make_path = GIT_BUF_INIT;
|
git_buf make_path = GIT_BUF_INIT;
|
||||||
size_t start;
|
size_t start;
|
||||||
char *pp, *sp;
|
char *pp, *sp;
|
||||||
|
bool failed = false;
|
||||||
|
|
||||||
if (base != NULL) {
|
if (base != NULL) {
|
||||||
start = strlen(base);
|
start = strlen(base);
|
||||||
error = git_buf_joinpath(&make_path, base, path);
|
if (git_buf_joinpath(&make_path, base, path) < 0)
|
||||||
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
start = 0;
|
start = 0;
|
||||||
error = git_buf_puts(&make_path, path);
|
if (git_buf_puts(&make_path, path) < 0)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
return git__rethrow(error, "Failed to create `%s` tree structure", path);
|
|
||||||
|
|
||||||
pp = make_path.ptr + start;
|
pp = make_path.ptr + start;
|
||||||
|
|
||||||
@ -232,14 +233,13 @@ int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode)
|
|||||||
if (root_path_offset > 0)
|
if (root_path_offset > 0)
|
||||||
pp += root_path_offset; /* On Windows, will skip the drive name (eg. C: or D:) */
|
pp += root_path_offset; /* On Windows, will skip the drive name (eg. C: or D:) */
|
||||||
|
|
||||||
while (error == GIT_SUCCESS && (sp = strchr(pp, '/')) != NULL) {
|
while (!failed && (sp = strchr(pp, '/')) != NULL) {
|
||||||
if (sp != pp && git_path_isdir(make_path.ptr) == false) {
|
if (sp != pp && git_path_isdir(make_path.ptr) == false) {
|
||||||
*sp = 0;
|
*sp = 0;
|
||||||
error = p_mkdir(make_path.ptr, mode);
|
|
||||||
|
|
||||||
/* Do not choke while trying to recreate an existing directory */
|
/* Do not choke while trying to recreate an existing directory */
|
||||||
if (errno == EEXIST)
|
if (p_mkdir(make_path.ptr, mode) < 0 && errno != EEXIST)
|
||||||
error = GIT_SUCCESS;
|
failed = true;
|
||||||
|
|
||||||
*sp = '/';
|
*sp = '/';
|
||||||
}
|
}
|
||||||
@ -247,18 +247,20 @@ int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode)
|
|||||||
pp = sp + 1;
|
pp = sp + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*pp != '\0' && error == GIT_SUCCESS) {
|
if (*pp != '\0' && !failed) {
|
||||||
error = p_mkdir(make_path.ptr, mode);
|
if (p_mkdir(make_path.ptr, mode) < 0 && errno != EEXIST)
|
||||||
if (errno == EEXIST)
|
failed = true;
|
||||||
error = GIT_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
git_buf_free(&make_path);
|
git_buf_free(&make_path);
|
||||||
|
|
||||||
if (error < GIT_SUCCESS)
|
if (failed) {
|
||||||
return git__throw(error, "Failed to recursively create `%s` tree structure", path);
|
giterr_set(GITERR_OS,
|
||||||
|
"Failed to create directory structure at '%s'", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _rmdir_recurs_foreach(void *opaque, git_buf *path)
|
static int _rmdir_recurs_foreach(void *opaque, git_buf *path)
|
||||||
@ -407,8 +409,8 @@ cleanup:
|
|||||||
|
|
||||||
int git_futils_find_system_file(git_buf *path, const char *filename)
|
int git_futils_find_system_file(git_buf *path, const char *filename)
|
||||||
{
|
{
|
||||||
if (git_buf_joinpath(path, "/etc", filename) < GIT_SUCCESS)
|
if (git_buf_joinpath(path, "/etc", filename) < 0)
|
||||||
return git_buf_lasterror(path);
|
return -1;
|
||||||
|
|
||||||
if (git_path_exists(path->ptr) == true)
|
if (git_path_exists(path->ptr) == true)
|
||||||
return GIT_SUCCESS;
|
return GIT_SUCCESS;
|
||||||
|
@ -171,7 +171,10 @@ static int index_path(git_buf *path, git_indexer *idx)
|
|||||||
path->size += GIT_OID_HEXSZ;
|
path->size += GIT_OID_HEXSZ;
|
||||||
git_buf_puts(path, suffix);
|
git_buf_puts(path, suffix);
|
||||||
|
|
||||||
return git_buf_lasterror(path);
|
if (git_buf_oom(path))
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_indexer_write(git_indexer *idx)
|
int git_indexer_write(git_indexer *idx)
|
||||||
@ -192,8 +195,8 @@ int git_indexer_write(git_indexer *idx)
|
|||||||
git_buf_truncate(&filename, filename.size - strlen("pack"));
|
git_buf_truncate(&filename, filename.size - strlen("pack"));
|
||||||
git_buf_puts(&filename, "idx");
|
git_buf_puts(&filename, "idx");
|
||||||
|
|
||||||
if ((error = git_buf_lasterror(&filename)) < GIT_SUCCESS)
|
if (git_buf_oom(&filename))
|
||||||
goto cleanup;
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
error = git_filebuf_open(&idx->file, filename.ptr, GIT_FILEBUF_HASH_CONTENTS);
|
error = git_filebuf_open(&idx->file, filename.ptr, GIT_FILEBUF_HASH_CONTENTS);
|
||||||
if (error < GIT_SUCCESS)
|
if (error < GIT_SUCCESS)
|
||||||
|
@ -387,8 +387,8 @@ static int read_loose(git_rawobj *out, git_buf *loc)
|
|||||||
|
|
||||||
assert(out && loc);
|
assert(out && loc);
|
||||||
|
|
||||||
if ((error = git_buf_lasterror(loc)) < GIT_SUCCESS)
|
if (git_buf_oom(loc))
|
||||||
return error;
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
out->data = NULL;
|
out->data = NULL;
|
||||||
out->len = 0;
|
out->len = 0;
|
||||||
@ -413,8 +413,8 @@ static int read_header_loose(git_rawobj *out, git_buf *loc)
|
|||||||
|
|
||||||
assert(out && loc);
|
assert(out && loc);
|
||||||
|
|
||||||
if ((error = git_buf_lasterror(loc)) < GIT_SUCCESS)
|
if (git_buf_oom(loc))
|
||||||
return error;
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
out->data = NULL;
|
out->data = NULL;
|
||||||
|
|
||||||
@ -704,8 +704,8 @@ static int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream)
|
|||||||
if ((error = object_file_name(&final_path, backend->objects_dir, oid)) < GIT_SUCCESS)
|
if ((error = object_file_name(&final_path, backend->objects_dir, oid)) < GIT_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if ((error = git_buf_lasterror(&final_path)) < GIT_SUCCESS)
|
if (git_buf_oom(&final_path))
|
||||||
goto cleanup;
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
if ((error = git_futils_mkpath2file(final_path.ptr, GIT_OBJECT_DIR_MODE)) < GIT_SUCCESS)
|
if ((error = git_futils_mkpath2file(final_path.ptr, GIT_OBJECT_DIR_MODE)) < GIT_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
39
src/path.c
39
src/path.c
@ -56,7 +56,7 @@ Exit:
|
|||||||
|
|
||||||
if (buffer != NULL) {
|
if (buffer != NULL) {
|
||||||
if (git_buf_set(buffer, startp, len) < GIT_SUCCESS)
|
if (git_buf_set(buffer, startp, len) < GIT_SUCCESS)
|
||||||
return git__rethrow(git_buf_lasterror(buffer),
|
return git__rethrow(GIT_ENOMEM,
|
||||||
"Could not get basename of '%s'", path);
|
"Could not get basename of '%s'", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ Exit:
|
|||||||
|
|
||||||
if (buffer != NULL) {
|
if (buffer != NULL) {
|
||||||
if (git_buf_set(buffer, path, len) < GIT_SUCCESS)
|
if (git_buf_set(buffer, path, len) < GIT_SUCCESS)
|
||||||
return git__rethrow(git_buf_lasterror(buffer),
|
return git__rethrow(GIT_ENOMEM,
|
||||||
"Could not get dirname of '%s'", path);
|
"Could not get dirname of '%s'", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,34 +185,36 @@ int git_path_root(const char *path)
|
|||||||
|
|
||||||
int git_path_prettify(git_buf *path_out, const char *path, const char *base)
|
int git_path_prettify(git_buf *path_out, const char *path, const char *base)
|
||||||
{
|
{
|
||||||
int error = GIT_SUCCESS;
|
|
||||||
char buf[GIT_PATH_MAX];
|
char buf[GIT_PATH_MAX];
|
||||||
|
|
||||||
|
assert(path && path_out);
|
||||||
git_buf_clear(path_out);
|
git_buf_clear(path_out);
|
||||||
|
|
||||||
/* construct path if needed */
|
/* construct path if needed */
|
||||||
if (base != NULL && git_path_root(path) < 0) {
|
if (base != NULL && git_path_root(path) < 0) {
|
||||||
if ((error = git_buf_joinpath(path_out, base, path)) < GIT_SUCCESS)
|
if (git_buf_joinpath(path_out, base, path) < 0)
|
||||||
return error;
|
return -1;
|
||||||
|
|
||||||
path = path_out->ptr;
|
path = path_out->ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path == NULL || p_realpath(path, buf) == NULL)
|
if (p_realpath(path, buf) == NULL) {
|
||||||
error = GIT_EOSERR;
|
giterr_set(GITERR_OS, "Failed to resolve path '%s': %s", path, strerror(errno));
|
||||||
else
|
return (errno == ENOENT) ? GIT_ENOTFOUND : -1;
|
||||||
error = git_buf_sets(path_out, buf);
|
}
|
||||||
|
|
||||||
return error;
|
if (git_buf_sets(path_out, buf) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_path_prettify_dir(git_buf *path_out, const char *path, const char *base)
|
int git_path_prettify_dir(git_buf *path_out, const char *path, const char *base)
|
||||||
{
|
{
|
||||||
int error = git_path_prettify(path_out, path, base);
|
if (git_path_prettify(path_out, path, base) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (error == GIT_SUCCESS)
|
return git_path_to_dir(path_out);
|
||||||
error = git_path_to_dir(path_out);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_path_to_dir(git_buf *path)
|
int git_path_to_dir(git_buf *path)
|
||||||
@ -222,7 +224,10 @@ int git_path_to_dir(git_buf *path)
|
|||||||
path->ptr[path->size - 1] != '/')
|
path->ptr[path->size - 1] != '/')
|
||||||
git_buf_putc(path, '/');
|
git_buf_putc(path, '/');
|
||||||
|
|
||||||
return git_buf_lasterror(path);
|
if (git_buf_oom(path))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_path_string_to_dir(char* path, size_t size)
|
void git_path_string_to_dir(char* path, size_t size)
|
||||||
@ -445,7 +450,7 @@ int git_path_find_dir(git_buf *dir, const char *path, const char *base)
|
|||||||
/* call dirname if this is not a directory */
|
/* call dirname if this is not a directory */
|
||||||
if (error == GIT_SUCCESS && git_path_isdir(dir->ptr) == false)
|
if (error == GIT_SUCCESS && git_path_isdir(dir->ptr) == false)
|
||||||
if (git_path_dirname_r(dir, dir->ptr) < GIT_SUCCESS)
|
if (git_path_dirname_r(dir, dir->ptr) < GIT_SUCCESS)
|
||||||
error = git_buf_lasterror(dir);
|
error = GIT_ENOMEM;
|
||||||
|
|
||||||
if (error == GIT_SUCCESS)
|
if (error == GIT_SUCCESS)
|
||||||
error = git_path_to_dir(dir);
|
error = git_path_to_dir(dir);
|
||||||
|
@ -65,9 +65,9 @@ static int reflog_write(const char *log_path, const char *oid_old,
|
|||||||
|
|
||||||
git_buf_putc(&log, '\n');
|
git_buf_putc(&log, '\n');
|
||||||
|
|
||||||
if ((error = git_buf_lasterror(&log)) < GIT_SUCCESS) {
|
if (git_buf_oom(&log)) {
|
||||||
git_buf_free(&log);
|
git_buf_free(&log);
|
||||||
return git__rethrow(error, "Failed to write reflog. Memory allocation failure");
|
return git__throw(GIT_ENOMEM, "Failed to write reflog. Memory allocation failure");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = git_filebuf_open(&fbuf, log_path, GIT_FILEBUF_APPEND)) < GIT_SUCCESS) {
|
if ((error = git_filebuf_open(&fbuf, log_path, GIT_FILEBUF_APPEND)) < GIT_SUCCESS) {
|
||||||
|
@ -97,7 +97,7 @@ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, con
|
|||||||
int git_refspec_transform_r(git_buf *out, const git_refspec *spec, const char *name)
|
int git_refspec_transform_r(git_buf *out, const git_refspec *spec, const char *name)
|
||||||
{
|
{
|
||||||
if (git_buf_sets(out, spec->dst) < GIT_SUCCESS)
|
if (git_buf_sets(out, spec->dst) < GIT_SUCCESS)
|
||||||
return git_buf_lasterror(out);
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No '*' at the end means that it's mapped to one specific local
|
* No '*' at the end means that it's mapped to one specific local
|
||||||
@ -109,5 +109,9 @@ int git_refspec_transform_r(git_buf *out, const git_refspec *spec, const char *n
|
|||||||
git_buf_truncate(out, out->size - 1); /* remove trailing '*' */
|
git_buf_truncate(out, out->size - 1); /* remove trailing '*' */
|
||||||
git_buf_puts(out, name + strlen(spec->src) - 1);
|
git_buf_puts(out, name + strlen(spec->src) - 1);
|
||||||
|
|
||||||
return git_buf_lasterror(out);
|
if (git_buf_oom(out))
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
541
src/repository.c
541
src/repository.c
@ -80,35 +80,31 @@ void git_repository_free(git_repository *repo)
|
|||||||
*
|
*
|
||||||
* Open a repository object from its path
|
* Open a repository object from its path
|
||||||
*/
|
*/
|
||||||
static int quickcheck_repository_dir(git_buf *repository_path)
|
static bool valid_repository_path(git_buf *repository_path)
|
||||||
{
|
{
|
||||||
/* Check OBJECTS_DIR first, since it will generate the longest path name */
|
/* Check OBJECTS_DIR first, since it will generate the longest path name */
|
||||||
if (git_path_contains_dir(repository_path, GIT_OBJECTS_DIR) == false)
|
if (git_path_contains_dir(repository_path, GIT_OBJECTS_DIR) == false)
|
||||||
return GIT_ERROR;
|
return false;
|
||||||
|
|
||||||
/* Ensure HEAD file exists */
|
/* Ensure HEAD file exists */
|
||||||
if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false)
|
if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false)
|
||||||
return GIT_ERROR;
|
return false;
|
||||||
|
|
||||||
if (git_path_contains_dir(repository_path, GIT_REFS_DIR) == false)
|
if (git_path_contains_dir(repository_path, GIT_REFS_DIR) == false)
|
||||||
return GIT_ERROR;
|
return false;
|
||||||
|
|
||||||
return GIT_SUCCESS;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static git_repository *repository_alloc(void)
|
static git_repository *repository_alloc(void)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
|
|
||||||
git_repository *repo = git__malloc(sizeof(git_repository));
|
git_repository *repo = git__malloc(sizeof(git_repository));
|
||||||
if (!repo)
|
if (!repo)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memset(repo, 0x0, sizeof(git_repository));
|
memset(repo, 0x0, sizeof(git_repository));
|
||||||
|
|
||||||
error = git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free);
|
if (git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free) < 0) {
|
||||||
if (error < GIT_SUCCESS) {
|
|
||||||
git__free(repo);
|
git__free(repo);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -121,50 +117,48 @@ static git_repository *repository_alloc(void)
|
|||||||
|
|
||||||
static int load_config_data(git_repository *repo)
|
static int load_config_data(git_repository *repo)
|
||||||
{
|
{
|
||||||
int error, is_bare;
|
int is_bare;
|
||||||
git_config *config;
|
git_config *config;
|
||||||
|
|
||||||
error = git_repository_config__weakptr(&config, repo);
|
if (git_repository_config__weakptr(&config, repo) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return error;
|
|
||||||
|
|
||||||
error = git_config_get_bool(config, "core.bare", &is_bare);
|
if (git_config_get_bool(config, "core.bare", &is_bare) < 0)
|
||||||
if (error == GIT_SUCCESS)
|
return -1; /* FIXME: We assume that a missing core.bare
|
||||||
repo->is_bare = is_bare;
|
variable is an error. Is this right? */
|
||||||
|
|
||||||
/* TODO: what else can we load/cache here? */
|
repo->is_bare = is_bare;
|
||||||
|
return 0;
|
||||||
return GIT_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_workdir(git_repository *repo)
|
static int load_workdir(git_repository *repo)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
git_buf workdir_buf = GIT_BUF_INIT;
|
git_buf workdir_buf = GIT_BUF_INIT;
|
||||||
|
|
||||||
if (repo->is_bare)
|
if (repo->is_bare)
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
|
|
||||||
git_path_dirname_r(&workdir_buf, repo->path_repository);
|
git_path_dirname_r(&workdir_buf, repo->path_repository);
|
||||||
git_path_to_dir(&workdir_buf);
|
git_path_to_dir(&workdir_buf);
|
||||||
|
|
||||||
if ((error = git_buf_lasterror(&workdir_buf)) == GIT_SUCCESS)
|
if (git_buf_oom(&workdir_buf))
|
||||||
repo->workdir = git_buf_detach(&workdir_buf);
|
return -1;
|
||||||
|
|
||||||
|
repo->workdir = git_buf_detach(&workdir_buf);
|
||||||
git_buf_free(&workdir_buf);
|
git_buf_free(&workdir_buf);
|
||||||
|
|
||||||
return error;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_repository_open(git_repository **repo_out, const char *path)
|
int git_repository_open(git_repository **repo_out, const char *path)
|
||||||
{
|
{
|
||||||
int error = GIT_SUCCESS;
|
|
||||||
git_buf path_buf = GIT_BUF_INIT;
|
git_buf path_buf = GIT_BUF_INIT;
|
||||||
git_repository *repo = NULL;
|
git_repository *repo = NULL;
|
||||||
|
int res;
|
||||||
|
|
||||||
error = git_path_prettify_dir(&path_buf, path, NULL);
|
res = git_path_prettify_dir(&path_buf, path, NULL);
|
||||||
if (error < GIT_SUCCESS)
|
if (res < 0)
|
||||||
goto cleanup;
|
return res;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the path we've been given is actually the path
|
* Check if the path we've been given is actually the path
|
||||||
@ -174,39 +168,32 @@ int git_repository_open(git_repository **repo_out, const char *path)
|
|||||||
if (git_path_contains_dir(&path_buf, GIT_DIR) == true)
|
if (git_path_contains_dir(&path_buf, GIT_DIR) == true)
|
||||||
git_buf_joinpath(&path_buf, path_buf.ptr, GIT_DIR);
|
git_buf_joinpath(&path_buf, path_buf.ptr, GIT_DIR);
|
||||||
|
|
||||||
if (quickcheck_repository_dir(&path_buf) < GIT_SUCCESS) {
|
if (valid_repository_path(&path_buf) == false) {
|
||||||
error = git__throw(GIT_ENOTAREPO,
|
giterr_set(GITERR_REPOSITORY,
|
||||||
"The given path (%s) is not a valid Git repository", git_buf_cstr(&path_buf));
|
"The given path (%s) is not a valid Git repository", git_buf_cstr(&path_buf));
|
||||||
goto cleanup;
|
git_buf_free(&path_buf);
|
||||||
|
return GIT_ENOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
repo = repository_alloc();
|
repo = repository_alloc();
|
||||||
if (repo == NULL) {
|
GITERR_CHECK_ALLOC(repo);
|
||||||
error = GIT_ENOMEM;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
repo->path_repository = git_buf_detach(&path_buf);
|
repo->path_repository = git_buf_detach(&path_buf);
|
||||||
if (repo->path_repository == NULL) {
|
GITERR_CHECK_ALLOC(repo->path_repository);
|
||||||
error = GIT_ENOMEM;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = load_config_data(repo);
|
if (load_config_data(repo) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
error = load_workdir(repo);
|
if (load_workdir(repo) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
*repo_out = repo;
|
*repo_out = repo;
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
git_repository_free(repo);
|
git_repository_free(repo);
|
||||||
git_buf_free(&path_buf);
|
git_buf_free(&path_buf);
|
||||||
return error;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_config(
|
static int load_config(
|
||||||
@ -216,85 +203,79 @@ static int load_config(
|
|||||||
const char *system_config_path)
|
const char *system_config_path)
|
||||||
{
|
{
|
||||||
git_buf config_path = GIT_BUF_INIT;
|
git_buf config_path = GIT_BUF_INIT;
|
||||||
int error;
|
|
||||||
git_config *cfg = NULL;
|
git_config *cfg = NULL;
|
||||||
|
|
||||||
assert(repo && out);
|
assert(repo && out);
|
||||||
|
|
||||||
error = git_config_new(&cfg);
|
if (git_config_new(&cfg) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return error;
|
|
||||||
|
|
||||||
error = git_buf_joinpath(&config_path, repo->path_repository,
|
if (git_buf_joinpath(
|
||||||
GIT_CONFIG_FILENAME_INREPO);
|
&config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
goto on_error;
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
error = git_config_add_file_ondisk(cfg, config_path.ptr, 3);
|
if (git_config_add_file_ondisk(cfg, config_path.ptr, 3) < 0)
|
||||||
git_buf_free(&config_path); /* done with config_path now */
|
goto on_error;
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
goto cleanup;
|
git_buf_free(&config_path);
|
||||||
|
|
||||||
if (global_config_path != NULL) {
|
if (global_config_path != NULL) {
|
||||||
error = git_config_add_file_ondisk(cfg, global_config_path, 2);
|
if (git_config_add_file_ondisk(cfg, global_config_path, 2) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
goto on_error;
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system_config_path != NULL) {
|
if (system_config_path != NULL) {
|
||||||
error = git_config_add_file_ondisk(cfg, system_config_path, 1);
|
if (git_config_add_file_ondisk(cfg, system_config_path, 1) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
goto on_error;
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = cfg;
|
*out = cfg;
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
|
|
||||||
cleanup:
|
on_error:
|
||||||
|
git_buf_free(&config_path);
|
||||||
git_config_free(cfg);
|
git_config_free(cfg);
|
||||||
*out = NULL;
|
*out = NULL;
|
||||||
return error;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_repository_config__weakptr(git_config **out, git_repository *repo)
|
int git_repository_config__weakptr(git_config **out, git_repository *repo)
|
||||||
{
|
{
|
||||||
if (repo->_config == NULL) {
|
if (repo->_config == NULL) {
|
||||||
int error;
|
|
||||||
git_buf global_buf = GIT_BUF_INIT, system_buf = GIT_BUF_INIT;
|
git_buf global_buf = GIT_BUF_INIT, system_buf = GIT_BUF_INIT;
|
||||||
|
int res;
|
||||||
|
|
||||||
const char *global_config_path = NULL;
|
const char *global_config_path = NULL;
|
||||||
const char *system_config_path = NULL;
|
const char *system_config_path = NULL;
|
||||||
|
|
||||||
if (git_config_find_global_r(&global_buf) == GIT_SUCCESS)
|
if (git_config_find_global_r(&global_buf) == 0)
|
||||||
global_config_path = global_buf.ptr;
|
global_config_path = global_buf.ptr;
|
||||||
|
|
||||||
if (git_config_find_system_r(&system_buf) == GIT_SUCCESS)
|
if (git_config_find_system_r(&system_buf) == 0)
|
||||||
system_config_path = system_buf.ptr;
|
system_config_path = system_buf.ptr;
|
||||||
|
|
||||||
error = load_config(&repo->_config, repo, global_config_path, system_config_path);
|
res = load_config(&repo->_config, repo, global_config_path, system_config_path);
|
||||||
|
|
||||||
git_buf_free(&global_buf);
|
git_buf_free(&global_buf);
|
||||||
git_buf_free(&system_buf);
|
git_buf_free(&system_buf);
|
||||||
|
|
||||||
if (error < GIT_SUCCESS)
|
if (res < 0)
|
||||||
return error;
|
return -1;
|
||||||
|
|
||||||
GIT_REFCOUNT_OWN(repo->_config, repo);
|
GIT_REFCOUNT_OWN(repo->_config, repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = repo->_config;
|
*out = repo->_config;
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_repository_config(git_config **out, git_repository *repo)
|
int git_repository_config(git_config **out, git_repository *repo)
|
||||||
{
|
{
|
||||||
int error = git_repository_config__weakptr(out, repo);
|
if (git_repository_config__weakptr(out, repo) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (error == GIT_SUCCESS) {
|
GIT_REFCOUNT_INC(*out);
|
||||||
GIT_REFCOUNT_INC(*out);
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_repository_set_config(git_repository *repo, git_config *config)
|
void git_repository_set_config(git_repository *repo, git_config *config)
|
||||||
@ -312,34 +293,32 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
|
|||||||
assert(repo && out);
|
assert(repo && out);
|
||||||
|
|
||||||
if (repo->_odb == NULL) {
|
if (repo->_odb == NULL) {
|
||||||
int error;
|
|
||||||
git_buf odb_path = GIT_BUF_INIT;
|
git_buf odb_path = GIT_BUF_INIT;
|
||||||
|
int res;
|
||||||
|
|
||||||
error = git_buf_joinpath(&odb_path, repo->path_repository, GIT_OBJECTS_DIR);
|
if (git_buf_joinpath(&odb_path, repo->path_repository, GIT_OBJECTS_DIR) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return error;
|
|
||||||
|
|
||||||
error = git_odb_open(&repo->_odb, odb_path.ptr);
|
res = git_odb_open(&repo->_odb, odb_path.ptr);
|
||||||
git_buf_free(&odb_path); /* done with path */
|
git_buf_free(&odb_path); /* done with path */
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
return error;
|
if (res < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
GIT_REFCOUNT_OWN(repo->_odb, repo);
|
GIT_REFCOUNT_OWN(repo->_odb, repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = repo->_odb;
|
*out = repo->_odb;
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_repository_odb(git_odb **out, git_repository *repo)
|
int git_repository_odb(git_odb **out, git_repository *repo)
|
||||||
{
|
{
|
||||||
int error = git_repository_odb__weakptr(out, repo);
|
if (git_repository_odb__weakptr(out, repo) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (error == GIT_SUCCESS) {
|
GIT_REFCOUNT_INC(*out);
|
||||||
GIT_REFCOUNT_INC(*out);
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_repository_set_odb(git_repository *repo, git_odb *odb)
|
void git_repository_set_odb(git_repository *repo, git_odb *odb)
|
||||||
@ -357,34 +336,32 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
|
|||||||
assert(out && repo);
|
assert(out && repo);
|
||||||
|
|
||||||
if (repo->_index == NULL) {
|
if (repo->_index == NULL) {
|
||||||
int error;
|
int res;
|
||||||
git_buf index_path = GIT_BUF_INIT;
|
git_buf index_path = GIT_BUF_INIT;
|
||||||
|
|
||||||
error = git_buf_joinpath(&index_path, repo->path_repository, GIT_INDEX_FILE);
|
if (git_buf_joinpath(&index_path, repo->path_repository, GIT_INDEX_FILE) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return error;
|
|
||||||
|
|
||||||
error = git_index_open(&repo->_index, index_path.ptr);
|
res = git_index_open(&repo->_index, index_path.ptr);
|
||||||
git_buf_free(&index_path); /* done with path */
|
git_buf_free(&index_path); /* done with path */
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
return error;
|
if (res < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
GIT_REFCOUNT_OWN(repo->_index, repo);
|
GIT_REFCOUNT_OWN(repo->_index, repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = repo->_index;
|
*out = repo->_index;
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_repository_index(git_index **out, git_repository *repo)
|
int git_repository_index(git_index **out, git_repository *repo)
|
||||||
{
|
{
|
||||||
int error = git_repository_index__weakptr(out, repo);
|
if (git_repository_index__weakptr(out, repo) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (error == GIT_SUCCESS) {
|
GIT_REFCOUNT_INC(*out);
|
||||||
GIT_REFCOUNT_INC(*out);
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_repository_set_index(git_repository *repo, git_index *index)
|
void git_repository_set_index(git_repository *repo, git_index *index)
|
||||||
@ -404,12 +381,13 @@ static int retrieve_device(dev_t *device_out, const char *path)
|
|||||||
|
|
||||||
assert(device_out);
|
assert(device_out);
|
||||||
|
|
||||||
if (p_lstat(path, &path_info))
|
if (p_lstat(path, &path_info)) {
|
||||||
return git__throw(GIT_EOSERR, "Failed to get file informations: %s", path);
|
giterr_set(GITERR_OS, "Failed to retrieve file information: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
*device_out = path_info.st_dev;
|
*device_out = path_info.st_dev;
|
||||||
|
return 0;
|
||||||
return GIT_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -473,35 +451,31 @@ static int retrieve_ceiling_directories_offset(
|
|||||||
static int read_gitfile(git_buf *path_out, const char *file_path, const char *base_path)
|
static int read_gitfile(git_buf *path_out, const char *file_path, const char *base_path)
|
||||||
{
|
{
|
||||||
git_buf file = GIT_BUF_INIT;
|
git_buf file = GIT_BUF_INIT;
|
||||||
int error;
|
|
||||||
|
|
||||||
assert(path_out && file_path);
|
assert(path_out && file_path);
|
||||||
|
|
||||||
error = git_futils_readbuffer(&file, file_path);
|
if (git_futils_readbuffer(&file, file_path) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return error;
|
|
||||||
|
|
||||||
if (git__prefixcmp((char *)file.ptr, GIT_FILE_CONTENT_PREFIX)) {
|
|
||||||
git_buf_free(&file);
|
|
||||||
return git__throw(GIT_ENOTFOUND, "Invalid gitfile format `%s`", file_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
git_buf_rtrim(&file);
|
git_buf_rtrim(&file);
|
||||||
|
|
||||||
if (strlen(GIT_FILE_CONTENT_PREFIX) == file.size) {
|
if (git__prefixcmp((char *)file.ptr, GIT_FILE_CONTENT_PREFIX) != 0 ||
|
||||||
|
strlen(GIT_FILE_CONTENT_PREFIX) == file.size) {
|
||||||
git_buf_free(&file);
|
git_buf_free(&file);
|
||||||
return git__throw(GIT_ENOTFOUND, "No path in git file `%s`", file_path);
|
giterr_set(GITERR_REPOSITORY, "The `.git` file at '%s' is corrupted", file_path);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = git_path_prettify_dir(path_out,
|
if (git_path_prettify_dir(path_out,
|
||||||
((char *)file.ptr) + strlen(GIT_FILE_CONTENT_PREFIX), base_path);
|
((char *)file.ptr) + strlen(GIT_FILE_CONTENT_PREFIX), base_path) < 0) {
|
||||||
|
git_buf_free(&file);
|
||||||
|
giterr_set(GITERR_REPOSITORY,
|
||||||
|
"The `.git` file at '%s' points to an invalid path.", file_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
git_buf_free(&file);
|
git_buf_free(&file);
|
||||||
|
return 0;
|
||||||
if (error == GIT_SUCCESS && git_path_exists(path_out->ptr) == true)
|
|
||||||
return GIT_SUCCESS;
|
|
||||||
|
|
||||||
return git__throw(GIT_EOBJCORRUPTED, "The `.git` file points to a nonexistent path");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_repository_discover(
|
int git_repository_discover(
|
||||||
@ -511,7 +485,7 @@ int git_repository_discover(
|
|||||||
int across_fs,
|
int across_fs,
|
||||||
const char *ceiling_dirs)
|
const char *ceiling_dirs)
|
||||||
{
|
{
|
||||||
int error, ceiling_offset;
|
int res, ceiling_offset;
|
||||||
git_buf bare_path = GIT_BUF_INIT;
|
git_buf bare_path = GIT_BUF_INIT;
|
||||||
git_buf normal_path = GIT_BUF_INIT;
|
git_buf normal_path = GIT_BUF_INIT;
|
||||||
git_buf *found_path = NULL;
|
git_buf *found_path = NULL;
|
||||||
@ -521,22 +495,20 @@ int git_repository_discover(
|
|||||||
|
|
||||||
*repository_path = '\0';
|
*repository_path = '\0';
|
||||||
|
|
||||||
error = git_path_prettify_dir(&bare_path, start_path, NULL);
|
res = git_path_prettify_dir(&bare_path, start_path, NULL);
|
||||||
if (error < GIT_SUCCESS)
|
if (res < 0)
|
||||||
goto cleanup;
|
return res;
|
||||||
|
|
||||||
if (!across_fs) {
|
if (!across_fs) {
|
||||||
error = retrieve_device(¤t_device, bare_path.ptr);
|
if (retrieve_device(¤t_device, bare_path.ptr) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
goto on_error;
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ceiling_offset = retrieve_ceiling_directories_offset(bare_path.ptr, ceiling_dirs);
|
ceiling_offset = retrieve_ceiling_directories_offset(bare_path.ptr, ceiling_dirs);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
error = git_buf_joinpath(&normal_path, bare_path.ptr, DOT_GIT);
|
if (git_buf_joinpath(&normal_path, bare_path.ptr, DOT_GIT) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
goto on_error;
|
||||||
break;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the `.git` file is regular instead of
|
* If the `.git` file is regular instead of
|
||||||
@ -545,18 +517,21 @@ int git_repository_discover(
|
|||||||
if (git_path_isfile(normal_path.ptr) == true) {
|
if (git_path_isfile(normal_path.ptr) == true) {
|
||||||
git_buf gitfile_path = GIT_BUF_INIT;
|
git_buf gitfile_path = GIT_BUF_INIT;
|
||||||
|
|
||||||
error = read_gitfile(&gitfile_path, normal_path.ptr, bare_path.ptr);
|
if (read_gitfile(&gitfile_path, normal_path.ptr, bare_path.ptr) < 0) {
|
||||||
if (error < GIT_SUCCESS)
|
git_buf_free(&gitfile_path);
|
||||||
git__rethrow(error, "Unable to read git file `%s`", normal_path.ptr);
|
goto on_error;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (valid_repository_path(&gitfile_path) == false) {
|
||||||
|
git_buf_free(&gitfile_path);
|
||||||
|
giterr_set(GITERR_REPOSITORY,
|
||||||
|
"The `.git` file found at '%s' points to an invalid git folder", normal_path.ptr);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
git_buf_swap(&normal_path, &gitfile_path);
|
||||||
|
found_path = &normal_path;
|
||||||
|
|
||||||
git_buf_free(&gitfile_path);
|
git_buf_free(&gitfile_path);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -565,8 +540,7 @@ int git_repository_discover(
|
|||||||
* If the `.git` file is a folder, we check inside of it
|
* If the `.git` file is a folder, we check inside of it
|
||||||
*/
|
*/
|
||||||
if (git_path_isdir(normal_path.ptr) == true) {
|
if (git_path_isdir(normal_path.ptr) == true) {
|
||||||
error = quickcheck_repository_dir(&normal_path);
|
if (valid_repository_path(&normal_path) == true) {
|
||||||
if (error == GIT_SUCCESS) {
|
|
||||||
found_path = &normal_path;
|
found_path = &normal_path;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -576,8 +550,7 @@ int git_repository_discover(
|
|||||||
* Otherwise, the repository may be bare, let's check
|
* Otherwise, the repository may be bare, let's check
|
||||||
* the root anyway
|
* the root anyway
|
||||||
*/
|
*/
|
||||||
error = quickcheck_repository_dir(&bare_path);
|
if (valid_repository_path(&bare_path) == true) {
|
||||||
if (error == GIT_SUCCESS) {
|
|
||||||
found_path = &bare_path;
|
found_path = &bare_path;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -585,147 +558,146 @@ int git_repository_discover(
|
|||||||
/**
|
/**
|
||||||
* If we didn't find it, walk up the tree
|
* If we didn't find it, walk up the tree
|
||||||
*/
|
*/
|
||||||
error = git_path_dirname_r(&normal_path, bare_path.ptr);
|
if (git_path_dirname_r(&normal_path, bare_path.ptr) < 0)
|
||||||
if (error < GIT_SUCCESS) {
|
goto on_error;
|
||||||
git__rethrow(GIT_EOSERR, "Failed to dirname '%s'", bare_path.ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_buf_swap(&bare_path, &normal_path);
|
git_buf_swap(&bare_path, &normal_path);
|
||||||
|
|
||||||
if (!across_fs) {
|
if (!across_fs) {
|
||||||
dev_t new_device;
|
dev_t new_device;
|
||||||
error = retrieve_device(&new_device, bare_path.ptr);
|
if (retrieve_device(&new_device, bare_path.ptr) < 0)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
if (current_device != new_device)
|
||||||
|
goto on_not_found;
|
||||||
|
|
||||||
if (error < GIT_SUCCESS || current_device != new_device) {
|
|
||||||
error = git__throw(GIT_ENOTAREPO,
|
|
||||||
"Not a git repository (or any parent up to mount parent %s)\n"
|
|
||||||
"Stopping at filesystem boundary.", normal_path.ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
current_device = new_device;
|
current_device = new_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nothing has been found, lets try the parent directory
|
/* nothing has been found, lets try the parent directory
|
||||||
* but stop if we hit one of the ceiling directories
|
* but stop if we hit one of the ceiling directories
|
||||||
*/
|
*/
|
||||||
if (bare_path.ptr[ceiling_offset] == '\0') {
|
if (bare_path.ptr[ceiling_offset] == '\0')
|
||||||
error = git__throw(GIT_ENOTAREPO,
|
goto on_not_found;
|
||||||
"Not a git repository (or any of the parent directories): %s", start_path);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(found_path || error != GIT_SUCCESS);
|
assert(found_path);
|
||||||
|
|
||||||
if (found_path) {
|
if (git_path_to_dir(found_path) < 0)
|
||||||
if ((error = git_path_to_dir(found_path)) < GIT_SUCCESS)
|
goto on_error;
|
||||||
git__rethrow(error, "Could not convert git repository to directory");
|
|
||||||
else if (size < (size_t)(found_path->size + 1))
|
if (size < (size_t)(found_path->size + 1)) {
|
||||||
error = git__throw(GIT_ESHORTBUFFER,
|
giterr_set(GITERR_REPOSITORY,
|
||||||
"The repository buffer is not long enough to "
|
"The given buffer is too long to store the discovered path");
|
||||||
"handle the repository path `%s`", found_path->ptr);
|
goto on_error;
|
||||||
else
|
|
||||||
git_buf_copy_cstr(repository_path, size, found_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
/* success: we discovered a repository */
|
||||||
|
git_buf_copy_cstr(repository_path, size, found_path);
|
||||||
|
|
||||||
git_buf_free(&bare_path);
|
git_buf_free(&bare_path);
|
||||||
git_buf_free(&normal_path);
|
git_buf_free(&normal_path);
|
||||||
return error;
|
return 0;
|
||||||
|
|
||||||
|
on_error: /* unrecoverable error */
|
||||||
|
git_buf_free(&bare_path);
|
||||||
|
git_buf_free(&normal_path);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
on_not_found: /* failed to discover the repository */
|
||||||
|
git_buf_free(&bare_path);
|
||||||
|
git_buf_free(&normal_path);
|
||||||
|
return GIT_ENOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_repositoryformatversion(git_repository *repo)
|
static int check_repositoryformatversion(git_repository *repo)
|
||||||
{
|
{
|
||||||
git_config *config;
|
git_config *config;
|
||||||
int version, error = GIT_SUCCESS;
|
int version;
|
||||||
|
|
||||||
if ((error = git_repository_config(&config, repo)) < GIT_SUCCESS)
|
if (git_repository_config__weakptr(&config, repo) < 0)
|
||||||
return git__throw(error, "Failed to open config file.");
|
return -1;
|
||||||
|
|
||||||
error = git_config_get_int32(config, GIT_CONFIG_CORE_REPOSITORYFORMATVERSION, &version);
|
if (git_config_get_int32(config, GIT_CONFIG_CORE_REPOSITORYFORMATVERSION, &version) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (GIT_REPOSITORYFORMATVERSION < version)
|
if (GIT_REPOSITORYFORMATVERSION < version) {
|
||||||
error = git__throw(GIT_ERROR, "Unsupported git repository version (Expected version <= %d, found %d).", GIT_REPOSITORYFORMATVERSION, version);
|
giterr_set(GITERR_REPOSITORY,
|
||||||
|
"Unsupported repository version %d. Only versions up to %d are supported.",
|
||||||
|
version, GIT_REPOSITORYFORMATVERSION);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
git_config_free(config);
|
return 0;
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int repo_init_reinit(git_repository **repo_out, const char *repository_path, int is_bare)
|
static int repo_init_reinit(git_repository **repo_out, const char *repository_path, int is_bare)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
git_repository *repo = NULL;
|
git_repository *repo = NULL;
|
||||||
|
|
||||||
if ((error = git_repository_open(&repo, repository_path)) < GIT_SUCCESS)
|
GIT_UNUSED(is_bare);
|
||||||
goto error;
|
|
||||||
|
|
||||||
if ((error = check_repositoryformatversion(repo)) < GIT_SUCCESS)
|
if (git_repository_open(&repo, repository_path) < 0)
|
||||||
goto error;
|
return -1;
|
||||||
|
|
||||||
|
if (check_repositoryformatversion(repo) < 0) {
|
||||||
|
git_repository_free(repo);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: reinitialize the templates */
|
/* TODO: reinitialize the templates */
|
||||||
|
|
||||||
*repo_out = repo;
|
*repo_out = repo;
|
||||||
|
return 0;
|
||||||
return GIT_SUCCESS;
|
|
||||||
|
|
||||||
error:
|
|
||||||
git_repository_free(repo);
|
|
||||||
|
|
||||||
return git__rethrow(error,
|
|
||||||
"Failed to reinitialize the %srepository at '%s'. ",
|
|
||||||
is_bare ? "bare " : "", repository_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int repo_init_createhead(const char *git_dir)
|
static int repo_init_createhead(const char *git_dir)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
git_buf ref_path = GIT_BUF_INIT;
|
git_buf ref_path = GIT_BUF_INIT;
|
||||||
git_filebuf ref = GIT_FILEBUF_INIT;
|
git_filebuf ref = GIT_FILEBUF_INIT;
|
||||||
|
|
||||||
if (!(error = git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE)) &&
|
if (git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE) < 0 ||
|
||||||
!(error = git_filebuf_open(&ref, ref_path.ptr, 0)) &&
|
git_filebuf_open(&ref, ref_path.ptr, 0) < 0 ||
|
||||||
!(error = git_filebuf_printf(&ref, "ref: refs/heads/master\n")))
|
git_filebuf_printf(&ref, "ref: refs/heads/master\n") < 0 ||
|
||||||
error = git_filebuf_commit(&ref, GIT_REFS_FILE_MODE);
|
git_filebuf_commit(&ref, GIT_REFS_FILE_MODE) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
git_buf_free(&ref_path);
|
git_buf_free(&ref_path);
|
||||||
return error;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int repo_init_config(const char *git_dir, int is_bare)
|
static int repo_init_config(const char *git_dir, int is_bare)
|
||||||
{
|
{
|
||||||
git_buf cfg_path = GIT_BUF_INIT;
|
git_buf cfg_path = GIT_BUF_INIT;
|
||||||
git_config *config = NULL;
|
git_config *config = NULL;
|
||||||
int error = GIT_SUCCESS;
|
|
||||||
|
|
||||||
#define SET_REPO_CONFIG(type, name, val) {\
|
#define SET_REPO_CONFIG(type, name, val) {\
|
||||||
error = git_config_set_##type(config, name, val);\
|
if (git_config_set_##type(config, name, val) < 0) { \
|
||||||
if (error < GIT_SUCCESS)\
|
git_buf_free(&cfg_path); \
|
||||||
goto cleanup;\
|
git_config_free(config); \
|
||||||
|
return -1; } \
|
||||||
}
|
}
|
||||||
|
|
||||||
error = git_buf_joinpath(&cfg_path, git_dir, GIT_CONFIG_FILENAME_INREPO);
|
if (git_buf_joinpath(&cfg_path, git_dir, GIT_CONFIG_FILENAME_INREPO) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
error = git_config_open_ondisk(&config, cfg_path.ptr);
|
if (git_config_open_ondisk(&config, cfg_path.ptr) < 0) {
|
||||||
if (error < GIT_SUCCESS)
|
git_buf_free(&cfg_path);
|
||||||
goto cleanup;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
SET_REPO_CONFIG(bool, "core.bare", is_bare);
|
SET_REPO_CONFIG(bool, "core.bare", is_bare);
|
||||||
SET_REPO_CONFIG(int32, GIT_CONFIG_CORE_REPOSITORYFORMATVERSION, GIT_REPOSITORYFORMATVERSION);
|
SET_REPO_CONFIG(int32, GIT_CONFIG_CORE_REPOSITORYFORMATVERSION, GIT_REPOSITORYFORMATVERSION);
|
||||||
/* TODO: what other defaults? */
|
/* TODO: what other defaults? */
|
||||||
|
|
||||||
cleanup:
|
|
||||||
git_buf_free(&cfg_path);
|
git_buf_free(&cfg_path);
|
||||||
git_config_free(config);
|
git_config_free(config);
|
||||||
return error;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int repo_init_structure(const char *git_dir, int is_bare)
|
static int repo_init_structure(const char *git_dir, int is_bare)
|
||||||
{
|
{
|
||||||
int error, i;
|
int i;
|
||||||
struct { const char *dir; mode_t mode; } dirs[] = {
|
struct { const char *dir; mode_t mode; } dirs[] = {
|
||||||
{ GIT_OBJECTS_INFO_DIR, GIT_OBJECT_DIR_MODE }, /* '/objects/info/' */
|
{ GIT_OBJECTS_INFO_DIR, GIT_OBJECT_DIR_MODE }, /* '/objects/info/' */
|
||||||
{ GIT_OBJECTS_PACK_DIR, GIT_OBJECT_DIR_MODE }, /* '/objects/pack/' */
|
{ GIT_OBJECTS_PACK_DIR, GIT_OBJECT_DIR_MODE }, /* '/objects/pack/' */
|
||||||
@ -735,100 +707,80 @@ static int repo_init_structure(const char *git_dir, int is_bare)
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Make the base directory */
|
/* Make the base directory */
|
||||||
error = git_futils_mkdir_r(git_dir, NULL, is_bare ?
|
if (git_futils_mkdir_r(git_dir, NULL, is_bare ? GIT_BARE_DIR_MODE : GIT_DIR_MODE) < 0)
|
||||||
GIT_BARE_DIR_MODE : GIT_DIR_MODE);
|
return -1;
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
return git__rethrow(error, "Failed to initialize repository structure. Could not mkdir");
|
|
||||||
|
|
||||||
/* Hides the ".git" directory */
|
/* Hides the ".git" directory */
|
||||||
if (!is_bare) {
|
if (!is_bare) {
|
||||||
#ifdef GIT_WIN32
|
#ifdef GIT_WIN32
|
||||||
error = p_hide_directory__w32(git_dir);
|
if (p_hide_directory__w32(git_dir) < 0) {
|
||||||
if (error < GIT_SUCCESS)
|
giterr_set(GITERR_REPOSITORY,
|
||||||
return git__rethrow(error, "Failed to initialize repository structure");
|
"Failed to mark Git repository folder as hidden");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make subdirectories as needed */
|
/* Make subdirectories as needed */
|
||||||
for (i = 0; dirs[i].dir != NULL; ++i) {
|
for (i = 0; dirs[i].dir != NULL; ++i) {
|
||||||
error = git_futils_mkdir_r(dirs[i].dir, git_dir, dirs[i].mode);
|
if (git_futils_mkdir_r(dirs[i].dir, git_dir, dirs[i].mode) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return git__rethrow(error,
|
|
||||||
"Failed to create repository folder `%s`", dirs[i].dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: what's left? templates? */
|
/* TODO: what's left? templates? */
|
||||||
|
return 0;
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
int error = GIT_SUCCESS;
|
|
||||||
git_repository *repo = NULL;
|
|
||||||
git_buf repository_path = GIT_BUF_INIT;
|
git_buf repository_path = GIT_BUF_INIT;
|
||||||
|
|
||||||
assert(repo_out && path);
|
assert(repo_out && path);
|
||||||
|
|
||||||
error = git_buf_joinpath(&repository_path, path, is_bare ? "" : GIT_DIR);
|
if (git_buf_joinpath(&repository_path, path, is_bare ? "" : GIT_DIR) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return error;
|
|
||||||
|
|
||||||
if (git_path_isdir(repository_path.ptr) == true) {
|
if (git_path_isdir(repository_path.ptr) == true) {
|
||||||
if (quickcheck_repository_dir(&repository_path) == GIT_SUCCESS) {
|
if (valid_repository_path(&repository_path) == true) {
|
||||||
error = repo_init_reinit(repo_out, repository_path.ptr, is_bare);
|
int res = repo_init_reinit(repo_out, repository_path.ptr, is_bare);
|
||||||
git_buf_free(&repository_path);
|
git_buf_free(&repository_path);
|
||||||
return error;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(error = repo_init_structure(repository_path.ptr, is_bare)) &&
|
if (repo_init_structure(repository_path.ptr, is_bare) < 0 ||
|
||||||
!(error = repo_init_config(repository_path.ptr, is_bare)) &&
|
repo_init_config(repository_path.ptr, is_bare) < 0 ||
|
||||||
!(error = repo_init_createhead(repository_path.ptr)))
|
repo_init_createhead(repository_path.ptr) < 0 ||
|
||||||
error = git_repository_open(repo_out, repository_path.ptr);
|
git_repository_open(repo_out, repository_path.ptr) < 0) {
|
||||||
else
|
git_buf_free(&repository_path);
|
||||||
git_repository_free(repo);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
git_buf_free(&repository_path);
|
git_buf_free(&repository_path);
|
||||||
|
return 0;
|
||||||
if (error != GIT_SUCCESS)
|
|
||||||
git__rethrow(error, "Failed to (re)init the repository `%s`", path);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_repository_head_detached(git_repository *repo)
|
int git_repository_head_detached(git_repository *repo)
|
||||||
{
|
{
|
||||||
git_reference *ref;
|
git_reference *ref;
|
||||||
int error;
|
|
||||||
size_t _size;
|
|
||||||
git_otype type;
|
|
||||||
git_odb *odb = NULL;
|
git_odb *odb = NULL;
|
||||||
|
int exists;
|
||||||
|
|
||||||
error = git_repository_odb__weakptr(&odb, repo);
|
if (git_repository_odb__weakptr(&odb, repo) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return error;
|
|
||||||
|
|
||||||
error = git_reference_lookup(&ref, repo, GIT_HEAD_FILE);
|
if (git_reference_lookup(&ref, repo, GIT_HEAD_FILE) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return error;
|
|
||||||
|
|
||||||
if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
|
if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
|
||||||
git_reference_free(ref);
|
git_reference_free(ref);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = git_odb_read_header(&_size, &type, odb, git_reference_oid(ref));
|
exists = git_odb_exists(odb, git_reference_oid(ref));
|
||||||
|
|
||||||
git_reference_free(ref);
|
git_reference_free(ref);
|
||||||
|
return exists;
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
if (type != GIT_OBJ_COMMIT)
|
|
||||||
return git__throw(GIT_EOBJCORRUPTED, "HEAD is not a commit");
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_repository_head(git_reference **head_out, git_repository *repo)
|
int git_repository_head(git_reference **head_out, git_repository *repo)
|
||||||
@ -839,32 +791,35 @@ int git_repository_head(git_reference **head_out, git_repository *repo)
|
|||||||
*head_out = NULL;
|
*head_out = NULL;
|
||||||
|
|
||||||
error = git_reference_lookup(&ref, repo, GIT_HEAD_FILE);
|
error = git_reference_lookup(&ref, repo, GIT_HEAD_FILE);
|
||||||
if (error < GIT_SUCCESS)
|
if (error < 0)
|
||||||
return git__rethrow(GIT_ENOTAREPO, "Failed to locate the HEAD");
|
return error;
|
||||||
|
|
||||||
error = git_reference_resolve(&resolved_ref, ref);
|
error = git_reference_resolve(&resolved_ref, ref);
|
||||||
if (error < GIT_SUCCESS) {
|
if (error < 0) {
|
||||||
git_reference_free(ref);
|
git_reference_free(ref);
|
||||||
return git__rethrow(error, "Failed to resolve the HEAD");
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
git_reference_free(ref);
|
git_reference_free(ref);
|
||||||
|
|
||||||
*head_out = resolved_ref;
|
*head_out = resolved_ref;
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_repository_head_orphan(git_repository *repo)
|
int git_repository_head_orphan(git_repository *repo)
|
||||||
{
|
{
|
||||||
git_reference *ref;
|
git_reference *ref = NULL;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = git_repository_head(&ref, repo);
|
error = git_repository_head(&ref, repo);
|
||||||
|
git_reference_free(ref);
|
||||||
|
|
||||||
if (error == GIT_SUCCESS)
|
if (error == GIT_ENOTFOUND)
|
||||||
git_reference_free(ref);
|
return 1;
|
||||||
|
|
||||||
return error == GIT_ENOTFOUND ? 1 : error;
|
if (error < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_repository_is_empty(git_repository *repo)
|
int git_repository_is_empty(git_repository *repo)
|
||||||
@ -872,9 +827,8 @@ int git_repository_is_empty(git_repository *repo)
|
|||||||
git_reference *head = NULL, *branch = NULL;
|
git_reference *head = NULL, *branch = NULL;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = git_reference_lookup(&head, repo, "HEAD");
|
if (git_reference_lookup(&head, repo, "HEAD") < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return git__throw(error, "Corrupted repository. HEAD does not exist");
|
|
||||||
|
|
||||||
if (git_reference_type(head) != GIT_REF_SYMBOLIC) {
|
if (git_reference_type(head) != GIT_REF_SYMBOLIC) {
|
||||||
git_reference_free(head);
|
git_reference_free(head);
|
||||||
@ -891,7 +845,13 @@ int git_repository_is_empty(git_repository *repo)
|
|||||||
git_reference_free(head);
|
git_reference_free(head);
|
||||||
git_reference_free(branch);
|
git_reference_free(branch);
|
||||||
|
|
||||||
return error == GIT_ENOTFOUND ? 1 : error;
|
if (error == GIT_ENOTFOUND)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (error < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *git_repository_path(git_repository *repo)
|
const char *git_repository_path(git_repository *repo)
|
||||||
@ -917,8 +877,7 @@ int git_repository_set_workdir(git_repository *repo, const char *workdir)
|
|||||||
free(repo->workdir);
|
free(repo->workdir);
|
||||||
|
|
||||||
repo->workdir = git__strdup(workdir);
|
repo->workdir = git__strdup(workdir);
|
||||||
if (repo->workdir == NULL)
|
GITERR_CHECK_ALLOC(repo->workdir);
|
||||||
return GIT_ENOMEM;
|
|
||||||
|
|
||||||
repo->is_bare = 0;
|
repo->is_bare = 0;
|
||||||
return GIT_SUCCESS;
|
return GIT_SUCCESS;
|
||||||
|
@ -423,10 +423,8 @@ static int dirent_cb(void *state, git_buf *a)
|
|||||||
if (git_tree_entry_type(m) == GIT_OBJ_TREE)
|
if (git_tree_entry_type(m) == GIT_OBJ_TREE)
|
||||||
git_path_to_dir(&st->head_tree_relative_path);
|
git_path_to_dir(&st->head_tree_relative_path);
|
||||||
|
|
||||||
error = git_buf_lasterror(&st->head_tree_relative_path);
|
if (git_buf_oom(&st->head_tree_relative_path))
|
||||||
if (error < GIT_SUCCESS)
|
return GIT_ENOMEM;
|
||||||
return git__rethrow(error, "An error occured while "
|
|
||||||
"determining the status of '%s'", a->ptr);
|
|
||||||
|
|
||||||
m_name = st->head_tree_relative_path.ptr;
|
m_name = st->head_tree_relative_path.ptr;
|
||||||
} else
|
} else
|
||||||
|
@ -193,10 +193,9 @@ static int write_tag_annotation(
|
|||||||
git_buf_putc(&tag, '\n');
|
git_buf_putc(&tag, '\n');
|
||||||
git_buf_puts(&tag, message);
|
git_buf_puts(&tag, message);
|
||||||
|
|
||||||
error = git_buf_lasterror(&tag);
|
if (git_buf_oom(&tag)) {
|
||||||
if (error < GIT_SUCCESS) {
|
|
||||||
git_buf_free(&tag);
|
git_buf_free(&tag);
|
||||||
return git__rethrow(error, "Not enough memory to build the tag data");
|
return git__throw(GIT_ENOMEM, "Not enough memory to build the tag data");
|
||||||
}
|
}
|
||||||
|
|
||||||
error = git_repository_odb__weakptr(&odb, repo);
|
error = git_repository_odb__weakptr(&odb, repo);
|
||||||
|
@ -68,7 +68,10 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
|
|||||||
git_buf_put(request, url, delim - url);
|
git_buf_put(request, url, delim - url);
|
||||||
git_buf_putc(request, '\0');
|
git_buf_putc(request, '\0');
|
||||||
|
|
||||||
return git_buf_lasterror(request);
|
if (git_buf_oom(request))
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_request(GIT_SOCKET s, const char *cmd, const char *url)
|
static int send_request(GIT_SOCKET s, const char *cmd, const char *url)
|
||||||
|
@ -77,7 +77,10 @@ static int gen_request(git_buf *buf, const char *url, const char *host, const ch
|
|||||||
}
|
}
|
||||||
git_buf_puts(buf, "\r\n");
|
git_buf_puts(buf, "\r\n");
|
||||||
|
|
||||||
return git_buf_lasterror(buf);
|
if (git_buf_oom(buf))
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_connect(transport_http *t, const char *host, const char *port)
|
static int do_connect(transport_http *t, const char *host, const char *port)
|
||||||
|
@ -569,9 +569,9 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b
|
|||||||
git_buf_put(&tree, (char *)entry->oid.id, GIT_OID_RAWSZ);
|
git_buf_put(&tree, (char *)entry->oid.id, GIT_OID_RAWSZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = git_buf_lasterror(&tree)) < GIT_SUCCESS) {
|
if (git_buf_oom(&tree)) {
|
||||||
git_buf_free(&tree);
|
git_buf_free(&tree);
|
||||||
return git__rethrow(error, "Not enough memory to build the tree data");
|
return git__throw(GIT_ENOMEM, "Not enough memory to build the tree data");
|
||||||
}
|
}
|
||||||
|
|
||||||
error = git_repository_odb__weakptr(&odb, repo);
|
error = git_repository_odb__weakptr(&odb, repo);
|
||||||
@ -720,8 +720,9 @@ static int tree_walk_post(
|
|||||||
/* append the next entry to the path */
|
/* append the next entry to the path */
|
||||||
git_buf_puts(path, entry->filename);
|
git_buf_puts(path, entry->filename);
|
||||||
git_buf_putc(path, '/');
|
git_buf_putc(path, '/');
|
||||||
if ((error = git_buf_lasterror(path)) < GIT_SUCCESS)
|
|
||||||
break;
|
if (git_buf_oom(path))
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
error = tree_walk_post(subtree, callback, path, payload);
|
error = tree_walk_post(subtree, callback, path, payload);
|
||||||
if (error < GIT_SUCCESS)
|
if (error < GIT_SUCCESS)
|
||||||
|
12
src/util.h
12
src/util.h
@ -7,6 +7,8 @@
|
|||||||
#ifndef INCLUDE_util_h__
|
#ifndef INCLUDE_util_h__
|
||||||
#define INCLUDE_util_h__
|
#define INCLUDE_util_h__
|
||||||
|
|
||||||
|
#include "git2/errors.h"
|
||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||||
#define bitsizeof(x) (CHAR_BIT * sizeof(x))
|
#define bitsizeof(x) (CHAR_BIT * sizeof(x))
|
||||||
#define MSB(x, bits) ((x) & (~0ULL << (bitsizeof(x) - (bits))))
|
#define MSB(x, bits) ((x) & (~0ULL << (bitsizeof(x) - (bits))))
|
||||||
@ -23,7 +25,7 @@ GIT_INLINE(void *) git__malloc(size_t len)
|
|||||||
{
|
{
|
||||||
void *ptr = malloc(len);
|
void *ptr = malloc(len);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)len);
|
giterr_set(GITERR_NOMEMORY, "Out of memory. Failed to allocate %d bytes.", (int)len);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +33,7 @@ GIT_INLINE(void *) git__calloc(size_t nelem, size_t elsize)
|
|||||||
{
|
{
|
||||||
void *ptr = calloc(nelem, elsize);
|
void *ptr = calloc(nelem, elsize);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)elsize);
|
giterr_set(GITERR_NOMEMORY, "Out of memory. Failed to allocate %d bytes.", (int)nelem*elsize);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ GIT_INLINE(char *) git__strdup(const char *str)
|
|||||||
{
|
{
|
||||||
char *ptr = strdup(str);
|
char *ptr = strdup(str);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to duplicate string");
|
giterr_set(GITERR_NOMEMORY, "Out of memory. Failed to duplicate string");
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n)
|
|||||||
|
|
||||||
ptr = (char*)malloc(length + 1);
|
ptr = (char*)malloc(length + 1);
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to duplicate string");
|
giterr_set(GITERR_NOMEMORY, "Out of memory. Failed to duplicate string");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +70,7 @@ GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
|
|||||||
{
|
{
|
||||||
void *new_ptr = realloc(ptr, size);
|
void *new_ptr = realloc(ptr, size);
|
||||||
if (!new_ptr)
|
if (!new_ptr)
|
||||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)size);
|
giterr_set(GITERR_NOMEMORY, "Out of memory. Failed to allocate %d bytes.", (int)size);
|
||||||
return new_ptr;
|
return new_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/ < 0)
|
||||||
* Copyright (C) 2009-2012 the libgit2 contributors
|
* Copyright (C) 2009-2012 the libgit2 contributors
|
||||||
*
|
*
|
||||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||||
@ -288,18 +288,13 @@ int p_rmdir(const char* path)
|
|||||||
|
|
||||||
int p_hide_directory__w32(const char *path)
|
int p_hide_directory__w32(const char *path)
|
||||||
{
|
{
|
||||||
int error;
|
int res;
|
||||||
wchar_t* buf = gitwin_to_utf16(path);
|
wchar_t* buf = gitwin_to_utf16(path);
|
||||||
|
|
||||||
error = SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0 ?
|
res = SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN);
|
||||||
GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */
|
|
||||||
|
|
||||||
git__free(buf);
|
git__free(buf);
|
||||||
|
|
||||||
if (error < GIT_SUCCESS)
|
return (res != 0) ? GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */
|
||||||
error = git__throw(GIT_EOSERR, "Failed to hide directory '%s'", path);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *p_realpath(const char *orig_path, char *buffer)
|
char *p_realpath(const char *orig_path, char *buffer)
|
||||||
|
@ -99,11 +99,15 @@ static int append_ceiling_dir(git_buf *ceiling_dirs, const char *path)
|
|||||||
|
|
||||||
if (ceiling_dirs->size > 0)
|
if (ceiling_dirs->size > 0)
|
||||||
git_buf_puts(ceiling_dirs, ceiling_separator);
|
git_buf_puts(ceiling_dirs, ceiling_separator);
|
||||||
|
|
||||||
git_buf_puts(ceiling_dirs, pretty_path.ptr);
|
git_buf_puts(ceiling_dirs, pretty_path.ptr);
|
||||||
|
|
||||||
git_buf_free(&pretty_path);
|
git_buf_free(&pretty_path);
|
||||||
|
|
||||||
return git_buf_lasterror(ceiling_dirs);
|
if (git_buf_oom(ceiling_dirs))
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BEGIN_TEST(discover0, "test discover")
|
BEGIN_TEST(discover0, "test discover")
|
||||||
@ -119,7 +123,7 @@ BEGIN_TEST(discover0, "test discover")
|
|||||||
must_pass(append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER));
|
must_pass(append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER));
|
||||||
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
|
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
|
||||||
|
|
||||||
must_be_true(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs) == GIT_ENOTAREPO);
|
must_fail(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));
|
||||||
|
|
||||||
must_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1));
|
must_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1));
|
||||||
must_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));
|
must_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));
|
||||||
|
Loading…
Reference in New Issue
Block a user