diff --git a/include/file.h b/include/file.h index b4011e4..ede5628 100644 --- a/include/file.h +++ b/include/file.h @@ -55,7 +55,7 @@ File* slice_file(File*, uint64_t, uint64_t); File* copy_file(File* original); int insert_line(File*, char*, size_t); int delete_line(File*, size_t); -int snapshot_file(char*, char*, size_t, char*); +int snapshot_file(char*, char*, size_t, char*, char*); void free_file(File*); FileInfoBuffer* file_info_buffer_new(); int file_info_buffer_push(FileInfoBuffer*, FileInfo); diff --git a/include/object.h b/include/object.h index 7e92fa4..0af3e8a 100644 --- a/include/object.h +++ b/include/object.h @@ -28,7 +28,7 @@ char* get_object(char*, size_t*); void* parse_object(char*, ObjectType, size_t*, char*); -int save_diff(ActionList*, char*, char*, size_t, char*); +int save_diff(ActionList*, char*, char*, size_t, char*, char*); int read_diff(char*, char*, ActionList*); int save_file_diff(char*, char*, size_t, char*, ActionList*); File* apply_diff(File*, ActionList*); diff --git a/src/commands.c b/src/commands.c index f05c059..f07a439 100644 --- a/src/commands.c +++ b/src/commands.c @@ -420,7 +420,7 @@ int commit(int argc, char** argv) { changes->insertions += modified_file->lines; char file_hash[41]; - snapshot_file(files->items[idx], root, 0, file_hash); + snapshot_file(files->items[idx], root, 0, branch, file_hash); flat_map_put(file_hash_map, files->items[idx], file_hash); continue; } @@ -545,7 +545,7 @@ int commit(int argc, char** argv) { if (diff->len > 200) { char new_base_hash[41]; - snapshot_file(files->items[idx], root, base_file->base_num+1, new_base_hash); + snapshot_file(files->items[idx], root, base_file->base_num+1, branch, new_base_hash); flat_map_put(file_hash_map, files->items[idx], new_base_hash); @@ -559,12 +559,28 @@ int commit(int argc, char** argv) { continue; } else { - save_diff(diff, files->items[idx], root, base_file->diff_num, base_file_hash); + save_diff(diff, files->items[idx], root, base_file->diff_num, base_file_hash, branch); char diff_hash[41]; - char id[3 + snprintf(NULL, 0, "%lu", base_file->diff_num) + strlen(files->items[idx]) + strlen(branch)]; - snprintf(id, sizeof(id), "%s %lu %s", (char*)files->items[idx], base_file->diff_num, branch); - object_hash(BaseFileObject, id, diff_hash); + size_t id_len = snprintf(NULL, 0, "%s %zu %s", (char*)files->items[idx], base_file->diff_num, branch) + 1; + char* id = calloc(id_len, sizeof(char)); + if (!id) { + free_action_list(diff); + free_file(modified_file); + free_file(basefile); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + free(changes); + return 1; + } + + snprintf(id, id_len, "%s %zu %s", (char*)files->items[idx], base_file->diff_num, branch); + object_hash(FileDiffObject, id, diff_hash); + free(id); flat_map_put(file_hash_map, files->items[idx], diff_hash); @@ -625,36 +641,141 @@ int commit(int argc, char** argv) { char timestamp[20]; snprintf(timestamp, sizeof(timestamp), "%ld", time(NULL)); - Author author = { - .name = strdup(config.user.name), - .email = strdup(config.user.email), - .timestamp = strdup(timestamp) - }; + Author* authors = calloc(1, sizeof(Author)); + if (!authors) { + file_info_buffer_free(tree); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; + } - if (log->len != 0) { - char parent_hash[41]; - snprintf(parent_hash, sizeof(parent_hash), "%s", ((Commit*)log->items + (log->len - 1))->hash); + authors[0].name = strdup(config.user.name); + authors[0].email = strdup(config.user.email); + authors[0].timestamp = strdup(timestamp); + if (!authors[0].name || !authors[0].email || !authors[0].timestamp) { + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + file_info_buffer_free(tree); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; } char commit_hash_content[4096]; int offset = 0; - offset += snprintf(commit_hash_content + offset, sizeof(commit_hash_content) - offset, "tree %s\n", tree_hash); - if (log->len != 0) { - offset += snprintf(commit_hash_content + offset, sizeof(commit_hash_content) - offset, "parent %s\n", parent_hash); + size_t remaining = sizeof(commit_hash_content); + + int written = snprintf(commit_hash_content + offset, remaining - offset, "tree %s\n", tree_hash); + if (written < 0 || (size_t)written >= remaining - offset) { + commit_log_free(log); + file_info_buffer_free(tree); + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; } - offset += snprintf(commit_hash_content + offset, sizeof(commit_hash_content) - offset, "author %s <%s> %s\n", author.name, author.email, author.timestamp); - offset += snprintf(commit_hash_content + offset, sizeof(commit_hash_content) - offset, "committer %s <%s> %s\n", author.name, author.email, author.timestamp); - offset += snprintf(commit_hash_content + offset, sizeof(commit_hash_content) - offset, "message %s\n", commit_message); + offset += written; + + if (log->len != 0) { + written = snprintf(commit_hash_content + offset, remaining - offset, "parent %s\n", parent_hash); + if (written < 0 || (size_t)written >= remaining - offset) { + commit_log_free(log); + file_info_buffer_free(tree); + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; + } + offset += written; + } + + written = snprintf(commit_hash_content + offset, remaining - offset, "author %s <%s> %s\n", authors[0].name, authors[0].email, authors[0].timestamp); + if (written < 0 || (size_t)written >= remaining - offset) { + commit_log_free(log); + file_info_buffer_free(tree); + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; + } + offset += written; + + written = snprintf(commit_hash_content + offset, remaining - offset, "committer %s <%s> %s\n", authors[0].name, authors[0].email, authors[0].timestamp); + if (written < 0 || (size_t)written >= remaining - offset) { + commit_log_free(log); + file_info_buffer_free(tree); + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; + } + offset += written; + + written = snprintf(commit_hash_content + offset, remaining - offset, "message %s\n", commit_message); + if (written < 0 || (size_t)written >= remaining - offset) { + commit_log_free(log); + file_info_buffer_free(tree); + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; + } + offset += written; char commit_hash[41]; object_hash(LogObject, commit_hash_content, commit_hash); Commit commit = { - .hash = commit_hash, + .hash = strdup(commit_hash), .tree_hash = strdup(tree_hash), - .authors = &author, + .authors = authors, .authors_count = 1, - .committer = author, + .committer = authors[0], .message = strdup(commit_message) }; @@ -670,6 +791,7 @@ int commit(int argc, char** argv) { free_config(&config); return 1; } + commit_log_free(log); char ref_path[PATH_MAX]; snprintf(ref_path, sizeof(ref_path), "%s/.merk/refs/branches/%s", root, branch); diff --git a/src/commit.c b/src/commit.c index 25ca833..afbcfde 100644 --- a/src/commit.c +++ b/src/commit.c @@ -19,11 +19,13 @@ void commit_log_free(CommitLog* log) { for (size_t j = 0; j < commit->authors_count; j++) { free(commit->authors[j].name); free(commit->authors[j].email); + free(commit->authors[j].timestamp); } free(commit->authors); } free(commit->committer.name); free(commit->committer.email); + free(commit->committer.timestamp); free(commit->message); } free(log->items); diff --git a/src/file.c b/src/file.c index d98e964..d41589e 100644 --- a/src/file.c +++ b/src/file.c @@ -181,7 +181,7 @@ int delete_line(File* file, size_t idx) { return 1; } -int snapshot_file(char* path, char* root, size_t basefile_id, char* hash) { +int snapshot_file(char* path, char* root, size_t basefile_id, char* branch, char* hash) { File* file = new_file(path); if (!file) return 1; @@ -221,9 +221,17 @@ int snapshot_file(char* path, char* root, size_t basefile_id, char* hash) { free(concat_file); concat_file = NULL; - char id[2 + snprintf(NULL, 0, "%d", basefile_id) + strlen(path)]; - snprintf(id, sizeof(id), "%s %d", path, basefile_id); + size_t id_len = snprintf(NULL, 0, "%s %zu %s", path, basefile_id, branch) + 1; + char* id = calloc(id_len, sizeof(char)); + if (!id) { + free(final_content); + free_file(file); + return 0; + } + + snprintf(id, id_len, "%s %zu %s", path, basefile_id, branch); object_hash(BaseFileObject, id, hash); + free(id); char dir_path[PATH_MAX]; char file_path[PATH_MAX]; @@ -323,4 +331,4 @@ FileInfo* file_info_buffer_search(FileInfoBuffer* buffer, const char* filename) FileInfo search_key = {.mode = 0, .name = (char*)filename}; return (FileInfo*)list_binary_search(buffer, &search_key, compare_file_info); -} \ No newline at end of file +} diff --git a/src/object.c b/src/object.c index e4ed47a..2284d4a 100644 --- a/src/object.c +++ b/src/object.c @@ -152,7 +152,7 @@ static int mkdir_recursive(const char *path, mode_t mode) { return 0; } -int save_diff(ActionList* diff, char* path, char* root, size_t diff_id, char* basefile_hash) { +int save_diff(ActionList* diff, char* path, char* root, size_t diff_id, char* basefile_hash, char* branch) { size_t buffer_size = 41; buffer_size += 1 + snprintf(NULL, 0, "%d", diff->len); @@ -204,10 +204,16 @@ int save_diff(ActionList* diff, char* path, char* root, size_t diff_id, char* ba ); } - char id[2+snprintf(NULL, 0, "%d", diff_id)+strlen(path)]; - snprintf(id, sizeof(id), "%s %d", path, diff_id); + size_t id_len = snprintf(NULL, 0, "%s %zu %s", path, diff_id, branch) + 1; + char* id = calloc(id_len, sizeof(char)); + if (!id) { + return 0; + } + + snprintf(id, id_len, "%s %zu %s", path, diff_id, branch); char hash[41]; object_hash(FileDiffObject, id, hash); + free(id); char dir_path[PATH_MAX]; char file_path[PATH_MAX];