Skip to content

Commit

Permalink
error-handling: References
Browse files Browse the repository at this point in the history
Yes, this is error handling solely for `refs.c`, but some of the
abstractions leak all ofer the code base.
  • Loading branch information
vmg committed Mar 5, 2012
1 parent 45d387a commit 1a48112
Show file tree
Hide file tree
Showing 26 changed files with 590 additions and 664 deletions.
11 changes: 6 additions & 5 deletions include/git2/errors.h
Expand Up @@ -122,16 +122,17 @@ typedef struct {

typedef enum {
GITERR_NOMEMORY,
GITERR_OS,
GITERR_REFERENCE,
GITERR_ZLIB,

} git_error_class;

#define GITERR_CHECK_ALLOC(ptr, error) if (ptr == NULL) { giterr_set_oom(error); return -1 }
#define GITERR_CHECK_ALLOC(ptr) if (ptr == NULL) { return -1; }

GIT_EXTERN(void) giterr_set(git_error **error_out, int error_class, const char *string, ...);
GIT_EXTERN(void) giterr_set_oom(git_error **error);
GIT_EXTERN(void) giterr_free(git_error *error);
GIT_EXTERN(void) giterr_clear(git_error **error);
GIT_EXTERN(void) giterr_set_oom(void);
GIT_EXTERN(void) giterr_set(int error_class, const char *string, ...);
GIT_EXTERN(void) giterr_clear(void);

/**
* Return a detailed error string with the latest error
Expand Down
5 changes: 3 additions & 2 deletions src/attr_file.c
Expand Up @@ -250,11 +250,12 @@ int git_attr_path__init(
git_buf full_path = GIT_BUF_INIT;
int error = git_buf_joinpath(&full_path, base, path);
if (error == GIT_SUCCESS)
info->is_dir = (git_path_isdir(full_path.ptr) == GIT_SUCCESS);
info->is_dir = (int)git_path_isdir(full_path.ptr);

git_buf_free(&full_path);
return error;
}
info->is_dir = (git_path_isdir(path) == GIT_SUCCESS);
info->is_dir = (int)git_path_isdir(path);

return GIT_SUCCESS;
}
Expand Down
8 changes: 8 additions & 0 deletions src/cc-compat.h
Expand Up @@ -50,4 +50,12 @@
# pragma warning ( disable : 4127 )
#endif

#if defined (_MSC_VER)
typedef unsigned char bool;
# define true 1
# define false 0
#else
# include <stdbool.h>
#endif

#endif /* INCLUDE_compat_h__ */
54 changes: 17 additions & 37 deletions src/errors.c
Expand Up @@ -108,20 +108,24 @@ void git_clearerror(void)
* New error handling
********************************************/

void giterr_set(git_error **error_out, int error_class, const char *string, ...)
static git_error g_git_oom_error = {
"Out of memory",
GITERR_NOMEMORY
};

void giterr_set_oom(void)
{
GIT_GLOBAL->last_error = &g_git_oom_error;
}

void giterr_set(int error_class, const char *string, ...)
{
char error_str[1024];
va_list arglist;
git_error *error;

if (error_out == NULL)
return;

error = git__malloc(sizeof(git_error));
if (!error) {
giterr_set_oom(error_out);
return;
}
error = &GIT_GLOBAL->error_t;
free(error->message);

va_start(arglist, string);
p_vsnprintf(error_str, sizeof(error_str), string, arglist);
Expand All @@ -131,38 +135,14 @@ void giterr_set(git_error **error_out, int error_class, const char *string, ...)
error->klass = error_class;

if (error->message == NULL) {
free(error);
giterr_set_oom(error_out);
giterr_set_oom();
return;
}

*error_out = error;
}

static git_error g_git_oom_error = {
"Out of memory",
GITERR_NOMEMORY
};

void giterr_set_oom(git_error **error)
{
if (error != NULL)
*error = &g_git_oom_error;
}

void giterr_free(git_error *error)
{
if (error == NULL || error == &g_git_oom_error)
return;

free(error->message);
free(error);
GIT_GLOBAL->last_error = error;
}

void giterr_clear(git_error **error)
void giterr_clear(void)
{
if (error != NULL) {
giterr_free(*error);
*error = NULL;
}
GIT_GLOBAL->last_error = NULL;
}
75 changes: 32 additions & 43 deletions src/filebuf.c
Expand Up @@ -16,11 +16,14 @@ static const size_t WRITE_BUFFER_SIZE = (4096 * 2);

static int lock_file(git_filebuf *file, int flags)
{
if (git_path_exists(file->path_lock) == 0) {
if (git_path_exists(file->path_lock) == true) {
if (flags & GIT_FILEBUF_FORCE)
p_unlink(file->path_lock);
else
return git__throw(GIT_EOSERR, "Failed to lock file");
else {
giterr_set(GITERR_OS,
"Failed to lock file '%s' for writing", file->path_lock);
return -1;
}
}

/* create path to the file buffer is required */
Expand All @@ -32,16 +35,20 @@ static int lock_file(git_filebuf *file, int flags)
}

if (file->fd < 0)
return git__throw(GIT_EOSERR, "Failed to create lock");
return -1;

if ((flags & GIT_FILEBUF_APPEND) && git_path_exists(file->path_original) == 0) {
if ((flags & GIT_FILEBUF_APPEND) && git_path_exists(file->path_original) == true) {
git_file source;
char buffer[2048];
size_t read_bytes;

source = p_open(file->path_original, O_RDONLY);
if (source < 0)
return git__throw(GIT_EOSERR, "Failed to lock file. Could not open %s", file->path_original);
if (source < 0) {
giterr_set(GITERR_OS,
"Failed to open file '%s' for reading: %s",
file->path_original, strerror(errno));
return -1;
}

while ((read_bytes = p_read(source, buffer, 2048)) > 0) {
p_write(file->fd, buffer, read_bytes);
Expand All @@ -60,7 +67,7 @@ void git_filebuf_cleanup(git_filebuf *file)
if (file->fd >= 0)
p_close(file->fd);

if (file->fd >= 0 && file->path_lock && git_path_exists(file->path_lock) == GIT_SUCCESS)
if (file->fd >= 0 && file->path_lock && git_path_exists(file->path_lock) == true)
p_unlink(file->path_lock);

if (file->digest)
Expand Down Expand Up @@ -141,13 +148,13 @@ static int write_deflate(git_filebuf *file, void *source, size_t len)

int git_filebuf_open(git_filebuf *file, const char *path, int flags)
{
int error, compression;
int compression;
size_t path_len;

assert(file && path);

if (file->buffer)
return git__throw(GIT_EINVALIDARGS, "Tried to reopen an open filebuf");
/* opening an already open buffer is a programming error;
* assert that this never happens instead of returning
* an error code */
assert(file && path && file->buffer == NULL);

memset(file, 0x0, sizeof(git_filebuf));

Expand All @@ -157,17 +164,12 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags)

/* Allocate the main cache buffer */
file->buffer = git__malloc(file->buf_size);
if (file->buffer == NULL){
error = GIT_ENOMEM;
goto cleanup;
}
GITERR_CHECK_ALLOC(file->buffer);

/* If we are hashing on-write, allocate a new hash context */
if (flags & GIT_FILEBUF_HASH_CONTENTS) {
if ((file->digest = git_hash_new_ctx()) == NULL) {
error = GIT_ENOMEM;
goto cleanup;
}
file->digest = git_hash_new_ctx();
GITERR_CHECK_ALLOC(file->digest);
}

compression = flags >> GIT_FILEBUF_DEFLATE_SHIFT;
Expand All @@ -176,16 +178,13 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags)
if (compression != 0) {
/* Initialize the ZLib stream */
if (deflateInit(&file->zs, compression) != Z_OK) {
error = git__throw(GIT_EZLIB, "Failed to initialize zlib");
giterr_set(GITERR_ZLIB, "Failed to initialize zlib");
goto cleanup;
}

/* Allocate the Zlib cache buffer */
file->z_buf = git__malloc(file->buf_size);
if (file->z_buf == NULL){
error = GIT_ENOMEM;
goto cleanup;
}
GITERR_CHECK_ALLOC(file->z_buf);

/* Never flush */
file->flush_mode = Z_NO_FLUSH;
Expand All @@ -200,50 +199,40 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags)

/* Open the file as temporary for locking */
file->fd = git_futils_mktmp(&tmp_path, path);

if (file->fd < 0) {
git_buf_free(&tmp_path);
error = GIT_EOSERR;
goto cleanup;
}

/* No original path */
file->path_original = NULL;
file->path_lock = git_buf_detach(&tmp_path);

if (file->path_lock == NULL) {
error = GIT_ENOMEM;
goto cleanup;
}
GITERR_CHECK_ALLOC(file->path_lock);
} else {
path_len = strlen(path);

/* Save the original path of the file */
file->path_original = git__strdup(path);
if (file->path_original == NULL) {
error = GIT_ENOMEM;
goto cleanup;
}
GITERR_CHECK_ALLOC(file->path_original);

/* create the locking path by appending ".lock" to the original */
file->path_lock = git__malloc(path_len + GIT_FILELOCK_EXTLENGTH);
if (file->path_lock == NULL) {
error = GIT_ENOMEM;
goto cleanup;
}
GITERR_CHECK_ALLOC(file->path_lock);

memcpy(file->path_lock, file->path_original, path_len);
memcpy(file->path_lock + path_len, GIT_FILELOCK_EXTENSION, GIT_FILELOCK_EXTLENGTH);

/* open the file for locking */
if ((error = lock_file(file, flags)) < GIT_SUCCESS)
if (lock_file(file, flags) < 0)
goto cleanup;
}

return GIT_SUCCESS;
return 0;

cleanup:
git_filebuf_cleanup(file);
return git__rethrow(error, "Failed to open file buffer for '%s'", path);
return -1;
}

int git_filebuf_hash(git_oid *oid, git_filebuf *file)
Expand Down

0 comments on commit 1a48112

Please sign in to comment.