refactor(tree,utilities)!: moved find_root and walk to the utilities and removed the Tree struct in favor or the FileInfoBuffer

This commit is contained in:
lisk77 2025-08-27 02:03:05 +02:00
parent 8efadf051c
commit 326a33a3f4
4 changed files with 149 additions and 157 deletions

View file

@ -43,6 +43,153 @@ PathType get_path_type(const char* path) {
return PT_OTHER;
}
// A function that returns the system path of the where the closest merk
// directory to the current working directory is located up in direction to
// the filesystem root
// Mutates relative in place to get the correct amount of ../ in relation to
// the directory which the software was called in
char* find_root(char* relative) {
char* current_dir = calloc(PATH_MAX, sizeof(char));
if (!current_dir) {
perror("ERROR: calloc in find_root failed!");
return NULL;
}
if (!getcwd(current_dir, PATH_MAX)) {
perror("ERROR: getcwd in find_root failed!");
free(current_dir);
return NULL;
}
char* search_dir = strdup(current_dir);
if (!search_dir) {
perror("ERROR: strdup in find_root failed!");
free(current_dir);
return NULL;
}
while (1) {
size_t dir_len = strlen(search_dir);
size_t merk_path_len = dir_len + strlen("/.merk") + 1;
char* merk_path = calloc(merk_path_len, sizeof(char));
if (!merk_path) {
perror("ERROR: calloc in find_root failed!");
free(current_dir);
free(search_dir);
return NULL;
}
snprintf(merk_path, merk_path_len, "%s/.merk", search_dir);
struct stat st;
if (stat(merk_path, &st) == 0 && S_ISDIR(st.st_mode)) {
free(current_dir);
free(merk_path);
char* result = strdup(search_dir);
free(search_dir);
return result;
}
free(merk_path);
if (strcmp(search_dir, "/") == 0) {
break;
}
char temp[PATH_MAX];
snprintf(temp, sizeof(temp), "../%s", relative);
strcpy(relative, temp);
char* parent = strrchr(search_dir, '/');
if (parent == search_dir) {
search_dir[1] = '\0';
} else if (parent) {
*parent = '\0';
} else {
break;
}
}
free(current_dir);
free(search_dir);
printf("ERROR: you are in no merk repository!\nCreate a new repository with merk init\n");
return NULL;
}
void walk(char* base, char* base_rel, char* rel, PathBuffer* paths, int full_repo_path, char* repo_root_path) {
DIR* dir = opendir(base);
if (!dir) {
return;
}
struct dirent* de;
while ((de = readdir(dir)) != NULL) {
if (is_dot_or_dotdot(de->d_name)) continue;
if (strcmp(de->d_name, ".merk") == 0) continue;
char* child_full = join_path(base, de->d_name);
if (!child_full) {
perror("ERROR: memory allocation failed in walk!");
closedir(dir);
exit(1);
}
struct stat st;
if (lstat(child_full, &st) != 0) {
free(child_full);
continue;
}
if (S_ISDIR(st.st_mode)) {
char* new_rel;
if (rel && rel[0]) {
new_rel = join_path(rel, de->d_name);
} else {
new_rel = strdup(de->d_name);
}
if (!new_rel) {
perror("ERROR: memory allocation failed in walk!");
free(child_full);
closedir(dir);
exit(1);
}
walk(child_full, base_rel, new_rel, paths, full_repo_path, repo_root_path);
free(new_rel);
} else {
char* relative_path;
if (rel && rel[0]) {
relative_path = join_path(rel, de->d_name);
} else {
relative_path = strdup(de->d_name);
}
if (!relative_path) {
perror("ERROR: memory allocation failed in walk!");
free(child_full);
closedir(dir);
exit(1);
}
if (!full_repo_path) {
normalize_path(relative_path, base_rel);
path_buffer_push(paths, relative_path);
free(relative_path);
}
else {
char* real_path = realpath(relative_path, NULL);
cut_path(repo_root_path, real_path);
path_buffer_push(paths, real_path);
free(relative_path);
}
}
free(child_full);
}
closedir(dir);
}
void visualize_diff(File* old_version, File* new_version, ActionList* actions) {
int* deleted_lines = calloc(old_version->lines, sizeof(int));
int* inserted_lines = calloc(new_version->lines, sizeof(int));