Commit 854b701c8a799a484ef48d8b595601ab29876b57

Edward Thomson 2015-08-03T15:02:02

Merge remote-tracking branches 'upstream/pr/3323' and 'upstream/pr/3329'

diff --git a/src/errors.c b/src/errors.c
index f10430c..973326c 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -18,19 +18,30 @@ static git_error g_git_oom_error = {
 	GITERR_NOMEMORY
 };
 
-static void set_error(int error_class, char *string)
+static void set_error_from_buffer(int error_class)
 {
 	git_error *error = &GIT_GLOBAL->error_t;
+	git_buf *buf = &GIT_GLOBAL->error_buf;
 
-	if (error->message != string)
-		git__free(error->message);
-
-	error->message = string;
+	error->message = buf->ptr;
 	error->klass = error_class;
 
 	GIT_GLOBAL->last_error = error;
 }
 
+static void set_error(int error_class, char *string)
+{
+	git_buf *buf = &GIT_GLOBAL->error_buf;
+
+	git_buf_clear(buf);
+	if (string) {
+		git_buf_puts(buf, string);
+		git__free(string);
+	}
+
+	set_error_from_buffer(error_class);
+}
+
 void giterr_set_oom(void)
 {
 	GIT_GLOBAL->last_error = &g_git_oom_error;
@@ -38,27 +49,28 @@ void giterr_set_oom(void)
 
 void giterr_set(int error_class, const char *string, ...)
 {
-	git_buf buf = GIT_BUF_INIT;
 	va_list arglist;
 #ifdef GIT_WIN32
 	DWORD win32_error_code = (error_class == GITERR_OS) ? GetLastError() : 0;
 #endif
 	int error_code = (error_class == GITERR_OS) ? errno : 0;
+	git_buf *buf = &GIT_GLOBAL->error_buf;
 
+	git_buf_clear(buf);
 	if (string) {
 		va_start(arglist, string);
-		git_buf_vprintf(&buf, string, arglist);
+		git_buf_vprintf(buf, string, arglist);
 		va_end(arglist);
 
 		if (error_class == GITERR_OS)
-			git_buf_PUTS(&buf, ": ");
+			git_buf_PUTS(buf, ": ");
 	}
 
 	if (error_class == GITERR_OS) {
 #ifdef GIT_WIN32
 		char * win32_error = git_win32_get_error_message(win32_error_code);
 		if (win32_error) {
-			git_buf_puts(&buf, win32_error);
+			git_buf_puts(buf, win32_error);
 			git__free(win32_error);
 
 			SetLastError(0);
@@ -66,26 +78,29 @@ void giterr_set(int error_class, const char *string, ...)
 		else
 #endif
 		if (error_code)
-			git_buf_puts(&buf, strerror(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)
 {
-	char *message;
+	git_buf *buf = &GIT_GLOBAL->error_buf;
 
 	assert(string);
 
-	message = git__strdup(string);
+	if (!string)
+		return;
 
-	if (message)
-		set_error(error_class, message);
+	git_buf_clear(buf);
+	git_buf_puts(buf, string);
+	if (!git_buf_oom(buf))
+		set_error_from_buffer(error_class);
 }
 
 int giterr_set_regex(const regex_t *regex, int error_code)
@@ -119,13 +134,14 @@ void giterr_clear(void)
 static int giterr_detach(git_error *cpy)
 {
 	git_error *error = GIT_GLOBAL->last_error;
+	git_buf *buf = &GIT_GLOBAL->error_buf;
 
 	assert(cpy);
 
 	if (!error)
 		return -1;
 
-	cpy->message = error->message;
+	cpy->message = git_buf_detach(buf);
 	cpy->klass = error->klass;
 
 	if (error != &g_git_oom_error) {
diff --git a/src/global.c b/src/global.c
index 37a47bd..3d37ee4 100644
--- a/src/global.c
+++ b/src/global.c
@@ -279,18 +279,19 @@ int git_libgit2_shutdown(void)
 
 git_global_st *git__global_state(void)
 {
-	void *ptr;
+	git_global_st *ptr;
 
 	assert(git_atomic_get(&git__n_inits) > 0);
 
 	if ((ptr = TlsGetValue(_tls_index)) != NULL)
 		return ptr;
 
-	ptr = git__malloc(sizeof(git_global_st));
+	ptr = git__calloc(1, sizeof(git_global_st));
 	if (!ptr)
 		return NULL;
 
-	memset(ptr, 0x0, sizeof(git_global_st));
+	git_buf_init(&ptr->error_buf, 0);
+
 	TlsSetValue(_tls_index, ptr);
 	return ptr;
 }
@@ -378,18 +379,18 @@ int git_libgit2_shutdown(void)
 
 git_global_st *git__global_state(void)
 {
-	void *ptr;
+	git_global_st *ptr;
 
 	assert(git_atomic_get(&git__n_inits) > 0);
 
 	if ((ptr = pthread_getspecific(_tls_key)) != NULL)
 		return ptr;
 
-	ptr = git__malloc(sizeof(git_global_st));
+	ptr = git__calloc(1, sizeof(git_global_st));
 	if (!ptr)
 		return NULL;
 
-	memset(ptr, 0x0, sizeof(git_global_st));
+	git_buf_init(&ptr->error_buf, 0);
 	pthread_setspecific(_tls_key, ptr);
 	return ptr;
 }
@@ -407,6 +408,7 @@ int git_libgit2_init(void)
 		ssl_inited = 1;
 	}
 
+	git_buf_init(&__state.error_buf, 0);
 	return git_atomic_inc(&git__n_inits);
 }
 
diff --git a/src/global.h b/src/global.h
index fdad6ba..37e909a 100644
--- a/src/global.h
+++ b/src/global.h
@@ -14,6 +14,7 @@
 typedef struct {
 	git_error *last_error;
 	git_error error_t;
+	git_buf error_buf;
 	char oid_fmt[GIT_OID_HEXSZ+1];
 } git_global_st;