diff --git a/src/commit.c b/src/commit.c index 509d5f8..9c65565 100644 --- a/src/commit.c +++ b/src/commit.c @@ -12,84 +12,134 @@ #include "tree.h" #include "types.h" -int commit_from_object(struct commit *commit, struct object *object) +#define parse_field(commit, ptr, field, k_ofs, v_ofs, endline) \ + if (strcmp(ptr + k_ofs, #field) == 0) \ + { \ + commit->field = malloc(endline - v_ofs);\ + commit->field[endline - v_ofs - 1] = '\0'; \ + memcpy(commit->field, ptr + v_ofs + 1, endline - v_ofs - 1);\ + } + +int commit_from_object(commit_t *commit, object_t *object) { - char tmp[object->size + 1]; - memcpy(tmp, object->content, object->size); - tmp[object->size] = '\0'; - char *current_line = strtok(tmp, "\n"); - commit->tree = malloc(strlen(current_line) + 1); - sprintf(commit->tree, "%s", current_line); + int i = 0; + while (i < object->size) + { + int endline = i; + look_for(object->content, '\n', endline); + if (endline - i == 0) // Two consecutives lines feed: Begin of commit message + { + i = endline + 1; + break; + } - current_line = strtok(NULL, "\n"); - commit->parent = malloc(strlen(current_line) + 1); - sprintf(commit->parent, "%s", current_line); + int j = i; + look_for(object->content, ' ', j); + object->content[j] = '\0'; + + parse_field(commit, object->content, tree, i, j, endline) + else parse_field(commit, object->content, parent, i, j, endline) + else parse_field(commit, object->content, author, i, j, endline) + else parse_field(commit, object->content, committer, i, j, endline) + + object->content[j] = ' '; + i = endline + 1; + } + + if(object->size - i > 0) + { + debug_print("There is a commit msg"); + commit->message = malloc(object->size - i + 1); + commit->message[object->size - i] = '\0'; + memcpy(commit->message, object->content + i, object->size - i); + } - current_line = strtok(NULL, "\n"); - commit->author = malloc(strlen(current_line) + 1); - sprintf(commit->author, "%s", current_line); return 0; } -int commit_to_object(struct commit *commit, struct object *object) +int commit_to_object(commit_t *commit, object_t *object) { object->object_type = COMMIT; - object->size = strlen(commit->tree) + 2; + object->size = 5 + strlen(commit->tree) + 2; // len('tree ' + + '\n' + '\0') object->content = malloc(object->size); - sprintf(object->content, "%s\n", commit->tree); + sprintf(object->content, "tree %s\n", commit->tree); - object->size += strlen(commit->parent) + 1; + if (commit->parent != NULL) + { + object->size += 7 + strlen(commit->parent) + 1; // len('parent ' + + '\n') + object->content = realloc(object->content, object->size); + strcat(object->content, "parent "); + strncat(object->content, commit->parent, strlen(commit->parent)); + strcat(object->content, "\n"); + } + + object->size += 7 + strlen(commit->author) + 1; // len('author ' + + '\n') object->content = realloc(object->content, object->size); - strncat(object->content, commit->parent, strlen(commit->parent)); + strcat(object->content, "author "); + strncat(object->content, commit->author, strlen(commit->author)); strcat(object->content, "\n"); - object->size += strlen(commit->author); + object->size += 10 + strlen(commit->committer) + 2; // len('committer ' + + '\n' + '\n') object->content = realloc(object->content, object->size); + strcat(object->content, "committer "); strncat(object->content, commit->author, strlen(commit->author)); + strcat(object->content, "\n\n"); + + object->size += strlen(commit->message) + 1; + object->content = realloc(object->content, object->size); + strncat(object->content, commit->message, strlen(commit->message)); + strcat(object->content, "\n"); object->size --; + return 0; } -void free_commit(struct commit *commit) +void free_commit(commit_t *commit) { if (commit->author != NULL) free(commit->author); + if (commit->committer != NULL) + free(commit->committer); + if (commit->parent != NULL) free(commit->parent); if (commit->tree != NULL) free(commit->tree); + + if (commit->message != NULL) + free(commit->message); } -int commit() +int commit(char *msg) { - struct tree index = {0}; + tree_t index = {0}; if (load_index(&index) == REPO_NOT_INITIALIZED) { return REPO_NOT_INITIALIZED; } - struct object last_commit = {0}; - struct commit commit = {0}; + object_t last_commit = {0}; + commit_t commit = {0}; char last_commit_checksum[DIGEST_LENGTH * 2 + 1] = {0}; - struct tree commit_tree = {0}; + tree_t commit_tree = {0}; get_last_commit(&last_commit); if (last_commit.size != 0) { hash_object_str(&last_commit, last_commit_checksum); commit_from_object(&commit, &last_commit); - struct object last_commit_tree = {0}; + object_t last_commit_tree = {0}; read_object(commit.tree, &last_commit_tree); tree_from_object(&commit_tree, &last_commit_tree); free_object(&last_commit_tree); } free_object(&last_commit); - struct entry *current = index.first_entry; + entry_t *current = index.first_entry; while(current != NULL) { - struct object object = {0}; + object_t object = {0}; blob_from_file(current->filename, &object); add_object_to_tree(&commit_tree, current->filename, current->mode, &object); @@ -98,21 +148,22 @@ int commit() current = current->next; } - if (commit.author == NULL) + char* author = "Antonin"; + commit.author = realloc(commit.author, strlen(author) + 1); + commit.committer = realloc(commit.committer, strlen(author) + 1); + sprintf(commit.author, "%s", author); + sprintf(commit.committer, "%s", author); + + if (last_commit.size != 0) { - char* author = "Antonin"; - commit.author = malloc(strlen(author) + 1); - sprintf(commit.author, "%s", author); + commit.parent = realloc(commit.parent, DIGEST_LENGTH * 2 + 1); + sprintf(commit.parent, "%s", last_commit_checksum); } - - commit.parent = realloc(commit.parent, DIGEST_LENGTH * 2 + 1); - if (last_commit.size == 0) - { - sprintf(commit.parent, "%s", " "); - } else - { - sprintf(commit.parent, "%s", last_commit_checksum); + if (msg[0] != '\0') + { + commit.message = calloc(1, strlen(msg) + 1); + sprintf(commit.message, "%s", msg); } struct object commit_tree_obj = {0}; diff --git a/src/commit.h b/src/commit.h index 0eb84da..8316ac3 100644 --- a/src/commit.h +++ b/src/commit.h @@ -3,10 +3,11 @@ #include "types.h" -int commit_from_object(struct commit *commit, struct object *object); -void free_commit(struct commit *commit); +int commit_from_object(commit_t *commit, object_t *object); +int commit_to_object(commit_t *commit, object_t *object); +void free_commit(commit_t *commit); int diff_commit(char* checksum_a, char* checksum_b, int for_print); int diff_commit_with_working_tree(char *checksum, int for_print); -int commit(); +int commit(char *msg); #endif // COMMIT_H \ No newline at end of file diff --git a/src/fs.c b/src/fs.c index e1efc0f..0656a47 100644 --- a/src/fs.c +++ b/src/fs.c @@ -655,11 +655,10 @@ int dump_log() char checksum[DIGEST_LENGTH * 2 + 1]; hash_object_str(¤t_obj, checksum); fprintf(log_file, "commit %s HEAD\n", checksum); - fprintf(log_file, "Author: %s\n", current.author); - fprintf(log_file, "Tree: %s\n", current.tree); - fprintf(log_file, "\n"); + fprintf(log_file, "Author: \t%s\n", current.author); + fprintf(log_file, "\n\t%s\n", current.message); - while (strcmp(current.parent, " ") != 0) + while (current.parent != NULL) { free_object(¤t_obj); read_object(current.parent, ¤t_obj); @@ -669,9 +668,8 @@ int dump_log() checksum[DIGEST_LENGTH * 2 + 1]; hash_object_str(¤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"); + fprintf(log_file, "Author: \t%s\n", current.author); + fprintf(log_file, "\t%s\n", current.message); } fclose(log_file); return 0; diff --git a/src/main.c b/src/main.c index 4cfc1d6..e9590f3 100644 --- a/src/main.c +++ b/src/main.c @@ -96,7 +96,7 @@ int remove_cmd(int argc, char **argv) struct tree index = {0}; if (load_index(&index) == REPO_NOT_INITIALIZED) { - printf("Not a cgit repository\n"); + printf("fatal: not a cgit repository\n"); return 128; } @@ -113,11 +113,28 @@ int remove_cmd(int argc, char **argv) int commit_cmd(int argc, char **argv) { - if (commit("") == REPO_NOT_INITIALIZED) - { - printf("Not a cgit repository\n"); - return 128; + char buf[ARGS_MAX_SIZE]; + + if(pop_arg(&argc, &argv, buf) == 1) + goto usage; + + if(strcmp(buf, "-m") == 0) + { + if (pop_arg(&argc, &argv, buf) == 1) + goto usage; + + if (commit(buf) == REPO_NOT_INITIALIZED) + { + printf("Not a cgit repository\n"); + return 128; + } } + + return 0; + +usage: + printf("usage: cgit commit -m \n"); + return 129; } int diff(int argc, char **argv) @@ -321,24 +338,27 @@ int main(int argc, char **argv) } else if (strcmp(buf, "show-index") == 0) { return show_index(argc, argv); - } else if (strcmp(buf, "test") == 0) - { + } else if (strcmp(buf, "test") == 0) + { + commit_t commit = {0}; + // commit.author = "Antonin"; + // commit.parent = "a7ds456"; + // commit.tree = "aq46sq4"; + // commit.message = "Init commit"; + object_t obj = {0}; - read_object("192f287aebddb0080e6ea7cb567d76d78b54dee2", &obj); + read_object("40f0cbeb12128c258cecaa776c5af7b3971214ad", &obj); + // commit_to_object(&commit, &obj); + // write_object(&obj); - tree_t tree = {0}; - tree_from_object(&tree, &obj); - free_object(&obj); + commit_from_object(&commit, &obj); - debug_print("entries_size: %li", tree.entries_size); - debug_print("first_entry->filename: %s", tree.first_entry->filename); - debug_print("last_entry->filename: %s", tree.last_entry->filename); + debug_print("tree %s", commit.tree); + debug_print("parent %s", commit.parent); + debug_print("author %s", commit.author); + debug_print("committer %s", commit.committer); + debug_print("msg %s", commit.message); - tree_to_object(&tree, &obj); - write_object(&obj); - - free_tree(&tree); - free_object(&obj); } else { printf("Unknown command %s, try using %s -h\n", buf, cmd); return 0; diff --git a/src/types.h b/src/types.h index cfb855c..97e4395 100644 --- a/src/types.h +++ b/src/types.h @@ -49,6 +49,7 @@ typedef struct commit char *tree; char *parent; char *author; + char *committer; char *message; } commit_t;