]> git.proxmox.com Git - libgit2.git/blob - src/errors.c
Merge pull request #1920 from libgit2/cmn/ref-with-log
[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 #include <stdarg.h>
12
13 /********************************************
14 * New error handling
15 ********************************************/
16
17 static git_error g_git_oom_error = {
18 "Out of memory",
19 GITERR_NOMEMORY
20 };
21
22 static void set_error(int error_class, char *string)
23 {
24 git_error *error = &GIT_GLOBAL->error_t;
25
26 if (error->message != string)
27 git__free(error->message);
28
29 error->message = string;
30 error->klass = error_class;
31
32 GIT_GLOBAL->last_error = error;
33 }
34
35 void giterr_set_oom(void)
36 {
37 GIT_GLOBAL->last_error = &g_git_oom_error;
38 }
39
40 void giterr_set(int error_class, const char *string, ...)
41 {
42 git_buf buf = GIT_BUF_INIT;
43 va_list arglist;
44 #ifdef GIT_WIN32
45 DWORD win32_error_code = (error_class == GITERR_OS) ? GetLastError() : 0;
46 #endif
47 int error_code = (error_class == GITERR_OS) ? errno : 0;
48
49 va_start(arglist, string);
50 git_buf_vprintf(&buf, string, arglist);
51 va_end(arglist);
52
53 if (error_class == GITERR_OS) {
54 #ifdef GIT_WIN32
55 char * win32_error = git_win32_get_error_message(win32_error_code);
56 if (win32_error) {
57 git_buf_PUTS(&buf, ": ");
58 git_buf_puts(&buf, win32_error);
59 git__free(win32_error);
60
61 SetLastError(0);
62 }
63 else
64 #endif
65 if (error_code) {
66 git_buf_PUTS(&buf, ": ");
67 git_buf_puts(&buf, strerror(error_code));
68 }
69
70 if (error_code)
71 errno = 0;
72 }
73
74 if (!git_buf_oom(&buf))
75 set_error(error_class, git_buf_detach(&buf));
76 }
77
78 void giterr_set_str(int error_class, const char *string)
79 {
80 char *message;
81
82 assert(string);
83
84 message = git__strdup(string);
85
86 if (message)
87 set_error(error_class, message);
88 }
89
90 int giterr_set_regex(const regex_t *regex, int error_code)
91 {
92 char error_buf[1024];
93
94 assert(error_code);
95
96 regerror(error_code, regex, error_buf, sizeof(error_buf));
97 giterr_set_str(GITERR_REGEX, error_buf);
98
99 if (error_code == REG_NOMATCH)
100 return GIT_ENOTFOUND;
101
102 return GIT_EINVALIDSPEC;
103 }
104
105 void giterr_clear(void)
106 {
107 if (GIT_GLOBAL->last_error != NULL) {
108 set_error(0, NULL);
109 GIT_GLOBAL->last_error = NULL;
110 }
111
112 errno = 0;
113 #ifdef GIT_WIN32
114 SetLastError(0);
115 #endif
116 }
117
118 int giterr_detach(git_error *cpy)
119 {
120 git_error *error = GIT_GLOBAL->last_error;
121
122 assert(cpy);
123
124 if (!error)
125 return -1;
126
127 cpy->message = error->message;
128 cpy->klass = error->klass;
129
130 error->message = NULL;
131 giterr_clear();
132
133 return 0;
134 }
135
136 const git_error *giterr_last(void)
137 {
138 return GIT_GLOBAL->last_error;
139 }
140
141 int giterr_capture(git_error_state *state, int error_code)
142 {
143 state->error_code = error_code;
144 if (error_code)
145 giterr_detach(&state->error_msg);
146 return error_code;
147 }
148
149 int giterr_restore(git_error_state *state)
150 {
151 if (state && state->error_code && state->error_msg.message)
152 set_error(state->error_msg.klass, state->error_msg.message);
153 else
154 giterr_clear();
155
156 return state ? state->error_code : 0;
157 }
158
159 int giterr_system_last(void)
160 {
161 #ifdef GIT_WIN32
162 return GetLastError();
163 #else
164 return errno;
165 #endif
166 }
167
168 void giterr_system_set(int code)
169 {
170 #ifdef GIT_WIN32
171 SetLastError(code);
172 #else
173 errno = code;
174 #endif
175 }