diff --git a/include/tree.h b/include/tree.h index 86adefc..278f0f4 100644 --- a/include/tree.h +++ b/include/tree.h @@ -11,19 +11,26 @@ #include #include "utilities.h" +#include "hash.h" +#include "file.h" + +typedef List PathBuffer; +typedef List Tree; +typedef List FileInfoBuffer; typedef struct { - char** paths; + char* dir; + FileInfoBuffer* files; size_t len; size_t capacity; -} PathBuffer; +} TreeEntry; -PathBuffer* new_path_buffer(); -void add_path(PathBuffer*, char*); -void sort_path_buffer(PathBuffer*); -void free_path_buffer(PathBuffer*); +PathBuffer* path_buffer_new(); +void path_buffer_push(PathBuffer*, char*); +void path_buffer_sort(PathBuffer*); +void path_buffer_free(PathBuffer*); char* find_root(char*); void walk(char*, char*, char*, PathBuffer*, int, char*); -void save_tree(const char*, PathBuffer*); +void save_tree(PathBuffer*); #endif // TREE_H diff --git a/src/tree.c b/src/tree.c index 44d589a..bfd4c9e 100644 --- a/src/tree.c +++ b/src/tree.c @@ -1,43 +1,16 @@ #include "tree.h" -PathBuffer* new_path_buffer() { - PathBuffer* buffer = calloc(1, sizeof(PathBuffer)); - if (!buffer) { - perror("ERROR: Failed to allocate PathBuffer"); - exit(1); - } - - buffer->capacity = 10; - buffer->len = 0; - - buffer->paths = calloc(buffer->capacity, sizeof(char*)); - if (!buffer->paths) { - perror("ERROR: Failed to allocate paths array"); - free(buffer); - exit(1); - } - - return buffer; +PathBuffer* path_buffer_new() { + return list_new(sizeof(char*)); } -void add_path(PathBuffer* buffer, char* path) { - if (buffer->len >= buffer->capacity) { - buffer->capacity *= 2; - char** new_paths = realloc(buffer->paths, buffer->capacity * sizeof(char*)); - if (!new_paths) { - perror("ERROR: PathBuffer realloc failed!"); - exit(1); - } - buffer->paths = new_paths; - } - +void path_buffer_push(PathBuffer* buffer, char* path) { char* path_copy = strdup(path); if (!path_copy) { - perror("ERROR: strdup failed in add_path!"); - exit(1); + perror("ERROR: strdup failed in add_path"); + return; } - - buffer->paths[buffer->len++] = path_copy; + list_push(buffer, &path_copy); } int compare_paths(const void* a, const void* b) { @@ -46,20 +19,20 @@ int compare_paths(const void* a, const void* b) { return strcmp(s1,s2); } -void sort_path_buffer(PathBuffer* buffer) { +void path_buffer_sort(PathBuffer* buffer) { if (!buffer || buffer->len <= 1) { return; } - qsort(buffer->paths, buffer->len, sizeof(char*), compare_paths); + qsort(buffer->items, buffer->len, sizeof(char*), compare_paths); } -void free_path_buffer(PathBuffer* buffer) { +void path_buffer_free(PathBuffer* buffer) { if (buffer) { for (size_t i = 0; i < buffer->len; i++) { - free(buffer->paths[i]); + free(buffer->items[i]); } - free(buffer->paths); + free(buffer->items); free(buffer); } } @@ -238,13 +211,13 @@ void walk(char* base, char* base_rel, char* rel, PathBuffer* paths, int full_rep if (!full_repo_path) { normalize_path(relative_path, base_rel); - add_path(paths, relative_path); + path_buffer_push(paths, relative_path); free(relative_path); } else { char* real_path = realpath(relative_path, NULL); cut_path(repo_root_path, real_path); - add_path(paths, real_path); + path_buffer_push(paths, real_path); free(relative_path); } } @@ -255,28 +228,53 @@ void walk(char* base, char* base_rel, char* rel, PathBuffer* paths, int full_rep closedir(dir); } -void save_tree(const char* path, PathBuffer* tree) { +void save_tree(PathBuffer* tree) { + PathBuffer* files = path_buffer_new(); + char relative[PATH_MAX] = ""; + char* root = find_root(relative); + if (!root) { + perror("ERROR: unable to find root directory of the repository!"); + path_buffer_free(files); + return; + } + + walk(root, relative, relative, files, 1, root); + path_buffer_sort(files); + char tmp[1024]; size_t offset = 0; - FILE* fp = fopen(path, "wb"); - if (!fp) { perror("ERROR: cannot open path in save_tree!\n"); return; } + offset += snprintf(tmp, sizeof(tmp), "%zu:", files->len); - offset += snprintf(tmp, sizeof(tmp), "%zu:", tree->len); - - for (size_t idx = 0; idx < tree->len; idx++) { + for (size_t idx = 0; idx < files->len; idx++) { size_t remaining = sizeof(tmp) - offset; - int written = snprintf(tmp + offset, remaining, "%s:", tree->paths[idx]); + int written = snprintf(tmp + offset, remaining, "%s:", files->items[idx]); if (written < 0 || (size_t)written >= remaining) { perror("ERROR: buffer overflow in save_tree!\n"); - fclose(fp); return; } offset += (size_t)written; } + char hash[41]; + object_hash(TreeObject, tmp, hash); + + printf("hash: %s\n", hash); + + char dir_path[PATH_MAX]; + char file_path[PATH_MAX]; + + snprintf(dir_path, sizeof(dir_path), "%s/.merk/objects/%.2s", root, hash); + mkdir(dir_path, 0755); + + snprintf(file_path, sizeof(file_path), "%s/%s", dir_path, hash+2); + + FILE* fp = fopen(file_path, "wb"); + if (!fp) { perror("ERROR: cannot open path in save_tree!\n"); return; } + + uLong originalLen = strlen(tmp) + 1; uLong compressedLen = compressBound(originalLen);