feat(cli): added the diff command to display the difference of two files

This commit is contained in:
lisk77 2025-08-18 16:34:56 +02:00
parent 190aa7cc76
commit c8b4d93c89
2 changed files with 76 additions and 8 deletions

View file

@ -1,6 +1,9 @@
#ifndef UTILITIES_H #ifndef UTILITIES_H
#define UTILITIES_H #define UTILITIES_H
#include <sys/stat.h>
#include <errno.h>
#include "file.h" #include "file.h"
#include "action_list.h" #include "action_list.h"
@ -9,6 +12,25 @@
#define GREEN_BG "\033[42m" #define GREEN_BG "\033[42m"
#define BLACK_FG "\033[30m" #define BLACK_FG "\033[30m"
typedef enum {
PT_NOEXIST,
PT_FILE,
PT_DIR,
PT_OTHER,
PT_ERROR
} PathType;
PathType get_path_type(const char* path) {
struct stat st;
int rc = stat(path, &st);
if (rc != 0) {
return (errno == ENOENT) ? PT_NOEXIST : PT_ERROR;
}
if (S_ISREG(st.st_mode)) return PT_FILE;
if (S_ISDIR(st.st_mode)) return PT_DIR;
return PT_OTHER;
}
void visualize_diff(File* old_version, File* new_version, ActionList* actions) { void visualize_diff(File* old_version, File* new_version, ActionList* actions) {
int* deleted_lines = calloc(old_version->lines, sizeof(int)); int* deleted_lines = calloc(old_version->lines, sizeof(int));
int* inserted_lines = calloc(new_version->lines, sizeof(int)); int* inserted_lines = calloc(new_version->lines, sizeof(int));

View file

@ -1,16 +1,62 @@
#include "action_list.h" #include "action_list.h"
#include "file.h"
#include "myers.h"
#include "utilities.h"
// main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main() { static void usage(int exitcode) {
Action act1 = (Action){.type=INSERT, .line_original=0, .line_changed=1}; printf("usage: merk <command> [<args>]\n\n diff Displays the difference between the given two files\n");
Action act2 = (Action){.type=DELETE, .line_original=1, .line_changed=2}; exit(exitcode);
}
ActionList* list1 = new_list(); int main(int argc, char **argv) {
add_action(list1, act1); if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
usage(0);
}
ActionList* list2 = new_list(); const char* subcmd = argv[1];
add_action(list2, act2);
append_list(list1, list2); if (strcmp(subcmd, "diff") != 0) {
fprintf(stderr, "ERROR: Unknown subcommand: '%s'\n", subcmd);
usage(2);
}
if (strcmp(subcmd, "diff") == 0) {
if (argc != 4) {
printf("ERROR: too many/too little arguments given!\n");
printf("Usage: merk diff <PATH> <PATH>");
exit(1);
}
File* file1;
switch (get_path_type(argv[2])) {
case PT_FILE: file1 = new_file(argv[2]); break;
case PT_DIR: file1 = NULL; printf("ERROR: first path is a directory and no file!"); break;
case PT_NOEXIST: file1 = NULL; printf("ERROR: first path does not exist!"); break;
default: file1 = NULL; printf("ERROR: unknown first path!");
}
if (!file1) exit(1);
File* file2;
switch (get_path_type(argv[3])) {
case PT_FILE: file2 = new_file(argv[3]); break;
case PT_DIR: file2 = NULL; printf("ERROR: second path is a directory and no file!"); break;
case PT_NOEXIST: file2 = NULL; printf("ERROR: second path does not exist!"); break;
default: file2 = NULL; printf("ERROR: unknown second path!");
}
if (!file2) exit(1);
ActionList* actions = myers_diff(file1, file2, 0, 0);
if (!actions) printf("ERROR: something went wrong while taking the diff!");
else visualize_diff(file1, file2, actions);
}
else {
usage(1);
}
return 0; return 0;
} }