merk/src/main.c

119 lines
3.7 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include "action_list.h"
#include "file.h"
#include "myers.h"
#include "utilities.h"
#include "tree.h"
static void usage(int exitcode) {
printf("usage: merk <command> [<args>]\n\n init Initializes a repository in the current directory\n diff Displays the difference between the given two files\n status Displays a list of modified and untracked files in the repository\n");
exit(exitcode);
}
int main(int argc, char **argv) {
if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
usage(0);
}
const char* subcmd = argv[1];
if (strcmp(subcmd, "diff") != 0 && strcmp(subcmd, "init") != 0 && strcmp(subcmd, "status") != 0) {
fprintf(stderr, "ERROR: Unknown subcommand: '%s'\n", subcmd);
usage(2);
}
// Initializes a merk repository in the current directory
if (strcmp(subcmd, "init") == 0) {
if (argc != 2) {
printf("ERROR: too many agruments given!\n");
printf("Usage: merk init");
exit(1);
}
if (mkdir(".merk", 0700) == 0) {
printf("Initialized merk repository\n");
}
if (errno == EEXIST) {
struct stat st;
if (stat(".merk", &st) == 0 && S_ISDIR(st.st_mode)) {
printf("This directory is already a merk repository\n");
return 0;
}
}
mkdir(".merk/files", 0700);
mkdir(".merk/trees", 0700);
mkdir(".merk/branches", 0700);
}
// Prints out a visual representation of the diff of the files provided
else if (strcmp(subcmd, "diff") == 0) {
if (argc != 4) {
printf("ERROR: too many/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);
}
// Gives a list of untracked files in the repo
else if (strcmp(subcmd, "status") == 0) {
if (argc != 2) {
printf("ERROR: too many arguments given!\n");
printf("Usage: merk status");
exit(1);
}
PathBuffer* files = new_path_buffer();
char relative[PATH_MAX] = "";
char* root = find_root(relative);
if (!root) {
free_path_buffer(files);
return 1;
}
walk(root, relative, relative, files);
printf("Untracked files:\n\n");
for (size_t i = 0; i < files->len; i++) {
printf("%s\n", files->paths[i]);
}
free_path_buffer(files);
free(root);
return 0;
}
else {
usage(1);
}
return 0;
}