Diff between commits
This commit is contained in:
125
src/commit.c
125
src/commit.c
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
55
src/fs.c
55
src/fs.c
@@ -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;
|
||||||
|
|||||||
5
src/fs.h
5
src/fs.h
@@ -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
|
||||||
|
|||||||
34
src/main.c
34
src/main.c
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
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++)
|
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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user