mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-03 02:09:41 +00:00
Merge branch 'error-handling' into development
This commit is contained in:
commit
5711ca93d1
@ -170,6 +170,12 @@
|
||||
/** The given literal is not a valid number */
|
||||
#define GIT_ENOTNUM (GIT_ERROR - 25)
|
||||
|
||||
/** Streaming error */
|
||||
#define GIT_ESTREAM (GIT_ERROR - 26)
|
||||
|
||||
/** invalid arguments to function */
|
||||
#define GIT_EINVALIDARGS (GIT_ERROR - 27)
|
||||
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
typedef struct {
|
||||
|
@ -34,11 +34,11 @@
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* strerror() for the Git library
|
||||
* @param num The error code to explain
|
||||
* @return a string explaining the error code
|
||||
* Return a detailed error string with the latest error
|
||||
* that occurred in the library.
|
||||
* @return a string explaining the error
|
||||
*/
|
||||
GIT_EXTERN(const char *) git_strerror(int num);
|
||||
GIT_EXTERN(const char *) git_lasterror(void);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
# undef GIT_TLS
|
||||
# define GIT_TLS
|
||||
|
||||
#elif defined(__GNUC__) || \
|
||||
defined(__SUNPRO_C) || \
|
||||
|
@ -50,10 +50,13 @@ typedef SSIZE_T ssize_t;
|
||||
|
||||
#include "git2/common.h"
|
||||
#include "git2/types.h"
|
||||
#include "util.h"
|
||||
#include "thread-utils.h"
|
||||
#include "bswap.h"
|
||||
|
||||
#define GIT_PATH_MAX 4096
|
||||
extern int git__throw(int error, const char *, ...) GIT_FORMAT_PRINTF(2, 3);
|
||||
extern int git__rethrow(int error, const char *, ...) GIT_FORMAT_PRINTF(2, 3);
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#endif /* INCLUDE_common_h__ */
|
||||
|
98
src/errors.c
98
src/errors.c
@ -1,48 +1,66 @@
|
||||
/*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* In addition to the permissions in the GNU General Public License,
|
||||
* the authors give you unlimited permission to link the compiled
|
||||
* version of this file into combinations with other programs,
|
||||
* and to distribute those combinations without any restriction
|
||||
* coming from the use of this file. (The General Public License
|
||||
* restrictions do apply in other respects; for example, they cover
|
||||
* modification of the file, and distribution when not linked into
|
||||
* a combined executable.)
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "git2/thread-utils.h" /* for GIT_TLS */
|
||||
#include "thread-utils.h" /* for GIT_TLS */
|
||||
|
||||
static struct {
|
||||
int num;
|
||||
const char *str;
|
||||
} error_codes[] = {
|
||||
{GIT_ERROR, "Unspecified error"},
|
||||
{GIT_ENOTOID, "Input was not a properly formatted Git object id."},
|
||||
{GIT_ENOTFOUND, "Object does not exist in the scope searched."},
|
||||
{GIT_ENOMEM, "Not enough space available."},
|
||||
{GIT_EOSERR, "Consult the OS error information."},
|
||||
{GIT_EOBJTYPE, "The specified object is of invalid type"},
|
||||
{GIT_EOBJCORRUPTED, "The specified object has its data corrupted"},
|
||||
{GIT_ENOTAREPO, "The specified repository is invalid"},
|
||||
{GIT_EINVALIDTYPE, "The object type is invalid or doesn't match"},
|
||||
{GIT_EMISSINGOBJDATA, "The object cannot be written that because it's missing internal data"},
|
||||
{GIT_EPACKCORRUPTED, "The packfile for the ODB is corrupted"},
|
||||
{GIT_EFLOCKFAIL, "Failed to adquire or release a file lock"},
|
||||
{GIT_EZLIB, "The Z library failed to inflate/deflate an object's data"},
|
||||
{GIT_EBUSY, "The queried object is currently busy"},
|
||||
{GIT_EINVALIDPATH, "The path is invalid"},
|
||||
{GIT_EBAREINDEX, "The index file is not backed up by an existing repository"},
|
||||
{GIT_EINVALIDREFNAME, "The name of the reference is not valid"},
|
||||
{GIT_EREFCORRUPTED, "The specified reference has its data corrupted"},
|
||||
{GIT_ETOONESTEDSYMREF, "The specified symbolic reference is too deeply nested"},
|
||||
{GIT_EPACKEDREFSCORRUPTED, "The pack-refs file is either corrupted of its format is not currently supported"},
|
||||
{GIT_EINVALIDPATH, "The path is invalid" },
|
||||
{GIT_EREVWALKOVER, "The revision walker is empty; there are no more commits left to iterate"},
|
||||
{GIT_EINVALIDREFSTATE, "The state of the reference is not valid"},
|
||||
{GIT_ENOTIMPLEMENTED, "This feature has not been implemented yet"},
|
||||
{GIT_EEXISTS, "A reference with this name already exists"},
|
||||
{GIT_EOVERFLOW, "The given integer literal is too large to be parsed"},
|
||||
{GIT_ENOTNUM, "The given literal is not a valid number"},
|
||||
};
|
||||
#include <stdarg.h>
|
||||
|
||||
const char *git_strerror(int num)
|
||||
static GIT_TLS char g_last_error[1024];
|
||||
|
||||
int git__rethrow(int error, const char *msg, ...)
|
||||
{
|
||||
size_t i;
|
||||
char new_error[1024];
|
||||
char *old_error = NULL;
|
||||
|
||||
if (num == GIT_EOSERR)
|
||||
return strerror(errno);
|
||||
for (i = 0; i < ARRAY_SIZE(error_codes); i++)
|
||||
if (num == error_codes[i].num)
|
||||
return error_codes[i].str;
|
||||
va_list va;
|
||||
|
||||
return "Unknown error";
|
||||
va_start(va, msg);
|
||||
vsnprintf(new_error, sizeof(new_error), msg, va);
|
||||
va_end(va);
|
||||
|
||||
old_error = strdup(g_last_error);
|
||||
snprintf(g_last_error, sizeof(g_last_error), "%s \n - %s", new_error, old_error);
|
||||
free(old_error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git__throw(int error, const char *msg, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, msg);
|
||||
vsnprintf(g_last_error, sizeof(g_last_error), msg, va);
|
||||
va_end(va);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
const char *git_lasterror(void)
|
||||
{
|
||||
return g_last_error;
|
||||
}
|
||||
|
||||
|
33
src/refs.c
33
src/refs.c
@ -122,7 +122,8 @@ static int reference_create(
|
||||
else if (type == GIT_REF_OID)
|
||||
size = sizeof(reference_oid);
|
||||
else
|
||||
return GIT_EINVALIDREFSTATE;
|
||||
return git__throw(GIT_EINVALIDARGS,
|
||||
"Invalid reference type. Use either GIT_REF_OID or GIT_REF_SYMBOLIC as type specifier");
|
||||
|
||||
reference = git__malloc(size);
|
||||
if (reference == NULL)
|
||||
@ -159,11 +160,9 @@ static int reference_read(gitfo_buf *file_content, time_t *mtime, const char *re
|
||||
/* Determine the full path of the file */
|
||||
git__joinpath(path, repo_path, ref_name);
|
||||
|
||||
if (gitfo_stat(path, &st) < 0)
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
return GIT_EOBJCORRUPTED;
|
||||
if (gitfo_stat(path, &st) < 0 || S_ISDIR(st.st_mode))
|
||||
return git__throw(GIT_ENOTFOUND,
|
||||
"Cannot read reference file '%s'", ref_name);
|
||||
|
||||
if (mtime)
|
||||
*mtime = st.st_mtime;
|
||||
@ -205,7 +204,8 @@ static int loose_update(git_reference *ref)
|
||||
else if (ref->type == GIT_REF_OID)
|
||||
error = loose_parse_oid(ref, &ref_file);
|
||||
else
|
||||
error = GIT_EINVALIDREFSTATE;
|
||||
error = git__throw(GIT_EOBJCORRUPTED,
|
||||
"Invalid reference type (%d) for loose reference", ref->type);
|
||||
|
||||
gitfo_free_buf(&ref_file);
|
||||
|
||||
@ -229,7 +229,8 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
|
||||
ref_sym = (reference_symbolic *)ref;
|
||||
|
||||
if (file_content->len < (header_len + 1))
|
||||
return GIT_EREFCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED,
|
||||
"Failed to parse loose reference. Object too short");
|
||||
|
||||
/*
|
||||
* Assume we have already checked for the header
|
||||
@ -246,7 +247,8 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
|
||||
/* remove newline at the end of file */
|
||||
eol = strchr(ref_sym->target, '\n');
|
||||
if (eol == NULL)
|
||||
return GIT_EREFCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED,
|
||||
"Failed to parse loose reference. Missing EOL");
|
||||
|
||||
*eol = '\0';
|
||||
if (eol[-1] == '\r')
|
||||
@ -257,6 +259,7 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
|
||||
|
||||
static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content)
|
||||
{
|
||||
int error;
|
||||
reference_oid *ref_oid;
|
||||
char *buffer;
|
||||
|
||||
@ -265,17 +268,19 @@ static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content)
|
||||
|
||||
/* File format: 40 chars (OID) + newline */
|
||||
if (file_content->len < GIT_OID_HEXSZ + 1)
|
||||
return GIT_EREFCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED,
|
||||
"Failed to parse loose reference. Reference too short");
|
||||
|
||||
if (git_oid_mkstr(&ref_oid->oid, buffer) < GIT_SUCCESS)
|
||||
return GIT_EREFCORRUPTED;
|
||||
if ((error = git_oid_mkstr(&ref_oid->oid, buffer)) < GIT_SUCCESS)
|
||||
return git__rethrow(GIT_EOBJCORRUPTED, "Failed to parse loose reference.");
|
||||
|
||||
buffer = buffer + GIT_OID_HEXSZ;
|
||||
if (*buffer == '\r')
|
||||
buffer++;
|
||||
|
||||
if (*buffer != '\n')
|
||||
return GIT_EREFCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED,
|
||||
"Failed to parse loose reference. Missing EOL");
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
@ -387,7 +392,7 @@ static int loose_write(git_reference *ref)
|
||||
strcpy(ref_contents, GIT_SYMREF);
|
||||
strcat(ref_contents, ref_sym->target);
|
||||
} else {
|
||||
error = GIT_EINVALIDREFSTATE;
|
||||
error = git__throw(GIT_EOBJCORRUPTED, "Failed to write reference. Invalid reference type");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
|
43
src/util.h
43
src/util.h
@ -6,16 +6,41 @@
|
||||
#define MSB(x, bits) ((x) & (~0ULL << (bitsizeof(x) - (bits))))
|
||||
|
||||
/*
|
||||
* Don't wrap malloc/calloc.
|
||||
* Use the default versions in glibc, and make
|
||||
* sure that any methods that allocate memory
|
||||
* return a GIT_ENOMEM error when allocation
|
||||
* fails.
|
||||
* Custom memory allocation wrappers
|
||||
* that set error code and error message
|
||||
* on allocation failure
|
||||
*/
|
||||
#define git__malloc malloc
|
||||
#define git__calloc calloc
|
||||
#define git__realloc realloc
|
||||
#define git__strdup strdup
|
||||
GIT_INLINE(void *) git__malloc(size_t len)
|
||||
{
|
||||
void *ptr = malloc(len);
|
||||
if (!ptr)
|
||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)len);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
GIT_INLINE(void *) git__calloc(size_t nelem, size_t elsize)
|
||||
{
|
||||
void *ptr = calloc(nelem, elsize);
|
||||
if (!ptr)
|
||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)elsize);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
GIT_INLINE(char *) git__strdup(const char *str)
|
||||
{
|
||||
char *ptr = strdup(str);
|
||||
if (!ptr)
|
||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to duplicate string");
|
||||
return ptr;
|
||||
}
|
||||
|
||||
GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
|
||||
{
|
||||
void *new_ptr = realloc(ptr, size);
|
||||
if (!new_ptr)
|
||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)size);
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
extern int git__fmt(char *, size_t, const char *, ...)
|
||||
GIT_FORMAT_PRINTF(3, 4);
|
||||
|
Loading…
Reference in New Issue
Block a user