Diff between commits
This commit is contained in:
125
src/commit.c
125
src/commit.c
@@ -1,6 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "commit.h"
|
||||
#include "fs.h"
|
||||
@@ -145,4 +147,127 @@ int commit()
|
||||
|
||||
memset(&index, 0, sizeof(struct tree));
|
||||
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);
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
#ifndef COMMIT_H
|
||||
#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();
|
||||
|
||||
#endif // COMMIT_H
|
||||
55
src/fs.c
55
src/fs.c
@@ -193,6 +193,59 @@ defer:
|
||||
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)
|
||||
{
|
||||
struct object object;
|
||||
@@ -241,7 +294,7 @@ int save_index(struct tree *tree)
|
||||
return REPO_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
FILE *index_file = fopen(INDEX_FILE"_cpy", "w");
|
||||
FILE *index_file = fopen(INDEX_FILE, "w");
|
||||
if(index_exist == NULL)
|
||||
{
|
||||
return FS_ERROR;
|
||||
|
||||
5
src/fs.h
5
src/fs.h
@@ -9,6 +9,9 @@
|
||||
#define REFS_DIR LOCAL_REPO"/refs"
|
||||
#define HEADS_DIR REFS_DIR"/heads"
|
||||
#define HEAD_FILE LOCAL_REPO"/HEAD"
|
||||
|
||||
#define TMP "/tmp"
|
||||
|
||||
#define DEFAULT_DIR_MODE 0755
|
||||
#define DEFAULT_FILE_MODE 0444
|
||||
|
||||
@@ -34,5 +37,7 @@ int load_index(struct tree *index);
|
||||
int load_tree(char* checksum, struct tree *tree);
|
||||
int update_head(char *new_head);
|
||||
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
|
||||
|
||||
34
src/main.c
34
src/main.c
@@ -5,12 +5,42 @@
|
||||
// pull/push
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "includes.h"
|
||||
#include "objects.h"
|
||||
#include "types.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;
|
||||
}
|
||||
@@ -17,6 +17,11 @@ char *object_type_str[3] = {
|
||||
"commit",
|
||||
};
|
||||
|
||||
char* object_type_to_str(enum object_type type)
|
||||
{
|
||||
return object_type_str[type];
|
||||
}
|
||||
|
||||
enum object_type str_to_object_type(char* str)
|
||||
{
|
||||
if(strncmp("tree", str, 4) == 0)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#define HEADER_MAX_SIZE 20
|
||||
|
||||
char* object_type_to_str(enum object_type type);
|
||||
enum object_type str_to_object_type(char* str);
|
||||
size_t object_size(struct object *obj);
|
||||
int full_object(struct object *obj, char* buffer, size_t buffer_size);
|
||||
|
||||
21
src/tree.c
21
src/tree.c
@@ -55,6 +55,7 @@ void get_tree(char* content, struct tree *tree)
|
||||
|
||||
for(int i = 0; i < tree->entries_size; i++)
|
||||
{
|
||||
struct entry *entry = calloc(1, sizeof(struct entry));
|
||||
current_line = strtok(NULL, "\n");
|
||||
int j = 0;
|
||||
while(current_line[j] != ' ')
|
||||
@@ -62,12 +63,19 @@ void get_tree(char* content, struct tree *tree)
|
||||
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* filename = calloc(strlen(current_line) - j, sizeof(char));
|
||||
strncat(checksum, 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->filename = filename;
|
||||
entry->next = NULL;
|
||||
@@ -98,6 +106,7 @@ int add_to_tree(struct tree *tree, struct object *object, char *filename)
|
||||
free_entry(entry);
|
||||
}
|
||||
|
||||
entry->type = object->object_type;
|
||||
entry->filename = calloc(sizeof(char), strlen(filename) + 1);
|
||||
strncat(entry->filename, filename, strlen(filename));
|
||||
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);
|
||||
|
||||
write_object(&object);
|
||||
free_object(&object);
|
||||
return FS_OK;
|
||||
}
|
||||
@@ -203,11 +212,12 @@ int tree_to_object(struct tree *tree, struct object *object)
|
||||
struct entry *current = tree->first_entry;
|
||||
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];
|
||||
object->size = object->size + entry_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);
|
||||
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 object result = {0};
|
||||
result.object_type = TREE;
|
||||
struct entry *top_folder = find_entry(tree, top_folder_name);
|
||||
if(top_folder != NULL)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ struct object
|
||||
struct entry {
|
||||
char *checksum;
|
||||
char *filename;
|
||||
enum object_type type;
|
||||
struct entry *previous;
|
||||
struct entry *next;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user