Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
cf716bee
Commit
cf716bee
authored
9 years ago
by
Carlos Martín Nieto
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3351 from ethomson/error_buf
Error handling: use buffers, improved OOM handling
parents
69adb781
ef4857c2
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
148 additions
and
71 deletions
+148
-71
include/git2/errors.h
+0
-12
src/clone.c
+2
-2
src/common.h
+8
-3
src/errors.c
+75
-40
src/global.c
+8
-6
src/global.h
+1
-0
src/index.c
+3
-3
src/iterator.c
+2
-2
tests/core/errors.c
+49
-3
No files found.
include/git2/errors.h
View file @
cf716bee
...
...
@@ -114,18 +114,6 @@ 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 into the given `git_error` struct
* and returns 0 if the copy was successful, leaving the error
* cleared as if `giterr_clear` had been called.
*
* If there was no existing error in the library, -1 will be returned
* and the contents of `cpy` will be left unmodified.
*/
GIT_EXTERN
(
int
)
giterr_detach
(
git_error
*
cpy
);
/**
* Set the error message string for this thread.
*
* This function is public so that custom ODB backends and the like can
...
...
This diff is collapsed.
Click to expand it.
src/clone.c
View file @
cf716bee
...
...
@@ -440,14 +440,14 @@ int git_clone(
if
(
error
!=
0
)
{
git_error_state
last_error
=
{
0
};
giterr_capture
(
&
last_error
,
error
);
giterr_
state_
capture
(
&
last_error
,
error
);
git_repository_free
(
repo
);
repo
=
NULL
;
(
void
)
git_futils_rmdir_r
(
local_path
,
NULL
,
rmdir_flags
);
giterr_restore
(
&
last_error
);
giterr_
state_
restore
(
&
last_error
);
}
*
out
=
repo
;
...
...
This diff is collapsed.
Click to expand it.
src/common.h
View file @
cf716bee
...
...
@@ -142,19 +142,24 @@ void giterr_system_set(int code);
*/
typedef
struct
{
int
error_code
;
unsigned
int
oom
:
1
;
git_error
error_msg
;
}
git_error_state
;
/**
* Capture current error state to restore later, returning error code.
* If `error_code` is zero, this does nothing and returns zero.
* If `error_code` is zero, this does not clear the current error state.
* You must either restore this error state, or free it.
*/
int
giterr
_capture
(
git_error_state
*
state
,
int
error_code
);
extern
int
giterr_state
_capture
(
git_error_state
*
state
,
int
error_code
);
/**
* Restore error state to a previous value, returning saved error code.
*/
int
giterr_restore
(
git_error_state
*
state
);
extern
int
giterr_state_restore
(
git_error_state
*
state
);
/** Free an error state. */
extern
void
giterr_state_free
(
git_error_state
*
state
);
/**
* Check a versioned structure for validity
...
...
This diff is collapsed.
Click to expand it.
src/errors.c
View file @
cf716bee
...
...
@@ -18,19 +18,30 @@ static git_error g_git_oom_error = {
GITERR_NOMEMORY
};
static
void
set_error
(
int
error_class
,
char
*
string
)
static
void
set_error
_from_buffer
(
int
error_class
)
{
git_error
*
error
=
&
GIT_GLOBAL
->
error_t
;
git_buf
*
buf
=
&
GIT_GLOBAL
->
error_buf
;
if
(
error
->
message
!=
string
)
git__free
(
error
->
message
);
error
->
message
=
string
;
error
->
message
=
buf
->
ptr
;
error
->
klass
=
error_class
;
GIT_GLOBAL
->
last_error
=
error
;
}
static
void
set_error
(
int
error_class
,
char
*
string
)
{
git_buf
*
buf
=
&
GIT_GLOBAL
->
error_buf
;
git_buf_clear
(
buf
);
if
(
string
)
{
git_buf_puts
(
buf
,
string
);
git__free
(
string
);
}
set_error_from_buffer
(
error_class
);
}
void
giterr_set_oom
(
void
)
{
GIT_GLOBAL
->
last_error
=
&
g_git_oom_error
;
...
...
@@ -38,27 +49,28 @@ void giterr_set_oom(void)
void
giterr_set
(
int
error_class
,
const
char
*
string
,
...)
{
git_buf
buf
=
GIT_BUF_INIT
;
va_list
arglist
;
#ifdef GIT_WIN32
DWORD
win32_error_code
=
(
error_class
==
GITERR_OS
)
?
GetLastError
()
:
0
;
#endif
int
error_code
=
(
error_class
==
GITERR_OS
)
?
errno
:
0
;
git_buf
*
buf
=
&
GIT_GLOBAL
->
error_buf
;
git_buf_clear
(
buf
);
if
(
string
)
{
va_start
(
arglist
,
string
);
git_buf_vprintf
(
&
buf
,
string
,
arglist
);
git_buf_vprintf
(
buf
,
string
,
arglist
);
va_end
(
arglist
);
if
(
error_class
==
GITERR_OS
)
git_buf_PUTS
(
&
buf
,
": "
);
git_buf_PUTS
(
buf
,
": "
);
}
if
(
error_class
==
GITERR_OS
)
{
#ifdef GIT_WIN32
char
*
win32_error
=
git_win32_get_error_message
(
win32_error_code
);
if
(
win32_error
)
{
git_buf_puts
(
&
buf
,
win32_error
);
git_buf_puts
(
buf
,
win32_error
);
git__free
(
win32_error
);
SetLastError
(
0
);
...
...
@@ -66,26 +78,29 @@ void giterr_set(int error_class, const char *string, ...)
else
#endif
if
(
error_code
)
git_buf_puts
(
&
buf
,
strerror
(
error_code
));
git_buf_puts
(
buf
,
strerror
(
error_code
));
if
(
error_code
)
errno
=
0
;
}
if
(
!
git_buf_oom
(
&
buf
))
set_error
(
error_class
,
git_buf_detach
(
&
buf
)
);
if
(
!
git_buf_oom
(
buf
))
set_error
_from_buffer
(
error_class
);
}
void
giterr_set_str
(
int
error_class
,
const
char
*
string
)
{
char
*
message
;
git_buf
*
buf
=
&
GIT_GLOBAL
->
error_buf
;
assert
(
string
);
message
=
git__strdup
(
string
);
if
(
!
string
)
return
;
if
(
message
)
set_error
(
error_class
,
message
);
git_buf_clear
(
buf
);
git_buf_puts
(
buf
,
string
);
if
(
!
git_buf_oom
(
buf
))
set_error_from_buffer
(
error_class
);
}
int
giterr_set_regex
(
const
regex_t
*
regex
,
int
error_code
)
...
...
@@ -116,45 +131,65 @@ void giterr_clear(void)
#endif
}
int
giterr_detach
(
git_error
*
cpy
)
const
git_error
*
giterr_last
(
void
)
{
return
GIT_GLOBAL
->
last_error
;
}
int
giterr_state_capture
(
git_error_state
*
state
,
int
error_code
)
{
git_error
*
error
=
GIT_GLOBAL
->
last_error
;
git_buf
*
error_buf
=
&
GIT_GLOBAL
->
error_buf
;
assert
(
cpy
);
memset
(
state
,
0
,
sizeof
(
git_error_state
)
);
if
(
!
error
)
return
-
1
;
if
(
!
error
_code
)
return
0
;
cpy
->
message
=
error
->
messag
e
;
cpy
->
klass
=
error
->
klass
;
state
->
error_code
=
error_cod
e
;
state
->
oom
=
(
error
==
&
g_git_oom_error
)
;
error
->
message
=
NULL
;
giterr_clear
()
;
if
(
error
)
{
state
->
error_msg
.
klass
=
error
->
klass
;
return
0
;
}
if
(
state
->
oom
)
state
->
error_msg
.
message
=
g_git_oom_error
.
message
;
else
state
->
error_msg
.
message
=
git_buf_detach
(
error_buf
);
}
const
git_error
*
giterr_last
(
void
)
{
return
GIT_GLOBAL
->
last_error
;
giterr_clear
();
return
error_code
;
}
int
giterr_
capture
(
git_error_state
*
state
,
int
error_cod
e
)
int
giterr_
state_restore
(
git_error_state
*
stat
e
)
{
state
->
error_code
=
error_code
;
if
(
error_code
)
giterr_detach
(
&
state
->
error_msg
);
return
error_code
;
int
ret
=
0
;
giterr_clear
();
if
(
state
&&
state
->
error_msg
.
message
)
{
if
(
state
->
oom
)
giterr_set_oom
();
else
set_error
(
state
->
error_msg
.
klass
,
state
->
error_msg
.
message
);
ret
=
state
->
error_code
;
memset
(
state
,
0
,
sizeof
(
git_error_state
));
}
return
ret
;
}
int
giterr_restor
e
(
git_error_state
*
state
)
void
giterr_state_fre
e
(
git_error_state
*
state
)
{
if
(
state
&&
state
->
error_code
&&
state
->
error_msg
.
message
)
set_error
(
state
->
error_msg
.
klass
,
state
->
error_msg
.
message
);
else
giterr_clear
();
if
(
!
state
)
return
;
if
(
!
state
->
oom
)
git__free
(
state
->
error_msg
.
message
);
return
state
?
state
->
error_code
:
0
;
memset
(
state
,
0
,
sizeof
(
git_error_state
))
;
}
int
giterr_system_last
(
void
)
...
...
This diff is collapsed.
Click to expand it.
src/global.c
View file @
cf716bee
...
...
@@ -279,18 +279,19 @@ int git_libgit2_shutdown(void)
git_global_st
*
git__global_state
(
void
)
{
void
*
ptr
;
git_global_st
*
ptr
;
assert
(
git_atomic_get
(
&
git__n_inits
)
>
0
);
if
((
ptr
=
TlsGetValue
(
_tls_index
))
!=
NULL
)
return
ptr
;
ptr
=
git__
malloc
(
sizeof
(
git_global_st
));
ptr
=
git__
calloc
(
1
,
sizeof
(
git_global_st
));
if
(
!
ptr
)
return
NULL
;
memset
(
ptr
,
0x0
,
sizeof
(
git_global_st
));
git_buf_init
(
&
ptr
->
error_buf
,
0
);
TlsSetValue
(
_tls_index
,
ptr
);
return
ptr
;
}
...
...
@@ -378,18 +379,18 @@ int git_libgit2_shutdown(void)
git_global_st
*
git__global_state
(
void
)
{
void
*
ptr
;
git_global_st
*
ptr
;
assert
(
git_atomic_get
(
&
git__n_inits
)
>
0
);
if
((
ptr
=
pthread_getspecific
(
_tls_key
))
!=
NULL
)
return
ptr
;
ptr
=
git__
malloc
(
sizeof
(
git_global_st
));
ptr
=
git__
calloc
(
1
,
sizeof
(
git_global_st
));
if
(
!
ptr
)
return
NULL
;
memset
(
ptr
,
0x0
,
sizeof
(
git_global_st
)
);
git_buf_init
(
&
ptr
->
error_buf
,
0
);
pthread_setspecific
(
_tls_key
,
ptr
);
return
ptr
;
}
...
...
@@ -407,6 +408,7 @@ int git_libgit2_init(void)
ssl_inited
=
1
;
}
git_buf_init
(
&
__state
.
error_buf
,
0
);
return
git_atomic_inc
(
&
git__n_inits
);
}
...
...
This diff is collapsed.
Click to expand it.
src/global.h
View file @
cf716bee
...
...
@@ -14,6 +14,7 @@
typedef
struct
{
git_error
*
last_error
;
git_error
error_t
;
git_buf
error_buf
;
char
oid_fmt
[
GIT_OID_HEXSZ
+
1
];
}
git_global_st
;
...
...
This diff is collapsed.
Click to expand it.
src/index.c
View file @
cf716bee
...
...
@@ -1286,13 +1286,13 @@ int git_index_add_bypath(git_index *index, const char *path)
git_submodule
*
sm
;
git_error_state
err
;
giterr_capture
(
&
err
,
ret
);
giterr_
state_
capture
(
&
err
,
ret
);
ret
=
git_submodule_lookup
(
&
sm
,
INDEX_OWNER
(
index
),
path
);
if
(
ret
==
GIT_ENOTFOUND
)
return
giterr_restore
(
&
err
);
return
giterr_
state_
restore
(
&
err
);
git
__free
(
err
.
error_msg
.
message
);
git
err_state_free
(
&
err
);
/*
* EEXISTS means that there is a repository at that path, but it's not known
...
...
This diff is collapsed.
Click to expand it.
src/iterator.c
View file @
cf716bee
...
...
@@ -1120,7 +1120,7 @@ static int fs_iterator__expand_dir(fs_iterator *fi)
if
(
error
<
0
)
{
git_error_state
last_error
=
{
0
};
giterr_capture
(
&
last_error
,
error
);
giterr_
state_
capture
(
&
last_error
,
error
);
/* these callbacks may clear the error message */
fs_iterator__free_frame
(
ff
);
...
...
@@ -1128,7 +1128,7 @@ static int fs_iterator__expand_dir(fs_iterator *fi)
/* next time return value we skipped to */
fi
->
base
.
flags
&=
~
GIT_ITERATOR_FIRST_ACCESS
;
return
giterr_restore
(
&
last_error
);
return
giterr_
state_
restore
(
&
last_error
);
}
if
(
ff
->
entries
.
length
==
0
)
{
...
...
This diff is collapsed.
Click to expand it.
tests/core/errors.c
View file @
cf716bee
...
...
@@ -93,23 +93,69 @@ void test_core_errors__restore(void)
giterr_clear
();
cl_assert
(
giterr_last
()
==
NULL
);
cl_assert_equal_i
(
0
,
giterr_capture
(
&
err_state
,
0
));
cl_assert_equal_i
(
0
,
giterr_
state_
capture
(
&
err_state
,
0
));
memset
(
&
err_state
,
0x0
,
sizeof
(
git_error_state
));
giterr_set
(
42
,
"Foo: %s"
,
"bar"
);
cl_assert_equal_i
(
-
1
,
giterr_capture
(
&
err_state
,
-
1
));
cl_assert_equal_i
(
-
1
,
giterr_
state_
capture
(
&
err_state
,
-
1
));
cl_assert
(
giterr_last
()
==
NULL
);
giterr_set
(
99
,
"Bar: %s"
,
"foo"
);
giterr_restore
(
&
err_state
);
giterr_
state_
restore
(
&
err_state
);
cl_assert_equal_i
(
42
,
giterr_last
()
->
klass
);
cl_assert_equal_s
(
"Foo: bar"
,
giterr_last
()
->
message
);
}
void
test_core_errors__free_state
(
void
)
{
git_error_state
err_state
=
{
0
};
giterr_clear
();
giterr_set
(
42
,
"Foo: %s"
,
"bar"
);
cl_assert_equal_i
(
-
1
,
giterr_state_capture
(
&
err_state
,
-
1
));
giterr_set
(
99
,
"Bar: %s"
,
"foo"
);
giterr_state_free
(
&
err_state
);
cl_assert_equal_i
(
99
,
giterr_last
()
->
klass
);
cl_assert_equal_s
(
"Bar: foo"
,
giterr_last
()
->
message
);
giterr_state_restore
(
&
err_state
);
cl_assert
(
giterr_last
()
==
NULL
);
}
void
test_core_errors__restore_oom
(
void
)
{
git_error_state
err_state
=
{
0
};
const
git_error
*
oom_error
=
NULL
;
giterr_clear
();
giterr_set_oom
();
/* internal fn */
oom_error
=
giterr_last
();
cl_assert
(
oom_error
);
cl_assert_equal_i
(
-
1
,
giterr_state_capture
(
&
err_state
,
-
1
));
cl_assert
(
giterr_last
()
==
NULL
);
cl_assert_equal_i
(
GITERR_NOMEMORY
,
err_state
.
error_msg
.
klass
);
cl_assert_equal_s
(
"Out of memory"
,
err_state
.
error_msg
.
message
);
giterr_state_restore
(
&
err_state
);
cl_assert
(
giterr_last
()
->
klass
==
GITERR_NOMEMORY
);
cl_assert_
(
giterr_last
()
==
oom_error
,
"static oom error not restored"
);
giterr_clear
();
}
static
int
test_arraysize_multiply
(
size_t
nelem
,
size_t
size
)
{
size_t
out
;
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment