Merge pull request #947 from arrbee/public-error-set Make giterr_set_str() and giterr_set_oom() public APIs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
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"