diff --git a/src/cache.c b/src/cache.c index fd42e2c5b..b0a093100 100644 --- a/src/cache.c +++ b/src/cache.c @@ -32,7 +32,7 @@ #define GIT_CACHE_OPENADR 3 -void git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr) +int git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr) { size_t i; @@ -52,6 +52,8 @@ void git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_p cache->free_obj = free_ptr; cache->nodes = git__malloc((size + 1) * sizeof(cache_node)); + if (cache->nodes == NULL) + return GIT_ENOMEM; for (i = 0; i < (size + 1); ++i) { git_mutex_init(&cache->nodes[i].lock); diff --git a/src/cache.h b/src/cache.h index 975aaff7e..2d9bb51eb 100644 --- a/src/cache.h +++ b/src/cache.h @@ -31,7 +31,7 @@ typedef struct { } git_cache; -void git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr); +int git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr); void git_cache_free(git_cache *cache); void *git_cache_try_store(git_cache *cache, void *entry); diff --git a/src/fileops.c b/src/fileops.c index 5dd4a3806..45dd8f444 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -10,7 +10,7 @@ int gitfo_mkdir_2file(const char *file_path) error = git__dirname_r(target_folder_path, sizeof(target_folder_path), file_path); if (error < GIT_SUCCESS) - return error; + return git__throw(GIT_EINVALIDPATH, "Failed to recursively build `%s` tree structure. Unable to parse parent folder name", file_path); /* Does the containing folder exist? */ if (gitfo_isdir(target_folder_path)) { @@ -19,7 +19,7 @@ int gitfo_mkdir_2file(const char *file_path) /* Let's create the tree structure */ error = gitfo_mkdir_recurs(target_folder_path, mode); if (error < GIT_SUCCESS) - return error; + return error; /* The callee already takes care of setting the correct error message. */ } return GIT_SUCCESS; @@ -164,19 +164,19 @@ int gitfo_read_file(gitfo_buf *obj, const char *path) if (((size = gitfo_size(fd)) < 0) || !git__is_sizet(size+1)) { gitfo_close(fd); - return GIT_ERROR; + return git__throw(GIT_ERROR, "Failed to read file `%s`. Either an error occured while calculating its size or the file is too large", path); } len = (size_t) size; if ((buff = git__malloc(len + 1)) == NULL) { gitfo_close(fd); - return GIT_ERROR; + return GIT_ENOMEM; } if (gitfo_read(fd, buff, len) < 0) { gitfo_close(fd); free(buff); - return GIT_ERROR; + return git__throw(GIT_ERROR, "Failed to read file `%s`", path); } buff[len] = '\0'; @@ -197,13 +197,15 @@ void gitfo_free_buf(gitfo_buf *obj) int gitfo_mv(const char *from, const char *to) { + int error; + #ifdef GIT_WIN32 /* * Win32 POSIX compilance my ass. If the destination * file exists, the `rename` call fails. This is as * close as it gets with the Win32 API. */ - return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR; + error = MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR; #else /* Don't even try this on Win32 */ if (!link(from, to)) { @@ -214,16 +216,21 @@ int gitfo_mv(const char *from, const char *to) if (!rename(from, to)) return GIT_SUCCESS; - return GIT_EOSERR; + error = GIT_EOSERR; #endif + + if (error < GIT_SUCCESS) + return git__throw(error, "Failed to move file from `%s`to `%s`", from, to); + + return GIT_SUCCESS; } int gitfo_mv_force(const char *from, const char *to) { if (gitfo_mkdir_2file(to) < GIT_SUCCESS) - return GIT_EOSERR; + return GIT_EOSERR; /* The callee already takes care of setting the correct error message. */ - return gitfo_mv(from, to); + return gitfo_mv(from, to); /* The callee already takes care of setting the correct error message. */ } int gitfo_map_ro(git_map *out, git_file fd, git_off_t begin, size_t len) @@ -338,7 +345,7 @@ int gitfo_dirent( struct dirent *de; if (!wd_len || path_sz < wd_len + 2) - return GIT_ERROR; + return git__throw(GIT_EINVALIDARGS, "Failed to process `%s` tree structure. Path is either empty or buffer size is too short", path); while (path[wd_len - 1] == '/') wd_len--; @@ -347,7 +354,7 @@ int gitfo_dirent( dir = opendir(path); if (!dir) - return GIT_EOSERR; + return git__throw(GIT_EOSERR, "Failed to process `%s` tree structure. An error occured while opening the directory", path); while ((de = readdir(dir)) != NULL) { size_t de_len; @@ -364,14 +371,14 @@ int gitfo_dirent( de_len = strlen(de->d_name); if (path_sz < wd_len + de_len + 1) { closedir(dir); - return GIT_ERROR; + return git__throw(GIT_ERROR, "Failed to process `%s` tree structure. Buffer size is too short", path); } strcpy(path + wd_len, de->d_name); result = fn(arg, path); if (result < GIT_SUCCESS) { closedir(dir); - return result; + return result; /* The callee is reponsible for setting the correct error message */ } if (result > 0) { closedir(dir); @@ -399,7 +406,7 @@ int retrieve_path_root_offset(const char *path) if (*(path + offset) == '/') return offset; - return GIT_ERROR; + return -1; /* Not a real error. Rather a signal than the path is not rooted */ } @@ -438,7 +445,11 @@ int gitfo_mkdir_recurs(const char *path, int mode) error = gitfo_mkdir(path, mode); free(path_copy); - return error; + + if (error < GIT_SUCCESS) + return git__throw(error, "Failed to recursively create `%s` tree structure", path); + + return GIT_SUCCESS; } static int retrieve_previous_path_component_start(const char *path) @@ -484,7 +495,7 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path) if (root_path_offset < 0) { error = gitfo_getcwd(buffer_out, size); if (error < GIT_SUCCESS) - return error; + return error; /* The callee already takes care of setting the correct error message. */ len = strlen(buffer_out); buffer_out += len; @@ -529,7 +540,7 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path) /* Are we escaping out of the root dir? */ if (len < 0) - return GIT_EINVALIDPATH; + return git__throw(GIT_EINVALIDPATH, "Failed to normalize path `%s`. The path escapes out of the root directory", path); buffer_out = (char *)buffer_out_start + len; continue; @@ -537,7 +548,7 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path) /* Guard against potential multiple dot path traversal (cf http://cwe.mitre.org/data/definitions/33.html) */ if (only_dots && segment_len > 0) - return GIT_EINVALIDPATH; + return git__throw(GIT_EINVALIDPATH, "Failed to normalize path `%s`. The path contains a segment with three `.` or more", path); *buffer_out++ = '/'; len++; @@ -557,21 +568,21 @@ int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path) /* Let's make sure the filename isn't empty nor a dot */ if (path_len == 0 || (path_len == 1 && *path == '.')) - return GIT_EINVALIDPATH; + return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path is either empty or equals `.`", path); /* Let's make sure the filename doesn't end with "/", "/." or "/.." */ for (i = 1; path_len > i && i < 4; i++) { if (!strncmp(path + path_len - i, pattern, i)) - return GIT_EINVALIDPATH; + return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path points to a folder", path); } error = gitfo_prettify_dir_path(buffer_out, size, path); if (error < GIT_SUCCESS) - return error; + return error; /* The callee already takes care of setting the correct error message. */ path_len = strlen(buffer_out); - if (path_len < 2) - return GIT_EINVALIDPATH; + if (path_len < 2) /* TODO: Fixme. We should also take of detecting Windows rooted path (probably through usage of retrieve_path_root_offset) */ + return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path points to a folder", path); /* Remove the trailing slash */ buffer_out[path_len - 1] = '\0'; @@ -616,11 +627,11 @@ int gitfo_getcwd(char *buffer_out, size_t size) #ifdef GIT_WIN32 cwd_buffer = _getcwd(buffer_out, size); #else - cwd_buffer = getcwd(buffer_out, size); //TODO: Fixme. Ensure the required headers are correctly included + cwd_buffer = getcwd(buffer_out, size); #endif if (cwd_buffer == NULL) - return GIT_EOSERR; + return git__throw(GIT_EOSERR, "Failed to retrieve current working directory"); posixify_path(buffer_out); diff --git a/src/odb.c b/src/odb.c index 3dca97764..8637534c1 100644 --- a/src/odb.c +++ b/src/odb.c @@ -234,13 +234,17 @@ static int backend_sort_cmp(const void *a, const void *b) int git_odb_new(git_odb **out) { + int error; + git_odb *db = git__calloc(1, sizeof(*db)); if (!db) return GIT_ENOMEM; git_cache_init(&db->cache, GIT_DEFAULT_CACHE_SIZE, &free_odb_object); + if (error < GIT_SUCCESS) + return error; - if (git_vector_init(&db->backends, 4, backend_sort_cmp) < 0) { + if (git_vector_init(&db->backends, 4, backend_sort_cmp) < GIT_SUCCESS) { free(db); return GIT_ENOMEM; } diff --git a/src/repository.c b/src/repository.c index 8cc2644ca..1072b22a1 100644 --- a/src/repository.c +++ b/src/repository.c @@ -124,16 +124,16 @@ static int check_repository_dirs(git_repository *repo) char path_aux[GIT_PATH_MAX]; if (gitfo_isdir(repo->path_repository) < GIT_SUCCESS) - return GIT_ENOTAREPO; + return git__throw(GIT_ENOTAREPO, "`%s` is not a folder", repo->path_repository); /* Ensure GIT_OBJECT_DIRECTORY exists */ if (gitfo_isdir(repo->path_odb) < GIT_SUCCESS) - return GIT_ENOTAREPO; + return git__throw(GIT_ENOTAREPO, "`%s` does not exist", repo->path_odb); /* Ensure HEAD file exists */ git__joinpath(path_aux, repo->path_repository, GIT_HEAD_FILE); if (gitfo_exists(path_aux) < 0) - return GIT_ENOTAREPO; + return git__throw(GIT_ENOTAREPO, "HEAD file is missing"); return GIT_SUCCESS; } @@ -145,12 +145,12 @@ static int guess_repository_dirs(git_repository *repo, const char *repository_pa /* Git directory name */ if (git__basename_r(buffer, sizeof(buffer), repository_path) < 0) - return GIT_EINVALIDPATH; + return git__throw(GIT_EINVALIDPATH, "Unable to parse folder name from `%s`", repository_path); if (strcmp(buffer, DOT_GIT) == 0) { /* Path to working dir */ if (git__dirname_r(buffer, sizeof(buffer), repository_path) < 0) - return GIT_EINVALIDPATH; + return git__throw(GIT_EINVALIDPATH, "Unable to parse parent folder name from `%s`", repository_path); path_work_tree = buffer; } @@ -159,13 +159,19 @@ static int guess_repository_dirs(git_repository *repo, const char *repository_pa static git_repository *repository_alloc() { + int error; + git_repository *repo = git__malloc(sizeof(git_repository)); if (!repo) return NULL; memset(repo, 0x0, sizeof(git_repository)); - git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free); + error = git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free); + if (error < GIT_SUCCESS) { + free(repo); + return NULL; + } if (git_repository__refcache_init(&repo->references) < GIT_SUCCESS) { free(repo); @@ -177,7 +183,7 @@ static git_repository *repository_alloc() static int init_odb(git_repository *repo) { - return git_odb_open(&repo->db, repo->path_odb); + return git_odb_open(&repo->db, repo->path_odb); /* TODO: Move odb.c to new error handling */ } int git_repository_open3(git_repository **repo_out, @@ -192,7 +198,7 @@ int git_repository_open3(git_repository **repo_out, assert(repo_out); if (object_database == NULL) - return GIT_ERROR; + return git__throw(GIT_EINVALIDARGS, "Failed to open repository. `object_database` can't be null"); repo = repository_alloc(); if (repo == NULL) @@ -218,7 +224,7 @@ int git_repository_open3(git_repository **repo_out, cleanup: git_repository_free(repo); - return error; + return git__rethrow(error, "Failed to open repository"); } @@ -259,7 +265,7 @@ int git_repository_open2(git_repository **repo_out, cleanup: git_repository_free(repo); - return error; + return git__rethrow(error, "Failed to open repository"); } int git_repository_open(git_repository **repo_out, const char *path) @@ -290,7 +296,7 @@ int git_repository_open(git_repository **repo_out, const char *path) cleanup: git_repository_free(repo); - return error; + return git__rethrow(error, "Failed to open repository"); } void git_repository_free(git_repository *repo) @@ -322,7 +328,7 @@ int git_repository_index(git_index **index_out, git_repository *repo) assert(index_out && repo); if (repo->index == NULL) { - error = git_index_open_inrepo(&repo->index, repo); + error = git_index_open_inrepo(&repo->index, repo); /* TODO: move index.c to new error handling */ if (error < GIT_SUCCESS) return error; @@ -349,7 +355,7 @@ static int repo_init_reinit(repo_init *results) static int repo_init_createhead(git_repository *repo) { git_reference *head_reference; - return git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE); + return git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE); /* TODO: finalize moving refs.c to new error handling */ } static int repo_init_check_head_existence(char * repository_path) @@ -363,6 +369,7 @@ static int repo_init_check_head_existence(char * repository_path) static int repo_init_structure(repo_init *results) { const int mode = 0755; /* or 0777 ? */ + int error; char temp_path[GIT_PATH_MAX]; char *git_dir = results->path_repository; @@ -372,23 +379,27 @@ static int repo_init_structure(repo_init *results) /* Creates the '/objects/info/' directory */ git__joinpath(temp_path, git_dir, GIT_OBJECTS_INFO_DIR); - if (gitfo_mkdir_recurs(temp_path, mode) < GIT_SUCCESS) - return GIT_ERROR; + error = gitfo_mkdir_recurs(temp_path, mode); + if (error < GIT_SUCCESS) + return error; /* Creates the '/objects/pack/' directory */ git__joinpath(temp_path, git_dir, GIT_OBJECTS_PACK_DIR); - if (gitfo_mkdir(temp_path, mode)) - return GIT_ERROR; + error = gitfo_mkdir(temp_path, mode); + if (error < GIT_SUCCESS) + return git__throw(error, "Unable to create `%s` folder", temp_path); /* Creates the '/refs/heads/' directory */ git__joinpath(temp_path, git_dir, GIT_REFS_HEADS_DIR); - if (gitfo_mkdir_recurs(temp_path, mode)) - return GIT_ERROR; + error = gitfo_mkdir_recurs(temp_path, mode); + if (error < GIT_SUCCESS) + return error; /* Creates the '/refs/tags/' directory */ git__joinpath(temp_path, git_dir, GIT_REFS_TAGS_DIR); - if (gitfo_mkdir(temp_path, mode)) - return GIT_ERROR; + error = gitfo_mkdir(temp_path, mode); + if (error < GIT_SUCCESS) + return git__throw(error, "Unable to create `%s` folder", temp_path); /* TODO: what's left? templates? */ @@ -467,7 +478,7 @@ int git_repository_init(git_repository **repo_out, const char *path, unsigned is cleanup: free(results.path_repository); git_repository_free(repo); - return error; + return git__rethrow(error, "Failed to (re)init the repository `%s`", path); } int git_repository_is_empty(git_repository *repo) @@ -477,10 +488,10 @@ int git_repository_is_empty(git_repository *repo) error = git_reference_lookup(&head, repo, "HEAD"); if (error < GIT_SUCCESS) - return error; + return git__throw(error, "Failed to determine the emptiness of the repository. An error occured while retrieving the HEAD reference"); if (git_reference_type(head) != GIT_REF_SYMBOLIC) - return GIT_EOBJCORRUPTED; + return git__throw(GIT_EOBJCORRUPTED, "Failed to determine the emptiness of the repository. HEAD is probably in detached state"); return git_reference_resolve(&branch, head) == GIT_SUCCESS ? 0 : 1; }