mirror of
https://github.com/libgit2/libgit2.git
synced 2026-01-25 11:06:32 +00:00
errors: never return a NULL error
Callers want to be able to simply call `git_error_last()->message`, not have to worry about whether `git_error_last()` returns NULL or not.
This commit is contained in:
@@ -118,10 +118,15 @@ typedef enum {
|
||||
* Return the last `git_error` object that was generated for the
|
||||
* current thread.
|
||||
*
|
||||
* The default behaviour of this function is to return NULL if no previous error has occurred.
|
||||
* However, libgit2's error strings are not cleared aggressively, so a prior
|
||||
* (unrelated) error may be returned. This can be avoided by only calling
|
||||
* this function if the prior call to a libgit2 API returned an error.
|
||||
* This function will never return NULL.
|
||||
*
|
||||
* Callers should not rely on this to determine whether an error has
|
||||
* occurred. For error checking, callers should examine the return
|
||||
* codes of libgit2 functions.
|
||||
*
|
||||
* This call can only reliably report error messages when an error
|
||||
* has occurred. (It may contain stale information if it is called
|
||||
* after a different function that succeeds.)
|
||||
*
|
||||
* @return A git_error object.
|
||||
*/
|
||||
|
||||
@@ -28,7 +28,12 @@ static git_error uninitialized_error = {
|
||||
|
||||
static git_error tlsdata_error = {
|
||||
"thread-local data initialization failure",
|
||||
GIT_ERROR
|
||||
GIT_ERROR_THREAD
|
||||
};
|
||||
|
||||
static git_error no_error = {
|
||||
"no error",
|
||||
GIT_ERROR_NONE
|
||||
};
|
||||
|
||||
static void set_error_from_buffer(int error_class)
|
||||
@@ -184,6 +189,9 @@ const git_error *git_error_last(void)
|
||||
if ((threadstate = git_threadstate_get()) == NULL)
|
||||
return &tlsdata_error;
|
||||
|
||||
if (!threadstate->last_error)
|
||||
return &no_error;
|
||||
|
||||
return threadstate->last_error;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ void test_config_include__missing(void)
|
||||
|
||||
git_error_clear();
|
||||
cl_git_pass(git_config_open_ondisk(&cfg, "including"));
|
||||
cl_assert(git_error_last() == NULL);
|
||||
cl_assert_equal_i(GIT_ERROR_NONE, git_error_last()->klass);
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
|
||||
cl_assert_equal_s("baz", buf.ptr);
|
||||
|
||||
@@ -126,7 +126,7 @@ void test_config_include__missing_homedir(void)
|
||||
|
||||
git_error_clear();
|
||||
cl_git_pass(git_config_open_ondisk(&cfg, "including"));
|
||||
cl_assert(git_error_last() == NULL);
|
||||
cl_assert_equal_i(GIT_ERROR_NONE, git_error_last()->klass);
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
|
||||
cl_assert_equal_s("baz", buf.ptr);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ void test_grafts_shallow__clears_errors(void)
|
||||
{
|
||||
g_repo = cl_git_sandbox_init("testrepo.git");
|
||||
cl_assert_equal_i(0, git_repository_is_shallow(g_repo));
|
||||
cl_assert_equal_p(NULL, git_error_last());
|
||||
cl_assert_equal_i(GIT_ERROR_NONE, git_error_last()->klass);
|
||||
}
|
||||
|
||||
void test_grafts_shallow__shallow_oids(void)
|
||||
|
||||
@@ -35,5 +35,5 @@ void test_repo_shallow__clears_errors(void)
|
||||
{
|
||||
g_repo = cl_git_sandbox_init("testrepo.git");
|
||||
cl_assert_equal_i(0, git_repository_is_shallow(g_repo));
|
||||
cl_assert_equal_p(NULL, git_error_last());
|
||||
cl_assert_equal_i(GIT_ERROR_NONE, git_error_last()->klass);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,8 @@ void test_assert__argument_with_void_return_type(void)
|
||||
|
||||
git_error_clear();
|
||||
cl_assert_equal_p(foo, fn_returns_string(foo));
|
||||
cl_assert_equal_p(NULL, git_error_last());
|
||||
cl_assert_equal_i(GIT_ERROR_NONE, git_error_last()->klass);
|
||||
cl_assert_equal_s("no error", git_error_last()->message);
|
||||
}
|
||||
|
||||
void test_assert__internal(void)
|
||||
|
||||
@@ -5,7 +5,10 @@ void test_errors__public_api(void)
|
||||
char *str_in_error;
|
||||
|
||||
git_error_clear();
|
||||
cl_assert(git_error_last() == NULL);
|
||||
|
||||
cl_assert(git_error_last() != NULL);
|
||||
cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
|
||||
cl_assert(strcmp(git_error_last()->message, "no error") == 0);
|
||||
|
||||
git_error_set_oom();
|
||||
|
||||
@@ -23,7 +26,9 @@ void test_errors__public_api(void)
|
||||
cl_assert(str_in_error != NULL);
|
||||
|
||||
git_error_clear();
|
||||
cl_assert(git_error_last() == NULL);
|
||||
cl_assert(git_error_last() != NULL);
|
||||
cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
|
||||
cl_assert(strcmp(git_error_last()->message, "no error") == 0);
|
||||
}
|
||||
|
||||
#include "common.h"
|
||||
@@ -35,7 +40,9 @@ void test_errors__new_school(void)
|
||||
char *str_in_error;
|
||||
|
||||
git_error_clear();
|
||||
cl_assert(git_error_last() == NULL);
|
||||
cl_assert(git_error_last() != NULL);
|
||||
cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
|
||||
cl_assert(strcmp(git_error_last()->message, "no error") == 0);
|
||||
|
||||
git_error_set_oom(); /* internal fn */
|
||||
|
||||
@@ -53,7 +60,9 @@ void test_errors__new_school(void)
|
||||
cl_assert(str_in_error != NULL);
|
||||
|
||||
git_error_clear();
|
||||
cl_assert(git_error_last() == NULL);
|
||||
cl_assert(git_error_last() != NULL);
|
||||
cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
|
||||
cl_assert(strcmp(git_error_last()->message, "no error") == 0);
|
||||
|
||||
do {
|
||||
struct stat st;
|
||||
@@ -91,7 +100,9 @@ void test_errors__restore(void)
|
||||
git_error_state err_state = {0};
|
||||
|
||||
git_error_clear();
|
||||
cl_assert(git_error_last() == NULL);
|
||||
cl_assert(git_error_last() != NULL);
|
||||
cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
|
||||
cl_assert(strcmp(git_error_last()->message, "no error") == 0);
|
||||
|
||||
cl_assert_equal_i(0, git_error_state_capture(&err_state, 0));
|
||||
|
||||
@@ -100,7 +111,9 @@ void test_errors__restore(void)
|
||||
git_error_set(42, "Foo: %s", "bar");
|
||||
cl_assert_equal_i(-1, git_error_state_capture(&err_state, -1));
|
||||
|
||||
cl_assert(git_error_last() == NULL);
|
||||
cl_assert(git_error_last() != NULL);
|
||||
cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
|
||||
cl_assert(strcmp(git_error_last()->message, "no error") == 0);
|
||||
|
||||
git_error_set(99, "Bar: %s", "foo");
|
||||
|
||||
@@ -128,7 +141,9 @@ void test_errors__free_state(void)
|
||||
|
||||
git_error_state_restore(&err_state);
|
||||
|
||||
cl_assert(git_error_last() == NULL);
|
||||
cl_assert(git_error_last() != NULL);
|
||||
cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
|
||||
cl_assert(strcmp(git_error_last()->message, "no error") == 0);
|
||||
}
|
||||
|
||||
void test_errors__restore_oom(void)
|
||||
@@ -144,7 +159,9 @@ void test_errors__restore_oom(void)
|
||||
|
||||
cl_assert_equal_i(-1, git_error_state_capture(&err_state, -1));
|
||||
|
||||
cl_assert(git_error_last() == NULL);
|
||||
cl_assert(git_error_last() != NULL);
|
||||
cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
|
||||
cl_assert(strcmp(git_error_last()->message, "no error") == 0);
|
||||
cl_assert_equal_i(GIT_ERROR_NOMEMORY, err_state.error_msg.klass);
|
||||
cl_assert_equal_s("Out of memory", err_state.error_msg.message);
|
||||
|
||||
@@ -204,11 +221,15 @@ void test_errors__integer_overflow_sets_oom(void)
|
||||
|
||||
git_error_clear();
|
||||
cl_assert(!GIT_ADD_SIZET_OVERFLOW(&out, SIZE_MAX-1, 1));
|
||||
cl_assert_equal_p(NULL, git_error_last());
|
||||
cl_assert(git_error_last() != NULL);
|
||||
cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
|
||||
cl_assert(strcmp(git_error_last()->message, "no error") == 0);
|
||||
|
||||
git_error_clear();
|
||||
cl_assert(!GIT_ADD_SIZET_OVERFLOW(&out, 42, 69));
|
||||
cl_assert_equal_p(NULL, git_error_last());
|
||||
cl_assert(git_error_last() != NULL);
|
||||
cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
|
||||
cl_assert(strcmp(git_error_last()->message, "no error") == 0);
|
||||
|
||||
git_error_clear();
|
||||
cl_assert(GIT_ADD_SIZET_OVERFLOW(&out, SIZE_MAX, SIZE_MAX));
|
||||
|
||||
Reference in New Issue
Block a user