diff --git a/include/git2/errors.h b/include/git2/errors.h index e5f435926..f6d9bf2e3 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 1d85428b3..747bbf7ce 100644 --- a/src/common.h +++ b/src/common.h @@ -49,14 +49,24 @@ #include +/** + * 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 802ad3647..942a2f799 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 10c0cdd3f..512a4134d 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"