diff --git a/include/git2/errors.h b/include/git2/errors.h index a454ac956..5f5d0ab1f 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -8,6 +8,7 @@ #define INCLUDE_git_errors_h__ #include "common.h" +#include "buffer.h" /** * @file git2/errors.h @@ -45,6 +46,7 @@ typedef struct { /** Error classes */ typedef enum { + GITERR_NONE = 0, GITERR_NOMEMORY, GITERR_OS, GITERR_INVALID, @@ -84,6 +86,21 @@ GIT_EXTERN(const git_error *) giterr_last(void); */ GIT_EXTERN(void) giterr_clear(void); +/** + * Get the last error data and clear it. + * + * This copies the last error message into the given `git_buf` and returns + * the associated `git_error_t`, leaving the error cleared as if + * `giterr_clear` had been called. You must call `git_buf_free` on the + * message to release the memory. + * + * Note: it is possible that this will return `GITERR_NONE` and set the + * buffer to NULL, so be prepared for that condition. Also, if the last + * error was an out-of-memory error, this will return `GITERR_NOMEMORY` + * but also leave the buffer set to NULL (to avoid allocation). + */ +GIT_EXTERN(git_error_t) giterr_detach(git_buf *message); + /** * Set the error message string for this thread. * diff --git a/src/errors.c b/src/errors.c index c9d9e4e37..70b5f2668 100644 --- a/src/errors.c +++ b/src/errors.c @@ -112,6 +112,29 @@ void giterr_clear(void) #endif } +git_error_t giterr_detach(git_buf *message) +{ + git_error_t rval; + git_error *error = GIT_GLOBAL->last_error; + + assert(message); + + git_buf_free(message); + + if (!error) + return GITERR_NONE; + + rval = error->klass; + + if (error != &g_git_oom_error) + git_buf_attach(message, error->message, 0); + + error->message = NULL; + giterr_clear(); + + return rval; +} + const git_error *giterr_last(void) { return GIT_GLOBAL->last_error;