summaryrefslogtreecommitdiff
path: root/src/errors.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/errors.c')
-rw-r--r--src/errors.c112
1 files changed, 87 insertions, 25 deletions
diff --git a/src/errors.c b/src/errors.c
index 81770e786..22b8ae7bf 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -4,7 +4,10 @@
* 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 "errors.h"
+#include "posix.h"
#include "global.h"
#include <stdarg.h>
@@ -55,50 +58,109 @@ const char *git_strerror(int num)
return "Unknown error";
}
-#define ERROR_MAX_LEN 1024
+static git_error git_error_OOM = {
+ GIT_ENOMEM,
+ "out of memory",
+ NULL,
+ NULL,
+ -1
+};
+
+git_error * git_error_oom(void)
+{
+ /*
+ * Throw an out-of-memory error:
+ * what we return is actually a static pointer, because on
+ * oom situations we cannot afford to allocate a new error
+ * object.
+ *
+ * The `git_error_free` function will take care of not
+ * freeing this special type of error.
+ *
+ */
+ return &git_error_OOM;
+}
-void git___rethrow(const char *msg, ...)
+git_error * git_error_createf(const char *file, unsigned int line, int code,
+ const char *fmt, ...)
{
- char new_error[ERROR_MAX_LEN];
- char *last_error;
- char *old_error = NULL;
+ git_error *err;
+ va_list ap;
+ size_t size;
- va_list va;
+ err = git__malloc(sizeof(git_error));
+ if (err == NULL)
+ return git_error_oom();
- last_error = GIT_GLOBAL->error.last;
+ memset(err, 0x0, sizeof(git_error));
- va_start(va, msg);
- vsnprintf(new_error, ERROR_MAX_LEN, msg, va);
- va_end(va);
+ va_start(ap, fmt);
+ size = p_vsnprintf(err->msg, 0, fmt, ap);
+ va_end(ap);
- old_error = git__strdup(last_error);
+ size++;
- snprintf(last_error, ERROR_MAX_LEN, "%s \n - %s", new_error, old_error);
+ err->msg = git__malloc(size);
+ if (err->msg == NULL) {
+ free(err);
+ return git_error_oom();
+ }
- git__free(old_error);
+ va_start(ap, fmt);
+ size = p_vsnprintf(err->msg, size, fmt, ap);
+ va_end(ap);
+
+ err->code = code;
+ err->child = GIT_GLOBAL->git_errno;
+ err->file = file;
+ err->line = line;
+
+ GIT_GLOBAL->git_errno = err;
+
+ return err;
}
-void git___throw(const char *msg, ...)
+git_error * git_error__quick_wrap(const char *file, int line,
+ git_error_code error, const char *msg)
{
- va_list va;
+ if (error == GIT_SUCCESS)
+ return GIT_SUCCESS;
- va_start(va, msg);
- vsnprintf(GIT_GLOBAL->error.last, ERROR_MAX_LEN, msg, va);
- va_end(va);
+ return git_error_createf(file, line, error, "%s", msg);
}
-const char *git_lasterror(void)
+void git_error_free(git_error *err)
{
- char *last_error = GIT_GLOBAL->error.last;
+ if (err == NULL)
+ return;
+
+ if (err->child)
+ git_error_free(err->child);
- if (!last_error[0])
- return NULL;
+ if (err->msg)
+ free(err->msg);
- return last_error;
+ free(err);
}
void git_clearerror(void)
{
- char *last_error = GIT_GLOBAL->error.last;
- last_error[0] = '\0';
+ git_error_free(GIT_GLOBAL->git_errno);
+ GIT_GLOBAL->git_errno = NULL;
+}
+
+const char *git_lasterror(void)
+{
+ return GIT_GLOBAL->git_errno == NULL ? NULL : GIT_GLOBAL->git_errno->msg;
+}
+
+void git_error_print_stack(git_error *error_in)
+{
+ git_error *error;
+
+ if (error_in == NULL)
+ error_in = GIT_GLOBAL->git_errno;
+
+ for (error = error_in; error; error = error->child)
+ fprintf(stderr, "%s:%u %s\n", error->file, error->line, error->msg);
}