refactor(tree)!: changed the api of the PathBuffer and generalized it to a List of char*

This commit is contained in:
lisk77 2025-08-27 01:23:00 +02:00
parent 7113b53caa
commit 8efadf051c
2 changed files with 60 additions and 55 deletions

View file

@ -11,19 +11,26 @@
#include <zlib.h>
#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

View file

@ -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);