]> git.proxmox.com Git - libgit2.git/blobdiff - src/errors.c
New upstream version 1.3.0+dfsg.1
[libgit2.git] / src / errors.c
index 3aa1757b208d7ad8c38ec8928339fb4fc61269bb..ce883b2dad17758ba3936b8c58d5f04f2a12a012 100644 (file)
@@ -4,11 +4,13 @@
  * 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 "threadstate.h"
 #include "posix.h"
 #include "buffer.h"
-#include <stdarg.h>
+#include "libgit2.h"
 
 /********************************************
  * New error handling
 
 static git_error g_git_oom_error = {
        "Out of memory",
-       GITERR_NOMEMORY
+       GIT_ERROR_NOMEMORY
 };
 
+static git_error g_git_uninitialized_error = {
+       "libgit2 has not been initialized; you must call git_libgit2_init",
+       GIT_ERROR_INVALID
+};
+
+static void set_error_from_buffer(int error_class)
+{
+       git_error *error = &GIT_THREADSTATE->error_t;
+       git_buf *buf = &GIT_THREADSTATE->error_buf;
+
+       error->message = buf->ptr;
+       error->klass = error_class;
+
+       GIT_THREADSTATE->last_error = error;
+}
+
 static void set_error(int error_class, char *string)
 {
-       git_error *error = &GIT_GLOBAL->error_t;
+       git_buf *buf = &GIT_THREADSTATE->error_buf;
 
-       git__free(error->message);
+       git_buf_clear(buf);
+       if (string) {
+               git_buf_puts(buf, string);
+               git__free(string);
+       }
 
-       error->message = string;
-       error->klass = error_class;
+       set_error_from_buffer(error_class);
+}
 
-       GIT_GLOBAL->last_error = error;
+void git_error_set_oom(void)
+{
+       GIT_THREADSTATE->last_error = &g_git_oom_error;
 }
 
-void giterr_set_oom(void)
+void git_error_set(int error_class, const char *fmt, ...)
 {
-       GIT_GLOBAL->last_error = &g_git_oom_error;
+       va_list ap;
+
+       va_start(ap, fmt);
+       git_error_vset(error_class, fmt, ap);
+       va_end(ap);
 }
 
-void giterr_set(int error_class, const char *string, ...)
+void git_error_vset(int error_class, const char *fmt, va_list ap)
 {
-       git_buf buf = GIT_BUF_INIT;
-       va_list arglist;
 #ifdef GIT_WIN32
-       DWORD win32_error_code = (error_class == GITERR_OS) ? GetLastError() : 0;
+       DWORD win32_error_code = (error_class == GIT_ERROR_OS) ? GetLastError() : 0;
 #endif
-       int error_code = (error_class == GITERR_OS) ? errno : 0;
-
-       va_start(arglist, string);
-       git_buf_vprintf(&buf, string, arglist);
-       va_end(arglist);
+       int error_code = (error_class == GIT_ERROR_OS) ? errno : 0;
+       git_buf *buf = &GIT_THREADSTATE->error_buf;
+
+       git_buf_clear(buf);
+       if (fmt) {
+               git_buf_vprintf(buf, fmt, ap);
+               if (error_class == GIT_ERROR_OS)
+                       git_buf_PUTS(buf, ": ");
+       }
 
-       if (error_class == GITERR_OS) {
+       if (error_class == GIT_ERROR_OS) {
 #ifdef GIT_WIN32
                char * win32_error = git_win32_get_error_message(win32_error_code);
                if (win32_error) {
-                       git_buf_PUTS(&buf, ": ");
-                       git_buf_puts(&buf, win32_error);
+                       git_buf_puts(buf, win32_error);
                        git__free(win32_error);
 
                        SetLastError(0);
                }
                else
 #endif
-               if (error_code) {
-                       git_buf_PUTS(&buf, ": ");
-                       git_buf_puts(&buf, strerror(error_code));
-               }
+               if (error_code)
+                       git_buf_puts(buf, strerror(error_code));
 
                if (error_code)
                        errno = 0;
        }
 
-       if (!git_buf_oom(&buf))
-               set_error(error_class, git_buf_detach(&buf));
+       if (!git_buf_oom(buf))
+               set_error_from_buffer(error_class);
 }
 
-void giterr_set_str(int error_class, const char *string)
+int git_error_set_str(int error_class, const char *string)
 {
-       char *message;
+       git_buf *buf = &GIT_THREADSTATE->error_buf;
+
+       GIT_ASSERT_ARG(string);
 
-       assert(string);
+       git_buf_clear(buf);
+       git_buf_puts(buf, string);
 
-       message = git__strdup(string);
+       if (git_buf_oom(buf))
+               return -1;
 
-       if (message)
-               set_error(error_class, message);
+       set_error_from_buffer(error_class);
+       return 0;
 }
 
-int giterr_set_regex(const regex_t *regex, int error_code)
+void git_error_clear(void)
 {
-       char error_buf[1024];
-       regerror(error_code, regex, error_buf, sizeof(error_buf));
-       giterr_set_str(GITERR_REGEX, error_buf);
+       if (GIT_THREADSTATE->last_error != NULL) {
+               set_error(0, NULL);
+               GIT_THREADSTATE->last_error = NULL;
+       }
 
-       if (error_code == REG_NOMATCH)
-               return GIT_ENOTFOUND;
-       else if (error_code > REG_BADPAT)
-               return GIT_EINVALIDSPEC;
-       else
-               return -1;
+       errno = 0;
+#ifdef GIT_WIN32
+       SetLastError(0);
+#endif
 }
 
-void giterr_clear(void)
+const git_error *git_error_last(void)
 {
-       GIT_GLOBAL->last_error = NULL;
+       /* If the library is not initialized, return a static error. */
+       if (!git_libgit2_init_count())
+               return &g_git_uninitialized_error;
 
-       errno = 0;
+       return GIT_THREADSTATE->last_error;
+}
+
+int git_error_state_capture(git_error_state *state, int error_code)
+{
+       git_error *error = GIT_THREADSTATE->last_error;
+       git_buf *error_buf = &GIT_THREADSTATE->error_buf;
+
+       memset(state, 0, sizeof(git_error_state));
+
+       if (!error_code)
+               return 0;
+
+       state->error_code = error_code;
+       state->oom = (error == &g_git_oom_error);
+
+       if (error) {
+               state->error_msg.klass = error->klass;
+
+               if (state->oom)
+                       state->error_msg.message = g_git_oom_error.message;
+               else
+                       state->error_msg.message = git_buf_detach(error_buf);
+       }
+
+       git_error_clear();
+       return error_code;
+}
+
+int git_error_state_restore(git_error_state *state)
+{
+       int ret = 0;
+
+       git_error_clear();
+
+       if (state && state->error_msg.message) {
+               if (state->oom)
+                       git_error_set_oom();
+               else
+                       set_error(state->error_msg.klass, state->error_msg.message);
+
+               ret = state->error_code;
+               memset(state, 0, sizeof(git_error_state));
+       }
+
+       return ret;
+}
+
+void git_error_state_free(git_error_state *state)
+{
+       if (!state)
+               return;
+
+       if (!state->oom)
+               git__free(state->error_msg.message);
+
+       memset(state, 0, sizeof(git_error_state));
+}
+
+int git_error_system_last(void)
+{
 #ifdef GIT_WIN32
-       SetLastError(0);
+       return GetLastError();
+#else
+       return errno;
+#endif
+}
+
+void git_error_system_set(int code)
+{
+#ifdef GIT_WIN32
+       SetLastError(code);
+#else
+       errno = code;
 #endif
 }
 
+/* Deprecated error values and functions */
+
+#ifndef GIT_DEPRECATE_HARD
 const git_error *giterr_last(void)
 {
-       return GIT_GLOBAL->last_error;
+       return git_error_last();
 }
 
+void giterr_clear(void)
+{
+       git_error_clear();
+}
+
+void giterr_set_str(int error_class, const char *string)
+{
+       git_error_set_str(error_class, string);
+}
+
+void giterr_set_oom(void)
+{
+       git_error_set_oom();
+}
+#endif