Diff between commits

This commit is contained in:
womax
2024-05-30 17:12:29 +02:00
parent 0bdc0b150d
commit b23f9a02f1
9 changed files with 244 additions and 8 deletions

View File

@@ -1,6 +1,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "commit.h" #include "commit.h"
#include "fs.h" #include "fs.h"
@@ -145,4 +147,127 @@ int commit()
memset(&index, 0, sizeof(struct tree)); memset(&index, 0, sizeof(struct tree));
save_index(&index); save_index(&index);
}
int diff_blob(char *filename, struct object *a, struct object *b)
{
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);
tmp_dump(a, a_path);
tmp_dump(b, b_path);
char cmd[1000];
FILE *f;
snprintf(cmd, sizeof(cmd), "diff -u %s %s", a_path, b_path);
f = popen(cmd, "w");
pclose(f);
}
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;
if (tree_b == NULL)
current_b = NULL;
else
current_b = tree_b->first_entry;
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);
}
}
void diff_commit(struct commit *commit_a, struct commit *commit_b)
{
struct object tree_obj_a, tree_obj_b;
read_object(commit_a->tree, &tree_obj_a);
read_object(commit_b->tree, &tree_obj_b);
struct tree tree_a, tree_b;
get_tree(tree_obj_a.content, &tree_a);
get_tree(tree_obj_b.content, &tree_b);
diff_tree("", &tree_a, &tree_b);
free_tree(&tree_a);
free_tree(&tree_b);
free_object(&tree_obj_a);
free_object(&tree_obj_b);
} }

View File

@@ -1,6 +1,11 @@
#ifndef COMMIT_H #ifndef COMMIT_H
#define COMMIT_H 1 #define COMMIT_H 1
#include "types.h"
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);
int commit(); int commit();
#endif // COMMIT_H #endif // COMMIT_H

View File

@@ -193,6 +193,59 @@ defer:
return result; return result;
} }
int create_dir(char *dir)
{
struct stat buffer = {0};
int result = FS_OK;
if(stat(dir, &buffer) == 0)
{
if (!S_ISREG(buffer.st_mode))
{
result = remove(dir);
if (result != 0)
return FS_ERROR;
}
} else {
result = mkdir(dir, DEFAULT_DIR_MODE);
if (result != 0)
return FS_ERROR;
}
}
int init_tmp_diff_dir(char* dir)
{
int dirlen = 0;
if (*dir != '\0')
dirlen = strlen(dir);
char path_a[dirlen + 8], path_b[dirlen + 8];
sprintf(path_a, "/tmp/a/%s", dir);
sprintf(path_b, "/tmp/b/%s", dir);
if (create_dir(path_a) != FS_OK)
return FS_ERROR;
if (create_dir(path_b) != FS_OK)
return FS_ERROR;
return FS_OK;
}
int tmp_dump(struct object *obj, char* filename)
{
if (obj == NULL)
{
open(filename, O_CREAT, 0644);
return FS_OK;
}
FILE *file = fopen(filename, "w");
fwrite(obj->content, obj->size, 1, file);
fclose(file);
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;
@@ -241,7 +294,7 @@ int save_index(struct tree *tree)
return REPO_NOT_INITIALIZED; return REPO_NOT_INITIALIZED;
} }
FILE *index_file = fopen(INDEX_FILE"_cpy", "w"); FILE *index_file = fopen(INDEX_FILE, "w");
if(index_exist == NULL) if(index_exist == NULL)
{ {
return FS_ERROR; return FS_ERROR;

View File

@@ -9,6 +9,9 @@
#define REFS_DIR LOCAL_REPO"/refs" #define REFS_DIR LOCAL_REPO"/refs"
#define HEADS_DIR REFS_DIR"/heads" #define HEADS_DIR REFS_DIR"/heads"
#define HEAD_FILE LOCAL_REPO"/HEAD" #define HEAD_FILE LOCAL_REPO"/HEAD"
#define TMP "/tmp"
#define DEFAULT_DIR_MODE 0755 #define DEFAULT_DIR_MODE 0755
#define DEFAULT_FILE_MODE 0444 #define DEFAULT_FILE_MODE 0444
@@ -34,5 +37,7 @@ int load_index(struct tree *index);
int load_tree(char* checksum, struct tree *tree); int load_tree(char* checksum, struct tree *tree);
int update_head(char *new_head); int update_head(char *new_head);
int get_last_commit(struct object *commit); int get_last_commit(struct object *commit);
int tmp_dump(struct object *obj, char* filename);
int init_tmp_diff_dir(char* dir);
#endif // FS_H #endif // FS_H

View File

@@ -5,12 +5,42 @@
// pull/push // pull/push
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "includes.h"
#include "objects.h"
#include "types.h"
#include "fs.h" #include "fs.h"
#include "tree.h"
#include "commit.h"
int main(int argc, char** argv) { int main(int argc, char** argv)
{
struct object a = {0}, b = {0};
read_object("5568f9722af893d2e6214617eefb62f40c9f8c69", &a);
read_object("4640f65f9340784086a5ddee4e1a46cdc3274424", &b);
struct commit c_a = {0}, c_b = {0};
commit_from_object(&c_a, &a);
commit_from_object(&c_b, &b);
diff_commit(&c_a, &c_b);
free_commit(&c_a);
free_commit(&c_b);
free_object(&a);
free_object(&b);
// struct tree index = {0};
// load_index(&index);
// add_to_index(&index, "src/commit.c");
// add_to_index(&index, "src/commit.h");
// save_index(&index);
// commit();
return 0; return 0;
} }

View File

@@ -17,6 +17,11 @@ char *object_type_str[3] = {
"commit", "commit",
}; };
char* object_type_to_str(enum object_type type)
{
return object_type_str[type];
}
enum object_type str_to_object_type(char* str) enum object_type str_to_object_type(char* str)
{ {
if(strncmp("tree", str, 4) == 0) if(strncmp("tree", str, 4) == 0)

View File

@@ -8,6 +8,7 @@
#define HEADER_MAX_SIZE 20 #define HEADER_MAX_SIZE 20
char* object_type_to_str(enum object_type type);
enum object_type str_to_object_type(char* str); enum object_type str_to_object_type(char* str);
size_t object_size(struct object *obj); size_t object_size(struct object *obj);
int full_object(struct object *obj, char* buffer, size_t buffer_size); int full_object(struct object *obj, char* buffer, size_t buffer_size);

View File

@@ -55,6 +55,7 @@ void get_tree(char* content, struct tree *tree)
for(int i = 0; i < tree->entries_size; i++) for(int i = 0; i < tree->entries_size; i++)
{ {
struct entry *entry = calloc(1, sizeof(struct entry));
current_line = strtok(NULL, "\n"); current_line = strtok(NULL, "\n");
int j = 0; int j = 0;
while(current_line[j] != ' ') while(current_line[j] != ' ')
@@ -62,12 +63,19 @@ void get_tree(char* content, struct tree *tree)
j++; j++;
} }
current_line[j] = '\0';
entry->type = str_to_object_type(current_line);
current_line += j + 1;
j = 0;
while(current_line[j] != ' ')
{
j++;
}
char* checksum = calloc(j + 1, sizeof(char)); char* checksum = calloc(j + 1, sizeof(char));
char* filename = calloc(strlen(current_line) - j, sizeof(char)); char* filename = calloc(strlen(current_line) - j, sizeof(char));
strncat(checksum, current_line, j); strncat(checksum, current_line, j);
strncat(filename, current_line + j + 1, strlen(current_line) - j); strncat(filename, current_line + j + 1, strlen(current_line) - j);
struct entry *entry = calloc(1, sizeof(struct entry));
entry->checksum = checksum; entry->checksum = checksum;
entry->filename = filename; entry->filename = filename;
entry->next = NULL; entry->next = NULL;
@@ -98,6 +106,7 @@ int add_to_tree(struct tree *tree, struct object *object, char *filename)
free_entry(entry); free_entry(entry);
} }
entry->type = object->object_type;
entry->filename = calloc(sizeof(char), strlen(filename) + 1); entry->filename = calloc(sizeof(char), strlen(filename) + 1);
strncat(entry->filename, filename, strlen(filename)); strncat(entry->filename, filename, strlen(filename));
entry->checksum = calloc(sizeof(char), DIGEST_LENGTH * 2 + 1); entry->checksum = calloc(sizeof(char), DIGEST_LENGTH * 2 + 1);
@@ -153,7 +162,7 @@ int add_to_index(struct tree *index, char *filename)
} }
add_to_tree(index, &object, filename); add_to_tree(index, &object, filename);
write_object(&object);
free_object(&object); free_object(&object);
return FS_OK; return FS_OK;
} }
@@ -203,11 +212,12 @@ int tree_to_object(struct tree *tree, struct object *object)
struct entry *current = tree->first_entry; struct entry *current = tree->first_entry;
for(int i = 0; i < tree->entries_size; i++) for(int i = 0; i < tree->entries_size; i++)
{ {
size_t entry_size = DIGEST_LENGTH * 2 + 2 + strlen(current->filename); char *type = object_type_to_str(current->type);
size_t entry_size = strlen(type) + DIGEST_LENGTH * 2 + 3 + strlen(current->filename);
char tmp[entry_size + 1]; char tmp[entry_size + 1];
object->size = object->size + entry_size; object->size = object->size + entry_size;
object->content = realloc(object->content, object->size); object->content = realloc(object->content, object->size);
sprintf(tmp, "%s %s\n", current->checksum, current->filename); sprintf(tmp, "%s %s %s\n", type, current->checksum, current->filename);
strncat(object->content, tmp, entry_size); strncat(object->content, tmp, entry_size);
current = current->next; current = current->next;
} }
@@ -224,6 +234,7 @@ int add_object_to_tree(struct tree *tree, char* filename, struct object *source)
{ {
struct tree subtree = {0}; struct tree subtree = {0};
struct object result = {0}; struct object result = {0};
result.object_type = TREE;
struct entry *top_folder = find_entry(tree, top_folder_name); struct entry *top_folder = find_entry(tree, top_folder_name);
if(top_folder != NULL) if(top_folder != NULL)
{ {

View File

@@ -20,6 +20,7 @@ struct object
struct entry { struct entry {
char *checksum; char *checksum;
char *filename; char *filename;
enum object_type type;
struct entry *previous; struct entry *previous;
struct entry *next; struct entry *next;
}; };