Commit 60bc2d20c40e37e92e4e15479ac4dccbde069bec

Vicent Martí 2012-02-14T21:23:11

error-handling: Add new routines Obviously all the old throw routines are still in place, so we can gradually port over.

diff --git a/include/git2/errors.h b/include/git2/errors.h
index f617986..54da869 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -113,8 +113,23 @@ typedef enum {
 
 	/** The buffer is too short to satisfy the request */
 	GIT_ESHORTBUFFER = -32,
+} git_error_t;
+
+typedef struct {
+	char *message;
+	int klass;
 } git_error;
 
+typedef enum {
+	GITERR_NOMEMORY,
+
+} git_error_class;
+
+GIT_EXTERN(void) giterr_set(git_error **error_out, int error_class, const char *string, ...);
+GIT_EXTERN(void) giterr_set_oom(git_error **error);
+GIT_EXTERN(void) giterr_free(git_error *error);
+GIT_EXTERN(void) giterr_clear(git_error **error);
+
 /**
  * Return a detailed error string with the latest error
  * that occurred in the library.
diff --git a/src/errors.c b/src/errors.c
index 58e0976..0105c25 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -6,6 +6,7 @@
  */
 #include "common.h"
 #include "global.h"
+#include "posix.h"
 #include <stdarg.h>
 
 static struct {
@@ -102,3 +103,66 @@ void git_clearerror(void)
 	char *last_error = GIT_GLOBAL->error.last;
 	last_error[0] = '\0';
 }
+
+/********************************************
+ * New error handling
+ ********************************************/
+
+void giterr_set(git_error **error_out, int error_class, const char *string, ...)
+{
+	char error_str[1024];
+	va_list arglist;
+	git_error *error;
+
+	if (error_out == NULL)
+		return;
+
+	error = git__malloc(sizeof(git_error));
+	if (!error) {
+		giterr_set_oom(error_out);
+		return;
+	}
+
+	va_start(arglist, string);
+	p_vsnprintf(error_str, sizeof(error_str), string, arglist);
+	va_end(arglist);
+
+	error->message = git__strdup(error_str);
+	error->klass = error_class;
+
+	if (error->message == NULL) {
+		free(error);
+		giterr_set_oom(error_out);
+		return;
+	}
+
+	*error_out = error;
+}
+
+static git_error g_git_oom_error = {
+	"Out of memory",
+	GITERR_NOMEMORY
+};
+
+void giterr_set_oom(git_error **error)
+{
+	if (error != NULL)
+		*error = &g_git_oom_error;
+}
+
+void giterr_free(git_error *error)
+{
+	if (error == NULL || error == &g_git_oom_error)
+		return;
+
+	free(error->message);
+	free(error);
+}
+
+void giterr_clear(git_error **error)
+{
+	if (error != NULL) {
+		giterr_free(*error);
+		*error = NULL;
+	}
+}
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index 91585ae..8e70719 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -341,8 +341,12 @@ done:
 int p_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
 {
 #ifdef _MSC_VER
-	int len = _vsnprintf(buffer, count, format, argptr);
-	return (len < 0) ? _vscprintf(format, argptr) : len;
+	int len;
+
+	if (count == 0 || (len = _vsnprintf(buffer, count, format, argptr)) < 0)
+		return p_vscprintf(format, argptr);
+
+	return len;
 #else /* MinGW */
 	return vsnprintf(buffer, count, format, argptr);
 #endif
diff --git a/tests-clar/object/tree/frompath.c b/tests-clar/object/tree/frompath.c
index 3857d42..523a0b9 100644
--- a/tests-clar/object/tree/frompath.c
+++ b/tests-clar/object/tree/frompath.c
@@ -24,7 +24,7 @@ void test_object_tree_frompath__cleanup(void)
 	cl_fixture_cleanup("testrepo.git");
 }
 
-static void assert_tree_from_path(git_tree *root, const char *path, git_error expected_result, const char *expected_raw_oid)
+static void assert_tree_from_path(git_tree *root, const char *path, int expected_result, const char *expected_raw_oid)
 {
 	git_tree *containing_tree = NULL;