diff options
Diffstat (limited to 'src/errors.c')
-rw-r--r-- | src/errors.c | 163 |
1 files changed, 89 insertions, 74 deletions
diff --git a/src/errors.c b/src/errors.c index 81770e786..d43d7d9b5 100644 --- a/src/errors.c +++ b/src/errors.c @@ -1,104 +1,119 @@ /* - * Copyright (C) 2009-2011 the libgit2 contributors + * Copyright (C) 2009-2012 the libgit2 contributors * * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. */ #include "common.h" #include "global.h" +#include "posix.h" +#include "buffer.h" #include <stdarg.h> -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 or config variable 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"}, - {GIT_EAMBIGUOUSOIDPREFIX, "The given oid prefix is ambiguous"}, +/******************************************** + * New error handling + ********************************************/ + +static git_error g_git_oom_error = { + "Out of memory", + GITERR_NOMEMORY }; -const char *git_strerror(int num) +static void set_error(int error_class, char *string) { - size_t i; + git_error *error = &GIT_GLOBAL->error_t; - 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; + git__free(error->message); - return "Unknown error"; -} + error->message = string; + error->klass = error_class; -#define ERROR_MAX_LEN 1024 + GIT_GLOBAL->last_error = error; +} -void git___rethrow(const char *msg, ...) +void giterr_set_oom(void) { - char new_error[ERROR_MAX_LEN]; - char *last_error; - char *old_error = NULL; - - va_list va; - - last_error = GIT_GLOBAL->error.last; - - va_start(va, msg); - vsnprintf(new_error, ERROR_MAX_LEN, msg, va); - va_end(va); - - old_error = git__strdup(last_error); - - snprintf(last_error, ERROR_MAX_LEN, "%s \n - %s", new_error, old_error); + GIT_GLOBAL->last_error = &g_git_oom_error; +} - git__free(old_error); +void giterr_set(int error_class, const char *string, ...) +{ + git_buf buf = GIT_BUF_INIT; + va_list arglist; + + int unix_error_code = 0; + +#ifdef GIT_WIN32 + DWORD win32_error_code = 0; +#endif + + if (error_class == GITERR_OS) { + unix_error_code = errno; + errno = 0; + +#ifdef GIT_WIN32 + win32_error_code = GetLastError(); + SetLastError(0); +#endif + } + + va_start(arglist, string); + git_buf_vprintf(&buf, string, arglist); + va_end(arglist); + + /* automatically suffix strerror(errno) for GITERR_OS errors */ + if (error_class == GITERR_OS) { + + if (unix_error_code != 0) { + git_buf_PUTS(&buf, ": "); + git_buf_puts(&buf, strerror(unix_error_code)); + } + +#ifdef GIT_WIN32 + else if (win32_error_code != 0) { + LPVOID lpMsgBuf = NULL; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, win32_error_code, 0, (LPTSTR) &lpMsgBuf, 0, NULL); + + if (lpMsgBuf) { + git_buf_PUTS(&buf, ": "); + git_buf_puts(&buf, lpMsgBuf); + LocalFree(lpMsgBuf); + } + } +#endif + } + + if (!git_buf_oom(&buf)) + set_error(error_class, git_buf_detach(&buf)); } -void git___throw(const char *msg, ...) +void giterr_set_str(int error_class, const char *string) { - va_list va; + char *message = git__strdup(string); - va_start(va, msg); - vsnprintf(GIT_GLOBAL->error.last, ERROR_MAX_LEN, msg, va); - va_end(va); + if (message) + set_error(error_class, message); } -const char *git_lasterror(void) +void giterr_set_regex(const regex_t *regex, int error_code) { - char *last_error = GIT_GLOBAL->error.last; - - if (!last_error[0]) - return NULL; + char error_buf[1024]; + regerror(error_code, regex, error_buf, sizeof(error_buf)); + giterr_set_str(GITERR_REGEX, error_buf); +} - return last_error; +void giterr_clear(void) +{ + GIT_GLOBAL->last_error = NULL; } -void git_clearerror(void) +const git_error *giterr_last(void) { - char *last_error = GIT_GLOBAL->error.last; - last_error[0] = '\0'; + return GIT_GLOBAL->last_error; } + |