Command line
This commit is contained in:
68
src/commit.c
68
src/commit.c
@@ -1,3 +1,4 @@
|
|||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -64,7 +65,10 @@ void free_commit(struct commit *commit)
|
|||||||
int commit()
|
int commit()
|
||||||
{
|
{
|
||||||
struct tree index = {0};
|
struct tree index = {0};
|
||||||
load_index(&index);
|
if (load_index(&index) == REPO_NOT_INITIALIZED)
|
||||||
|
{
|
||||||
|
return REPO_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
struct object last_commit = {0};
|
struct object last_commit = {0};
|
||||||
struct commit commit = {0};
|
struct commit commit = {0};
|
||||||
@@ -127,10 +131,6 @@ int commit()
|
|||||||
}
|
}
|
||||||
commit.tree = commit_tree_checksum;
|
commit.tree = commit_tree_checksum;
|
||||||
|
|
||||||
debug_print("Author: %s", commit.author);
|
|
||||||
debug_print("Parent: %s", commit.parent);
|
|
||||||
debug_print("Tree: %s", commit.tree);
|
|
||||||
|
|
||||||
struct object commit_obj = {0};
|
struct object commit_obj = {0};
|
||||||
commit_to_object(&commit, &commit_obj);
|
commit_to_object(&commit, &commit_obj);
|
||||||
write_object(&commit_obj);
|
write_object(&commit_obj);
|
||||||
@@ -149,10 +149,22 @@ int commit()
|
|||||||
save_index(&index);
|
save_index(&index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void diff_commit_with_working_tree(struct commit *commit, int for_print)
|
int diff_commit_with_working_tree(char *checksum, int for_print)
|
||||||
{
|
{
|
||||||
|
struct object commit_obj = {0};
|
||||||
|
if (read_object(checksum, &commit_obj) == OBJECT_DOES_NOT_EXIST)
|
||||||
|
{
|
||||||
|
return OBJECT_DOES_NOT_EXIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commit_obj.object_type != COMMIT)
|
||||||
|
return WRONG_OBJECT_TYPE;
|
||||||
|
|
||||||
|
struct commit commit = {0};
|
||||||
|
commit_from_object(&commit, &commit_obj);
|
||||||
|
|
||||||
struct object obj = {0};
|
struct object obj = {0};
|
||||||
read_object(commit->tree, &obj);
|
read_object(commit.tree, &obj);
|
||||||
|
|
||||||
struct tree commit_tree = {0};
|
struct tree commit_tree = {0};
|
||||||
get_tree(obj.content, &commit_tree);
|
get_tree(obj.content, &commit_tree);
|
||||||
@@ -177,18 +189,37 @@ void diff_commit_with_working_tree(struct commit *commit, int for_print)
|
|||||||
pclose(p);
|
pclose(p);
|
||||||
|
|
||||||
free_tree(&commit_tree);
|
free_tree(&commit_tree);
|
||||||
|
free_commit(&commit);
|
||||||
free_object(&obj);
|
free_object(&obj);
|
||||||
|
free_object(&commit_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void diff_commit(struct commit *commit_a, struct commit *commit_b, int for_print)
|
int diff_commit(char* checksum_a, char* checksum_b, int for_print)
|
||||||
{
|
{
|
||||||
struct object tree_obj_a, tree_obj_b;
|
struct object commit_a_obj = {0}, commit_b_obj = {0};
|
||||||
read_object(commit_a->tree, &tree_obj_a);
|
if (read_object(checksum_a, &commit_a_obj) == OBJECT_DOES_NOT_EXIST)
|
||||||
read_object(commit_b->tree, &tree_obj_b);
|
{
|
||||||
|
errno = 1;
|
||||||
|
return OBJECT_DOES_NOT_EXIST;
|
||||||
|
}
|
||||||
|
if (read_object(checksum_b, &commit_b_obj) == OBJECT_DOES_NOT_EXIST)
|
||||||
|
{
|
||||||
|
free_object(&commit_a_obj);
|
||||||
|
errno = 2;
|
||||||
|
return OBJECT_DOES_NOT_EXIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct commit commit_a, commit_b;
|
||||||
|
commit_from_object(&commit_a, &commit_a_obj);
|
||||||
|
commit_from_object(&commit_b, &commit_b_obj);
|
||||||
|
|
||||||
|
struct object tree_a_obj, tree_b_obj;
|
||||||
|
read_object(commit_a.tree, &tree_a_obj);
|
||||||
|
read_object(commit_b.tree, &tree_b_obj);
|
||||||
|
|
||||||
struct tree tree_a, tree_b;
|
struct tree tree_a, tree_b;
|
||||||
get_tree(tree_obj_a.content, &tree_a);
|
get_tree(tree_a_obj.content, &tree_a);
|
||||||
get_tree(tree_obj_b.content, &tree_b);
|
get_tree(tree_b_obj.content, &tree_b);
|
||||||
|
|
||||||
rmdir(TMP"/a");
|
rmdir(TMP"/a");
|
||||||
rmdir(TMP"/b");
|
rmdir(TMP"/b");
|
||||||
@@ -199,11 +230,16 @@ void diff_commit(struct commit *commit_a, struct commit *commit_b, int for_print
|
|||||||
dump_tree(TMP"/a", &tree_a);
|
dump_tree(TMP"/a", &tree_a);
|
||||||
dump_tree(TMP"/b", &tree_b);
|
dump_tree(TMP"/b", &tree_b);
|
||||||
|
|
||||||
FILE *f = popen("diff -ruN "TMP"/a "TMP"/b > "LOCAL_REPO"/last.diff", "w");
|
FILE *f = popen("diff -ruN "TMP"/a "TMP"/b --color=always> "LOCAL_REPO"/last.diff", "w");
|
||||||
pclose(f);
|
pclose(f);
|
||||||
|
|
||||||
free_tree(&tree_a);
|
free_tree(&tree_a);
|
||||||
free_tree(&tree_b);
|
free_tree(&tree_b);
|
||||||
free_object(&tree_obj_a);
|
free_commit(&commit_a);
|
||||||
free_object(&tree_obj_b);
|
free_commit(&commit_b);
|
||||||
|
free_object(&tree_a_obj);
|
||||||
|
free_object(&tree_b_obj);
|
||||||
|
free_object(&commit_a_obj);
|
||||||
|
free_object(&commit_b_obj);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
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, int for_print);
|
int diff_commit(char* checksum_a, char* checksum_b, int for_print);
|
||||||
void diff_commit_with_working_tree(struct commit *commit, int for_print);
|
int diff_commit_with_working_tree(char *checksum, int for_print);
|
||||||
int commit();
|
int commit();
|
||||||
|
|
||||||
#endif // COMMIT_H
|
#endif // COMMIT_H
|
||||||
207
src/fs.c
207
src/fs.c
@@ -194,6 +194,20 @@ defer:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int remove_object(char *checksum)
|
||||||
|
{
|
||||||
|
if(!local_repo_exist())
|
||||||
|
{
|
||||||
|
return REPO_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
int result = FS_OK;
|
||||||
|
|
||||||
|
char path[strlen(OBJECTS_DIR) + strlen(checksum) + 2];
|
||||||
|
sprintf(path, "%s/%s", OBJECTS_DIR, checksum);
|
||||||
|
|
||||||
|
remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
int create_dir(char *dir)
|
int create_dir(char *dir)
|
||||||
{
|
{
|
||||||
struct stat buffer = {0};
|
struct stat buffer = {0};
|
||||||
@@ -361,7 +375,7 @@ int get_head_commit_checksum(char* checksum)
|
|||||||
return REPO_NOT_INITIALIZED;
|
return REPO_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(head_size == 0) return 0;
|
if(head_size == 0) return NO_CURRENT_HEAD;
|
||||||
|
|
||||||
FILE *head_file = NULL;
|
FILE *head_file = NULL;
|
||||||
head_file = fopen(HEAD_FILE, "r");
|
head_file = fopen(HEAD_FILE, "r");
|
||||||
@@ -383,7 +397,8 @@ int get_head_commit_checksum(char* checksum)
|
|||||||
int get_last_commit(struct object *commit)
|
int get_last_commit(struct object *commit)
|
||||||
{
|
{
|
||||||
char commit_checksum[DIGEST_LENGTH * 2 + 1];
|
char commit_checksum[DIGEST_LENGTH * 2 + 1];
|
||||||
get_head_commit_checksum(commit_checksum);
|
if (get_head_commit_checksum(commit_checksum) == NO_CURRENT_HEAD)
|
||||||
|
return FS_OK;
|
||||||
|
|
||||||
int res = read_object(commit_checksum, commit);
|
int res = read_object(commit_checksum, commit);
|
||||||
if (res != 0) return FS_ERROR;
|
if (res != 0) return FS_ERROR;
|
||||||
@@ -465,24 +480,15 @@ int new_branch(char* branch_name)
|
|||||||
return FS_OK;
|
return FS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int revert_to(char* commit_checksum)
|
int reset_to(char* commit_checksum)
|
||||||
{
|
{
|
||||||
struct object obj = {0};
|
int res = diff_commit_with_working_tree(commit_checksum, 0);
|
||||||
read_object(commit_checksum, &obj);
|
if(res != FS_OK)
|
||||||
|
return res;
|
||||||
if(obj.object_type != COMMIT)
|
|
||||||
return WRONG_OBJECT_TYPE;
|
|
||||||
|
|
||||||
struct commit commit = {0};
|
|
||||||
commit_from_object(&commit, &obj);
|
|
||||||
|
|
||||||
diff_commit_with_working_tree(&commit, 0);
|
|
||||||
|
|
||||||
FILE *p = popen("patch -p0 -R < "LOCAL_REPO"/last.diff > /dev/null", "w");
|
FILE *p = popen("patch -p0 -R < "LOCAL_REPO"/last.diff > /dev/null", "w");
|
||||||
pclose(p);
|
pclose(p);
|
||||||
|
|
||||||
free_commit(&commit);
|
|
||||||
free_object(&obj);
|
|
||||||
return FS_OK;
|
return FS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,15 +507,178 @@ int checkout_branch(char *branch)
|
|||||||
fread(commit_checksum, DIGEST_LENGTH * 2 + 1, 1, branch_head);
|
fread(commit_checksum, DIGEST_LENGTH * 2 + 1, 1, branch_head);
|
||||||
fclose(branch_head);
|
fclose(branch_head);
|
||||||
|
|
||||||
revert_to(commit_checksum);
|
reset_to(commit_checksum);
|
||||||
|
|
||||||
FILE *head_file = fopen(HEAD_FILE, "w");
|
FILE *head_file = fopen(HEAD_FILE, "w");
|
||||||
fwrite(branch_path, DIGEST_LENGTH * 2 + 1, 1, head_file);
|
fwrite(branch_path, DIGEST_LENGTH * 2 + 1, 1, head_file);
|
||||||
fclose(head_file);
|
fclose(head_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_diff()
|
int is_file_ignored(char *filename)
|
||||||
{
|
{
|
||||||
FILE *p = popen("cat "LOCAL_REPO"/last.diff | less -R", "w");
|
struct stat buffer = {0};
|
||||||
pclose(p);
|
if (stat(IGNORE_FILE, &buffer) != 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char content[buffer.st_size + 1];
|
||||||
|
memset(content, 0, buffer.st_size + 1);
|
||||||
|
FILE *ignore_file = fopen(IGNORE_FILE, "r");
|
||||||
|
fread(content, buffer.st_size, 1, ignore_file);
|
||||||
|
fclose(ignore_file);
|
||||||
|
|
||||||
|
char *current_line = strtok(content, "\n");
|
||||||
|
|
||||||
|
while(current_line != NULL)
|
||||||
|
{
|
||||||
|
if(strncmp(current_line, filename, strlen(current_line)) == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
char alt[strlen(current_line) + 3];
|
||||||
|
sprintf(alt, "./%s", current_line);
|
||||||
|
if(strncmp(alt, filename, strlen(alt)) == 0)
|
||||||
|
return 1;
|
||||||
|
current_line = strtok(NULL, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_file_to_index(struct tree *index, char *filename)
|
||||||
|
{
|
||||||
|
if (is_file_ignored(filename)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
struct stat st = {0};
|
||||||
|
if (stat(filename, &st) != 0)
|
||||||
|
{
|
||||||
|
return FILE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
if (!S_ISREG(st.st_mode))
|
||||||
|
{
|
||||||
|
DIR *dp;
|
||||||
|
struct dirent *ep;
|
||||||
|
dp = opendir(filename);
|
||||||
|
if (dp != NULL)
|
||||||
|
{
|
||||||
|
while ((ep = readdir(dp)) != NULL)
|
||||||
|
{
|
||||||
|
if (strcmp(ep->d_name, "..") != 0 && strcmp(ep->d_name, ".") != 0)
|
||||||
|
{
|
||||||
|
char path[strlen(ep->d_name) + strlen(filename) + 2];
|
||||||
|
if (strcmp(filename, "./") == 0)
|
||||||
|
sprintf(path, "%s", ep->d_name);
|
||||||
|
else if (strcmp(filename, ".") == 0)
|
||||||
|
sprintf(path, "%s", ep->d_name);
|
||||||
|
else if(filename[strlen(filename) - 1] == '/')
|
||||||
|
sprintf(path, "%s%s", filename, ep->d_name);
|
||||||
|
else
|
||||||
|
sprintf(path, "%s/%s", filename, ep->d_name);
|
||||||
|
add_file_to_index(index, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (add_to_index(index, filename) == FILE_NOT_FOUND)
|
||||||
|
return FILE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int remove_file_from_index(struct tree *index, char *filename)
|
||||||
|
{
|
||||||
|
if (is_file_ignored(filename))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct stat st = {0};
|
||||||
|
if (stat(filename, &st) != 0)
|
||||||
|
return FILE_NOT_FOUND;
|
||||||
|
if (!S_ISREG(st.st_mode))
|
||||||
|
{
|
||||||
|
DIR *dp;
|
||||||
|
struct dirent *ep;
|
||||||
|
dp = opendir(filename);
|
||||||
|
if (dp != NULL)
|
||||||
|
{
|
||||||
|
while ((ep = readdir(dp)) != NULL)
|
||||||
|
{
|
||||||
|
if (strcmp(ep->d_name, "..") != 0 && strcmp(ep->d_name, ".") != 0)
|
||||||
|
{
|
||||||
|
char path[strlen(ep->d_name) + strlen(filename) + 2];
|
||||||
|
if (strcmp(filename, "./") == 0)
|
||||||
|
sprintf(path, "%s", ep->d_name);
|
||||||
|
else if(filename[strlen(filename) - 1] == '/')
|
||||||
|
sprintf(path, "%s%s", filename, ep->d_name);
|
||||||
|
else
|
||||||
|
sprintf(path, "%s/%s", filename, ep->d_name);
|
||||||
|
remove_file_from_index(index, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
remove_from_index(index, filename, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dump_log()
|
||||||
|
{
|
||||||
|
struct object current_obj = {0};
|
||||||
|
get_last_commit(¤t_obj);
|
||||||
|
struct commit current = {0};
|
||||||
|
commit_from_object(¤t, ¤t_obj);
|
||||||
|
|
||||||
|
FILE *log_file = fopen(LOG_FILE, "w");
|
||||||
|
char checksum[DIGEST_LENGTH * 2 + 1];
|
||||||
|
hash_object(¤t_obj, checksum);
|
||||||
|
fprintf(log_file, "commit %s\n", checksum);
|
||||||
|
fprintf(log_file, "Author: %s\n", current.author);
|
||||||
|
fprintf(log_file, "Tree: %s\n", current.tree);
|
||||||
|
fprintf(log_file, "\n");
|
||||||
|
|
||||||
|
while (strcmp(current.parent, " ") != 0)
|
||||||
|
{
|
||||||
|
free_object(¤t_obj);
|
||||||
|
read_object(current.parent, ¤t_obj);
|
||||||
|
free_commit(¤t);
|
||||||
|
commit_from_object(¤t, ¤t_obj);
|
||||||
|
|
||||||
|
checksum[DIGEST_LENGTH * 2 + 1];
|
||||||
|
hash_object(¤t_obj, checksum);
|
||||||
|
fprintf(log_file, "commit %s\n", checksum);
|
||||||
|
fprintf(log_file, "Author: %s\n", current.author);
|
||||||
|
fprintf(log_file, "Tree: %s\n", current.tree);
|
||||||
|
fprintf(log_file, "\n");
|
||||||
|
}
|
||||||
|
fclose(log_file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dump_branches()
|
||||||
|
{
|
||||||
|
if(!heads_dir_exist())
|
||||||
|
{
|
||||||
|
return REPO_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
DIR *heads_dir = opendir(HEADS_DIR);
|
||||||
|
struct dirent *ep;
|
||||||
|
FILE *dump = fopen(TMP"/branches", "w");
|
||||||
|
if (heads_dir != NULL)
|
||||||
|
{
|
||||||
|
while ((ep = readdir(heads_dir)) != NULL)
|
||||||
|
{
|
||||||
|
if (strcmp(ep->d_name, "..") != 0 && strcmp(ep->d_name, ".") != 0)
|
||||||
|
fprintf(dump, "%s\n", ep->d_name);
|
||||||
|
}
|
||||||
|
fclose(dump);
|
||||||
|
closedir(heads_dir);
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
return FS_ERROR;
|
||||||
}
|
}
|
||||||
20
src/fs.h
20
src/fs.h
@@ -9,6 +9,8 @@
|
|||||||
#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 IGNORE_FILE ".gitignore"
|
||||||
|
#define LOG_FILE LOCAL_REPO"/log"
|
||||||
|
|
||||||
#define TMP "/tmp"
|
#define TMP "/tmp"
|
||||||
|
|
||||||
@@ -26,26 +28,40 @@
|
|||||||
#define BRANCH_DOES_NOT_EXIST (-24)
|
#define BRANCH_DOES_NOT_EXIST (-24)
|
||||||
#define FILE_NOT_FOUND (-30)
|
#define FILE_NOT_FOUND (-30)
|
||||||
#define ENTRY_NOT_FOUND (-31)
|
#define ENTRY_NOT_FOUND (-31)
|
||||||
|
#define NO_CURRENT_HEAD (-40)
|
||||||
|
|
||||||
int local_repo_exist();
|
int local_repo_exist();
|
||||||
int index_exist();
|
int index_exist();
|
||||||
|
|
||||||
int init_repo();
|
int init_repo();
|
||||||
|
|
||||||
int blob_from_file(char *filename, struct object *object);
|
int blob_from_file(char *filename, struct object *object);
|
||||||
|
|
||||||
int write_object(struct object *obj);
|
int write_object(struct object *obj);
|
||||||
int read_object(char *checksum, struct object *obj);
|
int read_object(char *checksum, struct object *obj);
|
||||||
|
int remove_object(char *checksum);
|
||||||
|
|
||||||
int save_index(struct tree *tree);
|
int save_index(struct tree *tree);
|
||||||
int load_index(struct tree *index);
|
int load_index(struct tree *index);
|
||||||
|
int add_file_to_index(struct tree *index, char *filename);
|
||||||
|
int remove_file_from_index(struct tree *index, char *filename);
|
||||||
|
|
||||||
int load_tree(char* checksum, struct tree *tree);
|
int load_tree(char* checksum, struct tree *tree);
|
||||||
|
|
||||||
int update_current_branch_head(char *new_head);
|
int update_current_branch_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 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);
|
||||||
void print_diff();
|
int checkout_branch(char *branch);
|
||||||
int revert_to(char* commit_checksum);
|
|
||||||
|
int reset_to(char* commit_checksum);
|
||||||
|
|
||||||
int create_dir(char *dir);
|
int create_dir(char *dir);
|
||||||
int dump_tree(char *cwd, struct tree *tree);
|
int dump_tree(char *cwd, struct tree *tree);
|
||||||
|
int dump_log();
|
||||||
|
int dump_branches();
|
||||||
|
|
||||||
#endif // FS_H
|
#endif // FS_H
|
||||||
|
|||||||
285
src/main.c
285
src/main.c
@@ -1,46 +1,267 @@
|
|||||||
// Requirements
|
#include <errno.h>
|
||||||
// commit
|
|
||||||
// branching
|
|
||||||
// revert
|
|
||||||
// pull/push
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
#include "objects.h"
|
#include "commit.h"
|
||||||
#include "types.h"
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
#include "commit.h"
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
#define ARGS_MAX_SIZE 256
|
||||||
|
|
||||||
|
int print_help()
|
||||||
{
|
{
|
||||||
// struct tree index = {0};
|
printf("Usage: cgit init\n");
|
||||||
// load_index(&index);
|
printf(" cgit add [FILES]\n");
|
||||||
|
printf(" cgit remove [FILES]\n");
|
||||||
|
printf(" cgit commit -m [MESSAGE]\n");
|
||||||
|
printf(" cgit diff <COMMIT1> [COMMIT2]\n");
|
||||||
|
printf(" cgit branch [BRANCH]\n");
|
||||||
|
printf(" cgit checkout [BRANCH]\n");
|
||||||
|
printf(" cgit reset <COMMIT>\n");
|
||||||
|
printf(" cgit log\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// add_to_index(&index, "src/commit.c");
|
int pop_arg(int *argc, char ***argv, char *buf)
|
||||||
// add_to_index(&index, "src/commit.h");
|
{
|
||||||
// add_to_index(&index, "src/fs.c");
|
if (*argc == 0)
|
||||||
// add_to_index(&index, "src/fs.h");
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// save_index(&index);
|
strcpy(buf, *argv[0]);
|
||||||
|
*argc -= 1;
|
||||||
// commit();
|
*argv += 1;
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int add(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char buf[ARGS_MAX_SIZE];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = pop_arg(&argc, &argv, buf);
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
printf("No file specified\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tree index = {0};
|
||||||
|
if (load_index(&index) == REPO_NOT_INITIALIZED)
|
||||||
|
{
|
||||||
|
printf("Not a cgit repository\n");
|
||||||
|
return 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (add_file_to_index(&index, buf) == FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
printf("File %s does not exist\n", buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
res = pop_arg(&argc, &argv, buf);
|
||||||
|
} while (res == 0);
|
||||||
|
|
||||||
|
save_index(&index);
|
||||||
|
free_tree(&index);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remove_cmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char buf[ARGS_MAX_SIZE];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = pop_arg(&argc, &argv, buf);
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
printf("No file specified\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tree index = {0};
|
||||||
|
if (load_index(&index) == REPO_NOT_INITIALIZED)
|
||||||
|
{
|
||||||
|
printf("Not a cgit repository\n");
|
||||||
|
return 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
remove_file_from_index(&index, buf);
|
||||||
|
res = pop_arg(&argc, &argv, buf);
|
||||||
|
} while (res == 0);
|
||||||
|
|
||||||
|
save_index(&index);
|
||||||
|
free_tree(&index);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int commit_cmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (commit() == REPO_NOT_INITIALIZED)
|
||||||
|
{
|
||||||
|
printf("Not a cgit repository\n");
|
||||||
|
return 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int diff(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char checksum_a[ARGS_MAX_SIZE];
|
||||||
|
char checksum_b[ARGS_MAX_SIZE];
|
||||||
|
|
||||||
|
if(pop_arg(&argc, &argv, checksum_a) == 1)
|
||||||
|
{
|
||||||
|
printf("No commit specified\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pop_arg(&argc, &argv, checksum_b) == 0)
|
||||||
|
{
|
||||||
|
if (diff_commit(checksum_a, checksum_b, 1) == OBJECT_DOES_NOT_EXIST)
|
||||||
|
{
|
||||||
|
if(errno == 1)
|
||||||
|
{
|
||||||
|
printf("Could not find commit %s\n", checksum_a);
|
||||||
|
} else if (errno == 2)
|
||||||
|
{
|
||||||
|
printf("Could not find commit %s\n", checksum_b);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (diff_commit_with_working_tree(checksum_a, 1) == OBJECT_DOES_NOT_EXIST)
|
||||||
|
{
|
||||||
|
printf("Could not find commit %s\n", checksum_a);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *p = popen("cat "LOCAL_REPO"/last.diff | less -R", "w");
|
||||||
|
pclose(p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkout(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char buf[ARGS_MAX_SIZE];
|
||||||
|
|
||||||
|
if(pop_arg(&argc, &argv, buf) == 1)
|
||||||
|
{
|
||||||
|
printf("No branch name specified\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkout_branch(buf) == BRANCH_DOES_NOT_EXIST)
|
||||||
|
{
|
||||||
|
printf("Branch %s does not exist, use cgit branch <name> to create one\n", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int reset(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char buf[ARGS_MAX_SIZE];
|
||||||
|
|
||||||
|
if(pop_arg(&argc, &argv, buf) == 1)
|
||||||
|
{
|
||||||
|
printf("You must give a commit to reset to\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res = reset_to(buf);
|
||||||
|
if (res == OBJECT_DOES_NOT_EXIST)
|
||||||
|
{
|
||||||
|
printf("There is no commit named %s\n", buf);
|
||||||
|
} else if (res == WRONG_OBJECT_TYPE)
|
||||||
|
{
|
||||||
|
printf("Object %s is not a commit and thus cannot be reset to\n", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int branch(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char buf[ARGS_MAX_SIZE];
|
||||||
|
|
||||||
|
if (pop_arg(&argc, &argv, buf) == 1)
|
||||||
|
{
|
||||||
|
if (dump_branches() == REPO_NOT_INITIALIZED)
|
||||||
|
{
|
||||||
|
printf("Not a cgit repository\n");
|
||||||
|
return 128;
|
||||||
|
}
|
||||||
|
FILE *p = popen("cat "TMP"/branches | less", "w");
|
||||||
|
pclose(p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_branch(buf) == BRANCH_ALREADY_EXIST)
|
||||||
|
{
|
||||||
|
printf("Branch %s already exist\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int log_cmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
dump_log();
|
||||||
|
FILE *p = popen("cat "LOG_FILE" | less", "w");
|
||||||
|
pclose(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char cmd[ARGS_MAX_SIZE];
|
||||||
|
char buf[ARGS_MAX_SIZE];
|
||||||
|
|
||||||
|
pop_arg(&argc, &argv, cmd);
|
||||||
|
if(pop_arg(&argc, &argv, buf) == 1)
|
||||||
|
{
|
||||||
|
print_help();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(buf, "init") == 0)
|
||||||
|
{
|
||||||
|
return init_repo();
|
||||||
|
} else if (strcmp(buf, "add") == 0)
|
||||||
|
{
|
||||||
|
return add(argc, argv);
|
||||||
|
} else if (strcmp(buf, "remove") == 0)
|
||||||
|
{
|
||||||
|
return remove_cmd(argc, argv);
|
||||||
|
} else if (strcmp(buf, "commit") == 0)
|
||||||
|
{
|
||||||
|
return commit_cmd(argc, argv);
|
||||||
|
} else if (strcmp(buf, "diff") == 0)
|
||||||
|
{
|
||||||
|
return diff(argc, argv);
|
||||||
|
} else if (strcmp(buf, "branch") == 0)
|
||||||
|
{
|
||||||
|
return branch(argc, argv);
|
||||||
|
} else if (strcmp(buf, "checkout") == 0)
|
||||||
|
{
|
||||||
|
return checkout(argc, argv);
|
||||||
|
} else if (strcmp(buf, "reset") == 0)
|
||||||
|
{
|
||||||
|
return reset(argc, argv);
|
||||||
|
} else if (strcmp(buf, "log") == 0)
|
||||||
|
{
|
||||||
|
return log_cmd(argc, argv);
|
||||||
|
} else if (strcmp(buf, "-h") == 0) {
|
||||||
|
return print_help();
|
||||||
|
} else {
|
||||||
|
printf("Unknown command %s, try using %s -h\n", buf, cmd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/tree.c
33
src/tree.c
@@ -155,25 +155,32 @@ int add_to_tree(struct tree *tree, struct object *object, char *filename)
|
|||||||
|
|
||||||
int add_to_index(struct tree *index, char *filename)
|
int add_to_index(struct tree *index, char *filename)
|
||||||
{
|
{
|
||||||
|
int result = FS_OK;
|
||||||
struct object object = {0};
|
struct object object = {0};
|
||||||
if (blob_from_file(filename, &object) != FS_OK)
|
if (blob_from_file(filename, &object) != FS_OK)
|
||||||
{
|
{
|
||||||
return FILE_NOT_FOUND;
|
return FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_to_tree(index, &object, filename);
|
result = write_object(&object);
|
||||||
write_object(&object);
|
if (result == FS_OK)
|
||||||
free_object(&object);
|
|
||||||
return FS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int remove_from_index(struct tree *index, char *filename)
|
|
||||||
{
|
|
||||||
if (!local_repo_exist() || !index_exist())
|
|
||||||
{
|
{
|
||||||
return REPO_NOT_INITIALIZED;
|
add_to_tree(index, &object, filename);
|
||||||
|
defer(FS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result == OBJECT_ALREADY_EXIST)
|
||||||
|
{
|
||||||
|
defer(FS_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
defer:
|
||||||
|
free_object(&object);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remove_from_index(struct tree *index, char *filename, int delete)
|
||||||
|
{
|
||||||
struct entry *entry = find_entry(index, filename);
|
struct entry *entry = find_entry(index, filename);
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
{
|
{
|
||||||
@@ -196,6 +203,8 @@ int remove_from_index(struct tree *index, char *filename)
|
|||||||
entry->next->previous = entry->previous;
|
entry->next->previous = entry->previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (delete)
|
||||||
|
remove_object(entry->checksum);
|
||||||
index->entries_size = index->entries_size - 1;
|
index->entries_size = index->entries_size - 1;
|
||||||
free_entry(entry);
|
free_entry(entry);
|
||||||
free(entry);
|
free(entry);
|
||||||
@@ -239,7 +248,7 @@ int add_object_to_tree(struct tree *tree, char* filename, struct object *source)
|
|||||||
if(top_folder != NULL)
|
if(top_folder != NULL)
|
||||||
{
|
{
|
||||||
load_tree(top_folder->checksum, &subtree);
|
load_tree(top_folder->checksum, &subtree);
|
||||||
remove_from_index(tree, top_folder->filename);
|
remove_from_index(tree, top_folder->filename, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_to_tree(&subtree, source, path_left);
|
add_to_tree(&subtree, source, path_left);
|
||||||
@@ -248,7 +257,7 @@ int add_object_to_tree(struct tree *tree, char* filename, struct object *source)
|
|||||||
|
|
||||||
tree_to_object(&subtree, &result);
|
tree_to_object(&subtree, &result);
|
||||||
write_object(&result);
|
write_object(&result);
|
||||||
remove_from_index(tree, filename);
|
remove_from_index(tree, filename, 0);
|
||||||
add_to_tree(tree, &result, top_folder_name);
|
add_to_tree(tree, &result, top_folder_name);
|
||||||
free_object(&result);
|
free_object(&result);
|
||||||
free_tree(&subtree);
|
free_tree(&subtree);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ struct entry *find_entry(struct tree *index, char* filename);
|
|||||||
void get_tree(char* content, struct tree *tree);
|
void get_tree(char* content, struct tree *tree);
|
||||||
int add_to_tree(struct tree *tree, struct object *object, char *filename);
|
int add_to_tree(struct tree *tree, struct object *object, char *filename);
|
||||||
int add_to_index(struct tree *index, char *filename);
|
int add_to_index(struct tree *index, char *filename);
|
||||||
int remove_from_index(struct tree *index, char *filename);
|
int remove_from_index(struct tree *index, char *filename, int delete);
|
||||||
int tree_to_object(struct tree *tree, struct object *object);
|
int tree_to_object(struct tree *tree, struct object *object);
|
||||||
int add_object_to_tree(struct tree *tree, char* filename, struct object *source);
|
int add_object_to_tree(struct tree *tree, char* filename, struct object *source);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user