]> git.proxmox.com Git - libgit2.git/blob - src/errors.c
Merge pull request #3377 from dleehr/fix-push-cb
[libgit2.git] / src / errors.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7 #include "common.h"
8 #include "global.h"
9 #include "posix.h"
10 #include "buffer.h"
11
12 /********************************************
13 * New error handling
14 ********************************************/
15
16 static git_error g_git_oom_error = {
17 "Out of memory",
18 GITERR_NOMEMORY
19 };
20
21 static void set_error_from_buffer(int error_class)
22 {
23 git_error *error = &GIT_GLOBAL->error_t;
24 git_buf *buf = &GIT_GLOBAL->error_buf;
25
26 error->message = buf->ptr;
27 error->klass = error_class;
28
29 GIT_GLOBAL->last_error = error;
30 }
31
32 static void set_error(int error_class, char *string)
33 {
34 git_buf *buf = &GIT_GLOBAL->error_buf;
35
36 git_buf_clear(buf);
37 if (string) {
38 git_buf_puts(buf, string);
39 git__free(string);
40 }
41
42 set_error_from_buffer(error_class);
43 }
44
45 void giterr_set_oom(void)
46 {
47 GIT_GLOBAL->last_error = &g_git_oom_error;
48 }
49
50 void giterr_set(int error_class, const char *string, ...)
51 {
52 va_list arglist;
53 #ifdef GIT_WIN32
54 DWORD win32_error_code = (error_class == GITERR_OS) ? GetLastError() : 0;
55 #endif
56 int error_code = (error_class == GITERR_OS) ? errno : 0;
57 git_buf *buf = &GIT_GLOBAL->error_buf;
58
59 git_buf_clear(buf);
60 if (string) {
61 va_start(arglist, string);
62 git_buf_vprintf(buf, string, arglist);
63 va_end(arglist);
64
65 if (error_class == GITERR_OS)
66 git_buf_PUTS(buf, ": ");
67 }
68
69 if (error_class == GITERR_OS) {
70 #ifdef GIT_WIN32
71 char * win32_error = git_win32_get_error_message(win32_error_code);
72 if (win32_error) {
73 git_buf_puts(buf, win32_error);
74 git__free(win32_error);
75
76 SetLastError(0);
77 }
78 else
79 #endif
80 if (error_code)
81 git_buf_puts(buf, strerror(error_code));
82
83 if (error_code)
84 errno = 0;
85 }
86
87 if (!git_buf_oom(buf))
88 set_error_from_buffer(error_class);
89 }
90
91 void giterr_set_str(int error_class, const char *string)
92 {
93 git_buf *buf = &GIT_GLOBAL->error_buf;
94
95 assert(string);
96
97 if (!string)
98 return;
99
100 git_buf_clear(buf);
101 git_buf_puts(buf, string);
102 if (!git_buf_oom(buf))
103 set_error_from_buffer(error_class);
104 }
105
106 int giterr_set_regex(const regex_t *regex, int error_code)
107 {
108 char error_buf[1024];
109
110 assert(error_code);
111
112 regerror(error_code, regex, error_buf, sizeof(error_buf));
113 giterr_set_str(GITERR_REGEX, error_buf);
114
115 if (error_code == REG_NOMATCH)
116 return GIT_ENOTFOUND;
117
118 return GIT_EINVALIDSPEC;
119 }
120
121 void giterr_clear(void)
122 {
123 if (GIT_GLOBAL->last_error != NULL) {
124 set_error(0, NULL);
125 GIT_GLOBAL->last_error = NULL;
126 }
127
128 errno = 0;
129 #ifdef GIT_WIN32
130 SetLastError(0);
131 #endif
132 }
133
134 const git_error *giterr_last(void)
135 {
136 return GIT_GLOBAL->last_error;
137 }
138
139 int giterr_state_capture(git_error_state *state, int error_code)
140 {
141 git_error *error = GIT_GLOBAL->last_error;
142 git_buf *error_buf = &GIT_GLOBAL->error_buf;
143
144 memset(state, 0, sizeof(git_error_state));
145
146 if (!error_code)
147 return 0;
148
149 state->error_code = error_code;
150 state->oom = (error == &g_git_oom_error);
151
152 if (error) {
153 state->error_msg.klass = error->klass;
154
155 if (state->oom)
156 state->error_msg.message = g_git_oom_error.message;
157 else
158 state->error_msg.message = git_buf_detach(error_buf);
159 }
160
161 giterr_clear();
162 return error_code;
163 }
164
165 int giterr_state_restore(git_error_state *state)
166 {
167 int ret = 0;
168
169 giterr_clear();
170
171 if (state && state->error_msg.message) {
172 if (state->oom)
173 giterr_set_oom();
174 else
175 set_error(state->error_msg.klass, state->error_msg.message);
176
177 ret = state->error_code;
178 memset(state, 0, sizeof(git_error_state));
179 }
180
181 return ret;
182 }
183
184 void giterr_state_free(git_error_state *state)
185 {
186 if (!state)
187 return;
188
189 if (!state->oom)
190 git__free(state->error_msg.message);
191
192 memset(state, 0, sizeof(git_error_state));
193 }
194
195 int giterr_system_last(void)
196 {
197 #ifdef GIT_WIN32
198 return GetLastError();
199 #else
200 return errno;
201 #endif
202 }
203
204 void giterr_system_set(int code)
205 {
206 #ifdef GIT_WIN32
207 SetLastError(code);
208 #else
209 errno = code;
210 #endif
211 }