Change how diff works

This commit is contained in:
Antonin Ruan
2024-06-03 13:45:02 +02:00
parent 346c6e28aa
commit bd48b08294
6 changed files with 100 additions and 115 deletions

9
.gitignore vendored
View File

@@ -1,5 +1,6 @@
sample/
.vscode/
.cgit/
build/
sample
.vscode
.cgit
build
*.out
.git

View File

@@ -149,109 +149,27 @@ int commit()
save_index(&index);
}
int diff_blob(char *filename, struct object *a, struct object *b)
void diff_commit_with_working_tree(struct commit *commit)
{
char a_path[7 + strlen(filename)], b_path[7 + strlen(filename)];
sprintf(a_path, "/tmp/a%s", filename);
sprintf(b_path, "/tmp/b%s", filename);
struct object obj = {0};
read_object(commit->tree, &obj);
tmp_dump(a, a_path);
tmp_dump(b, b_path);
struct tree commit_tree = {0};
get_tree(obj.content, &commit_tree);
char cmd[1000];
FILE *f;
rmdir(TMP"/a");
create_dir(TMP"/a");
snprintf(cmd, sizeof(cmd), "diff -u %s %s", a_path, b_path);
f = popen(cmd, "w");
pclose(f);
}
dump_tree(TMP"/a", &commit_tree);
int diff_tree(char *cwd, struct tree *tree_a, struct tree *tree_b)
{
struct entry *current_a = NULL, *current_b = NULL;
if (tree_a == NULL)
current_a = NULL;
else
current_a = tree_a->first_entry;
FILE *p = popen("diff -ruN --exclude-from=.gitignore "TMP"/a ./ > "LOCAL_REPO"/diff", "w");
pclose(p);
if (tree_b == NULL)
current_b = NULL;
else
current_b = tree_b->first_entry;
p = popen("cat "LOCAL_REPO"/diff", "w");
pclose(p);
while(current_a != NULL || current_b != NULL)
{
int res = 0;
if (current_a == NULL)
{
res = 1;
} else if (current_b == NULL)
{
res = -1;
} else {
res = strcmp(current_a->filename, current_b->filename);
}
size_t cwd_len = 0;
if (*cwd != '\0')
cwd_len = strlen(cwd);
size_t filename_size = cwd_len + 1;
char *filename = calloc(1, filename_size);
strncpy(filename, cwd, filename_size);
struct object a = {0}, b = {0};
enum object_type type;
if (res == 0)
{
read_object(current_a->checksum, &a);
read_object(current_b->checksum, &b);
if (current_a->type != current_b->type)
return WRONG_OBJECT_TYPE;
filename_size += strlen(current_a->filename) + 1;
filename = realloc(filename, filename_size);
strcat(filename, "/");
strncat(filename, current_a->filename, strlen(current_a->filename));
type = current_a->type;
current_a = current_a->next;
current_b = current_b->next;
} else if (res < 0)
{
read_object(current_a->checksum, &a);
filename_size += strlen(current_a->filename) + 1;
filename = realloc(filename, filename_size);
strcat(filename, "/");
strncat(filename, current_a->filename, strlen(current_a->filename));
type = current_a->type;
current_a = current_a->next;
} else
{
read_object(current_b->checksum, &b);
filename_size += strlen(current_b->filename) + 1;
filename = realloc(filename, filename_size);
strcat(filename, "/");
strncat(filename, current_b->filename, strlen(current_b->filename));
type = current_b->type;
current_b = current_b->next;
}
if (type == BLOB)
diff_blob(filename, &a, &b);
else if (type == TREE)
{
struct tree subtree_a = {0}, subtree_b = {0};
if (res <= 0)
get_tree(a.content, &subtree_a);
if (res >= 0)
get_tree(b.content, &subtree_b);
init_tmp_diff_dir(filename);
diff_tree(filename, &subtree_a, &subtree_b);
free_tree(&subtree_a);
free_tree(&subtree_b);
}
free(filename);
free_object(&a);
free_object(&b);
}
free_tree(&commit_tree);
free_object(&obj);
}
void diff_commit(struct commit *commit_a, struct commit *commit_b)
@@ -264,7 +182,17 @@ void diff_commit(struct commit *commit_a, struct commit *commit_b)
get_tree(tree_obj_a.content, &tree_a);
get_tree(tree_obj_b.content, &tree_b);
diff_tree("", &tree_a, &tree_b);
rmdir(TMP"/a");
rmdir(TMP"/b");
create_dir(TMP"/a");
create_dir(TMP"/b");
dump_tree(TMP"/a", &tree_a);
dump_tree(TMP"/b", &tree_b);
FILE *f = popen("diff -ruN "TMP"/a "TMP"/b ", "w");
pclose(f);
free_tree(&tree_a);
free_tree(&tree_b);

View File

@@ -6,6 +6,7 @@
int commit_from_object(struct commit *commit, struct object *object);
void free_commit(struct commit *commit);
void diff_commit(struct commit *commit_a, struct commit *commit_b);
void diff_commit_with_working_tree(struct commit *commit);
int commit();
#endif // COMMIT_H

View File

@@ -214,6 +214,15 @@ int create_dir(char *dir)
}
}
void remove_dir(char *dir)
{
char cmd[strlen(dir) + strlen("rm -rf ") + 1];
sprintf(cmd, "rm -rf %s", dir);
FILE *p = popen(cmd, "r");
pclose(p);
}
int init_tmp_diff_dir(char* dir)
{
int dirlen = 0;
@@ -247,6 +256,41 @@ int tmp_dump(struct object *obj, char* filename)
return FS_OK;
}
int dump_tree(char *cwd, struct tree *tree)
{
struct entry *current = tree->first_entry;
while(current != NULL)
{
size_t cwd_len = 0;
if (*cwd != '\0')
cwd_len = strlen(cwd);
size_t filename_size = cwd_len + 2 + strlen(current->filename);
char filename[filename_size];
sprintf(filename, "%s/%s", cwd, current->filename);
struct object obj = {0};
read_object(current->checksum, &obj);
if(current->type == BLOB)
{
tmp_dump(&obj, filename);
} else if (current->type == TREE) {
struct tree subtree = {0};
get_tree(obj.content, &subtree);
create_dir(filename);
dump_tree(filename, &subtree);
free_tree(&subtree);
}
free_object(&obj);
current = current->next;
}
return FS_OK;
}
int load_tree(char* checksum, struct tree *tree)
{
struct object object;
@@ -421,22 +465,20 @@ int new_branch(char* branch_name)
return FS_OK;
}
int restore_tree();
int revert(char* commit_checksum)
{
struct object commit_obj = {0};
read_object(commit_checksum, &commit_obj);
struct object obj = {0};
read_object(commit_checksum, &obj);
if(commit_obj.object_type != COMMIT)
if(obj.object_type != COMMIT)
return WRONG_OBJECT_TYPE;
struct commit commit = {0};
commit_from_object(&commit, &commit_obj);
commit_from_object(&commit, &obj);
diff_commit_with_working_tree(&commit);
free_commit(&commit);
free_object(&commit_obj);
free_object(&obj);
return FS_OK;
}

View File

@@ -42,4 +42,7 @@ int tmp_dump(struct object *obj, char* filename);
int init_tmp_diff_dir(char* dir);
int new_branch(char* branch_name);
int create_dir(char *dir);
int dump_tree(char *cwd, struct tree *tree);
#endif // FS_H

View File

@@ -17,20 +17,30 @@
int main(int argc, char** argv)
{
// debug_print("master: %i", branch_exist("master"));
// debug_print("main: %i", branch_exist("main"));
// struct tree index = {0};
// load_index(&index);
// add_to_index(&index, "src/commit.c");
// add_to_index(&index, "src/commit.h");
// add_to_index(&index, "src/fs.c");
// add_to_index(&index, "src/fs.h");
// save_index(&index);
// commit();
new_branch("new_feature");
struct object a = {0}, b = {0};
read_object("083fec39f677b81de863cb0b8575ac76e87b7bff", &a);
read_object("fb5d38457520619b6e2f3b162c2a21a22b531cb4", &b);
struct commit c_a, c_b;
commit_from_object(&c_a, &a);
commit_from_object(&c_b, &b);
diff_commit_with_working_tree(&c_b);
free_object(&a);
free_object(&b);
return 0;
}