Commit 1a628100534a315bd00361fc3d32df671923c107

Russell Belfer 2012-09-21T15:04:39

Make giterr_set_str public There has been discussion for a while about making some set of the `giterr_set` type functions part of the public API for code that is implementing new backends to libgit2. This makes the `giterr_set_str()` and `giterr_set_oom()` functions public.

diff --git a/include/git2/errors.h b/include/git2/errors.h
index e5f4359..f6d9bf2 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -71,6 +71,40 @@ GIT_EXTERN(const git_error *) giterr_last(void);
  */
 GIT_EXTERN(void) giterr_clear(void);
 
+/**
+ * Set the error message string for this thread.
+ *
+ * This function is public so that custom ODB backends and the like can
+ * relay an error message through libgit2.  Most regular users of libgit2
+ * will never need to call this function -- actually, calling it in most
+ * circumstances (for example, calling from within a callback function)
+ * will just end up having the value overwritten by libgit2 internals.
+ *
+ * This error message is stored in thread-local storage and only applies
+ * to the particular thread that this libgit2 call is made from.
+ *
+ * NOTE: Passing the `error_class` as GITERR_OS has a special behavior: we
+ * attempt to append the system default error message for the last OS error
+ * that occurred and then clear the last error.  The specific implementation
+ * of looking up and clearing this last OS error will vary by platform.
+ *
+ * @param error_class One of the `git_error_t` enum above describing the
+ *                    general subsystem that is responsible for the error.
+ * @param message The formatted error message to keep
+ */
+GIT_EXTERN(void) giterr_set_str(int error_class, const char *string);
+
+/**
+ * Set the error message to a special value for memory allocation failure.
+ *
+ * The normal `giterr_set_str()` function attempts to `strdup()` the string
+ * that is passed in.  This is not a good idea when the error in question
+ * is a memory allocation failure.  That circumstance has a special setter
+ * function that sets the error string to a known and statically allocated
+ * internal value.
+ */
+GIT_EXTERN(void) giterr_set_oom(void);
+
 /** @} */
 GIT_END_DECL
 #endif
diff --git a/src/common.h b/src/common.h
index 1d85428..747bbf7 100644
--- a/src/common.h
+++ b/src/common.h
@@ -49,14 +49,24 @@
 
 #include <regex.h>
 
+/**
+ * Check a pointer allocation result, returning -1 if it failed.
+ */
 #define GITERR_CHECK_ALLOC(ptr) if (ptr == NULL) { return -1; }
 
-void giterr_set_oom(void);
+/**
+ * Set the error message for this thread, formatting as needed.
+ */
 void giterr_set(int error_class, const char *string, ...);
-void giterr_clear(void);
-void giterr_set_str(int error_class, const char *string);
+
+/**
+ * Set the error message for a regex failure, using the internal regex
+ * error code lookup.
+ */
 void giterr_set_regex(const regex_t *regex, int error_code);
 
+/* NOTE: other giterr functions are in the public errors.h header file */
+
 #include "util.h"
 
 typedef struct git_transport git_transport;
diff --git a/src/errors.c b/src/errors.c
index 802ad36..942a2f7 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -94,7 +94,11 @@ void giterr_set(int error_class, const char *string, ...)
 
 void giterr_set_str(int error_class, const char *string)
 {
-	char *message = git__strdup(string);
+	char *message;
+
+	assert(string);
+
+	message = git__strdup(string);
 
 	if (message)
 		set_error(error_class, message);
diff --git a/tests-clar/core/errors.c b/tests-clar/core/errors.c
index 10c0cdd..512a413 100644
--- a/tests-clar/core/errors.c
+++ b/tests-clar/core/errors.c
@@ -1,4 +1,31 @@
 #include "clar_libgit2.h"
+
+void test_core_errors__public_api(void)
+{
+	char *str_in_error;
+
+	giterr_clear();
+	cl_assert(giterr_last() == NULL);
+
+	giterr_set_oom();
+
+	cl_assert(giterr_last() != NULL);
+	cl_assert(giterr_last()->klass == GITERR_NOMEMORY);
+	str_in_error = strstr(giterr_last()->message, "memory");
+	cl_assert(str_in_error != NULL);
+
+	giterr_clear();
+
+	giterr_set_str(GITERR_REPOSITORY, "This is a test");
+
+	cl_assert(giterr_last() != NULL);
+	str_in_error = strstr(giterr_last()->message, "This is a test");
+	cl_assert(str_in_error != NULL);
+
+	giterr_clear();
+	cl_assert(giterr_last() == NULL);
+}
+
 #include "common.h"
 #include "util.h"
 #include "posix.h"