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/ sample
.vscode/ .vscode
.cgit/ .cgit
build/ build
*.out *.out
.git

View File

@@ -149,109 +149,27 @@ int commit()
save_index(&index); 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)]; struct object obj = {0};
sprintf(a_path, "/tmp/a%s", filename); read_object(commit->tree, &obj);
sprintf(b_path, "/tmp/b%s", filename);
tmp_dump(a, a_path); struct tree commit_tree = {0};
tmp_dump(b, b_path); get_tree(obj.content, &commit_tree);
char cmd[1000]; rmdir(TMP"/a");
FILE *f; create_dir(TMP"/a");
snprintf(cmd, sizeof(cmd), "diff -u %s %s", a_path, b_path); dump_tree(TMP"/a", &commit_tree);
f = popen(cmd, "w");
pclose(f);
}
int diff_tree(char *cwd, struct tree *tree_a, struct tree *tree_b) FILE *p = popen("diff -ruN --exclude-from=.gitignore "TMP"/a ./ > "LOCAL_REPO"/diff", "w");
{ pclose(p);
struct entry *current_a = NULL, *current_b = NULL;
if (tree_a == NULL)
current_a = NULL;
else
current_a = tree_a->first_entry;
if (tree_b == NULL) p = popen("cat "LOCAL_REPO"/diff", "w");
current_b = NULL; pclose(p);
else
current_b = tree_b->first_entry;
while(current_a != NULL || current_b != NULL) free_tree(&commit_tree);
{ free_object(&obj);
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);
}
} }
void diff_commit(struct commit *commit_a, struct commit *commit_b) 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_a.content, &tree_a);
get_tree(tree_obj_b.content, &tree_b); 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_a);
free_tree(&tree_b); free_tree(&tree_b);

View File

@@ -6,6 +6,7 @@
int commit_from_object(struct commit *commit, struct object *object); int commit_from_object(struct commit *commit, struct object *object);
void free_commit(struct commit *commit); void free_commit(struct commit *commit);
void diff_commit(struct commit *commit_a, struct commit *commit_b); void diff_commit(struct commit *commit_a, struct commit *commit_b);
void diff_commit_with_working_tree(struct commit *commit);
int commit(); int commit();
#endif // COMMIT_H #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 init_tmp_diff_dir(char* dir)
{ {
int dirlen = 0; int dirlen = 0;
@@ -247,6 +256,41 @@ int tmp_dump(struct object *obj, char* filename)
return FS_OK; 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) int load_tree(char* checksum, struct tree *tree)
{ {
struct object object; struct object object;
@@ -421,22 +465,20 @@ int new_branch(char* branch_name)
return FS_OK; return FS_OK;
} }
int restore_tree();
int revert(char* commit_checksum) int revert(char* commit_checksum)
{ {
struct object commit_obj = {0}; struct object obj = {0};
read_object(commit_checksum, &commit_obj); read_object(commit_checksum, &obj);
if(commit_obj.object_type != COMMIT) if(obj.object_type != COMMIT)
return WRONG_OBJECT_TYPE; return WRONG_OBJECT_TYPE;
struct commit commit = {0}; 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_commit(&commit);
free_object(&commit_obj); free_object(&obj);
return FS_OK; 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 init_tmp_diff_dir(char* dir);
int new_branch(char* branch_name); int new_branch(char* branch_name);
int create_dir(char *dir);
int dump_tree(char *cwd, struct tree *tree);
#endif // FS_H #endif // FS_H

View File

@@ -17,20 +17,30 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
// debug_print("master: %i", branch_exist("master"));
// debug_print("main: %i", branch_exist("main"));
// struct tree index = {0}; // struct tree index = {0};
// load_index(&index); // load_index(&index);
// add_to_index(&index, "src/commit.c"); // add_to_index(&index, "src/commit.c");
// add_to_index(&index, "src/commit.h"); // add_to_index(&index, "src/commit.h");
// add_to_index(&index, "src/fs.c");
// add_to_index(&index, "src/fs.h");
// save_index(&index); // save_index(&index);
// commit(); // 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; return 0;
} }