From ae0276aadaee422611bd67128c9d7e2cb1eb8855 Mon Sep 17 00:00:00 2001 From: Zejun Lin <871886504@qq.com> Date: Sat, 25 Apr 2020 14:13:51 -0400 Subject: [PATCH 1/7] add commit --- src/lib/commands.cpp | 26 ++++++++++++++++++------ src/lib/commands.hpp | 8 +++++--- src/lib/git_objects.cpp | 1 + src/lib/git_objects.hpp | 6 ++++++ test/test.cpp | 45 ++++------------------------------------- 5 files changed, 36 insertions(+), 50 deletions(-) diff --git a/src/lib/commands.cpp b/src/lib/commands.cpp index 6735ebe..69acd30 100644 --- a/src/lib/commands.cpp +++ b/src/lib/commands.cpp @@ -14,7 +14,7 @@ int test_function(void) { } -void cmd_init(std::vector& args){ +void cmd_init(const std::vector& args){ if ((args.size() >= 1 && args[0] == "--help") || args.size() > 1) { throw GIT_INIT_USAGE; @@ -23,7 +23,7 @@ void cmd_init(std::vector& args){ } -void cmd_cat_file(std::vector& args){ +void cmd_cat_file(const std::vector& args){ if (args.size() <= 1 || CAT_FILE_SUBCMDS.find(args[0]) == CAT_FILE_SUBCMDS.end() || args[0] == "--help") { throw CAT_FILE_USAGE; @@ -31,7 +31,7 @@ void cmd_cat_file(std::vector& args){ git_cat_file(fs::canonical(args[1]), "commit"); } -void cmd_checkout(std::vector& args){ +void cmd_checkout(const std::vector& args){ if (args.size() != 1) { throw CHECKOUT_USAGE; @@ -39,6 +39,14 @@ void cmd_checkout(std::vector& args){ git_checkout(args[0]); } +void cmd_commit(const std::vector& args){ + if (args.size() != 2) + { + throw "Currently only support `git commit -m 'your commit message'`"; + } + git_commit(args[1]); +} + void git_cat_file(fs::path obj, const std::string& fmt){ fs::path repo = repo_find(fs::current_path()); GitObject* object = read_object(repo, object_find(repo, obj, fmt)); @@ -74,14 +82,20 @@ void git_checkout(std::string hash){ if (fmt == "commit") { GitCommit* commit_obj = dynamic_cast(obj); git_checkout(commit_obj->tree_hash); - } else if (fmt == "tree") { - fs::path repo_base_path = repo_find(fs::current_path()); - walk_tree_and_replace(repo_base_path, obj); } else { throw "Shouldn't reach here"; } } +void git_commit(std::string commit_message){ + fs::path project_base_path = repo_find(fs::current_path()); + fs::path git_path = project_base_path / ".cpp-git"; + std::string index_tree_hash = get_tree_hash_of_index(git_path); + auto parent_commit_hash = HOWTOGET(); + GitCommit* obj = new GitCommit(git_path, index_tree_hash, parent_commit_hash, commit_message); + // TODO: write and update commit_obj to head +} + std::string get_sub_tree_hash_for_new_file(std::string old_tree_hash, typename fs::path::iterator file_it, const typename fs::path::iterator end_it, const fs::path git_path, diff --git a/src/lib/commands.hpp b/src/lib/commands.hpp index 7e055f6..4f679ac 100644 --- a/src/lib/commands.hpp +++ b/src/lib/commands.hpp @@ -17,13 +17,15 @@ namespace fs = std::filesystem; /* ********* Functions ********* */ // Functions dealing with commands: validate, convert file path to absolute etc. -void cmd_init(std::vector& args); -void cmd_cat_file(std::vector& args); -void cmd_checkout(std::vector& args); +void cmd_init(const std::vector& args); +void cmd_cat_file(const std::vector& args); +void cmd_checkout(const std::vector& args); +void cmd_commit(const std::vector& args); // Actual functions executing commands void git_cat_file(fs::path obj, const std::string& fmt); void git_init(fs::path project_base_path); void git_checkout(std::string hash); +void git_commit(); int test_function(void); diff --git a/src/lib/git_objects.cpp b/src/lib/git_objects.cpp index 98a1e7a..38725c2 100644 --- a/src/lib/git_objects.cpp +++ b/src/lib/git_objects.cpp @@ -9,6 +9,7 @@ GitObject::GitObject(fs::path git_path) { GitCommit::GitCommit(fs::path git_path, const std::string& data) : GitObject(git_path) { to_internal(data); } + GitTree::GitTree(fs::path git_path, const std::string& data) : GitObject(git_path) { to_internal(data); } diff --git a/src/lib/git_objects.hpp b/src/lib/git_objects.hpp index d548f2c..9957951 100644 --- a/src/lib/git_objects.hpp +++ b/src/lib/git_objects.hpp @@ -37,6 +37,12 @@ class GitCommit : public GitObject { std::string commit_message; virtual std::string get_fmt(void); GitCommit(fs::path git_path, const std::string& data); + GitCommit::GitCommit(fs::path git_path, const std::string& tree_hash, + const std::string parent_hash, const std::string commit_message): + GitObject(git_path), + tree_hash(tree_hash), + parent_hash(parent_hash), + commit_message(commit_message){}; void to_internal(const std::string& data); virtual std::string to_filesystem(void); }; diff --git a/test/test.cpp b/test/test.cpp index f7e97b4..85813af 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -182,43 +182,6 @@ class TreeTraversal : public ::testing::Test { } }; -TEST_F(TreeTraversal, one_level_tree) { - /* // Now walk */ - fs::path git_path = repo_find(fs::current_path()) / ".cpp-git"; - chkout_obj(git_path, tree_hash); - - // Check that we have written to project's path and that content is the same - std::string final_message_1 = read_file(current_path / "file1.txt"); - /* final_message_1.pop_back(); */ - std::string final_message_2 = read_file(current_path / "file2.txt"); - /* final_message_2.pop_back(); */ - ASSERT_EQ(message_1, final_message_1); - ASSERT_EQ(message_2, final_message_2); -} - -TEST_F(TreeTraversal, two_level_tree) { - // Create root tree - fs::path git_path = repo_find(fs::current_path()) / ".cpp-git"; - std::string message_3 = "file3"; - GitBlob file_3(git_path, message_3); - std::string hash_3 = write_object(&file_3); - GitTree root_tree_obj(git_path); - // Take tree from above and append to this tree - root_tree_obj.add_entry("blob", "file3.txt", hash_3); - root_tree_obj.add_entry("tree", "folder", tree_hash); - std::string root_hash = write_object(&root_tree_obj); - - // Now walk - chkout_obj(git_path, root_hash); - - // Check that everything is the same - ASSERT_EQ(message_3, read_file(current_path / "file3.txt")); - std::string final_message_1 = read_file(current_path / "folder" / "file1.txt"); - std::string final_message_2 = read_file(current_path / "folder" / "file2.txt"); - ASSERT_EQ(message_1, final_message_1); - ASSERT_EQ(message_2, final_message_2); -} - #if 1 TEST(Staging, git_add_entireFolder) { git_folder_setup("entireFolder"); @@ -320,7 +283,7 @@ TEST(Staging, git_add_file_twoLevelsNewFile) { // compare the two tree objects /* std::cout << "New Tree Listing" << std::endl; */ /* print_tree(git_path,new_tree_hash); */ - GitBlob* stage4_blob = findProjectFileFromTree(new_tree_hash, "folder/stage4.txt", git_path); + GitBlob* stage4_blob = find_project_file_from_tree(new_tree_hash, "folder/stage4.txt", git_path); ASSERT_EQ(stage4_blob->data, "stage4"); fs::remove_all(project_base_path); @@ -347,9 +310,9 @@ TEST(Staging, git_add_folder_twoLevelsNewFile) { // Add new file under folder write_file(project_base_path / "folder" / "stage4.txt", "stage4"); std::string new_tree_hash = git_add_folder(project_base_path / "folder"); - GitBlob* stage4_blob = findProjectFileFromTree(new_tree_hash, "folder/stage4.txt", git_path); + GitBlob* stage4_blob = find_project_file_from_tree(new_tree_hash, "folder/stage4.txt", git_path); ASSERT_EQ(stage4_blob->data, "stage4"); - GitTree* folder = findProjectFolderFromTree(new_tree_hash, "folder", git_path); + GitTree* folder = find_project_folder_from_tree(new_tree_hash, "folder", git_path); std::cout << "folder listing: " << std::endl; printer(folder->directory); @@ -379,7 +342,7 @@ TEST(Staging, git_add_folder_twoLevelsNewFolder) { write_file(project_base_path / "folder" / "new_folder" / "new.txt", "new"); std::string new_tree_hash = git_add_folder(project_base_path / "folder"); - GitTree* folder = findProjectFolderFromTree(new_tree_hash, "folder/new_folder", git_path); + GitTree* folder = find_project_folder_from_tree(new_tree_hash, "folder/new_folder", git_path); std::cout << "new_folder listing: " << std::endl; printer(folder->directory); From 0a9ffebf78e6ace0334386fb1e0bd00b62ba7e56 Mon Sep 17 00:00:00 2001 From: Zejun Lin <871886504@qq.com> Date: Sat, 25 Apr 2020 14:14:36 -0400 Subject: [PATCH 2/7] add commit --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index c4b320a..1eb35fc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,7 +47,7 @@ class InputParser {"rev-parse", cmd_print}, {"rm", cmd_print}, {"show-ref", cmd_print}, - {"tag", cmd_print}, + {"tag", cmd_print} }; }; From 9d5ffa5a78b6b2456755359913f578dcdd5f220a Mon Sep 17 00:00:00 2001 From: Zejun Lin <871886504@qq.com> Date: Sat, 25 Apr 2020 14:14:47 -0400 Subject: [PATCH 3/7] add commit --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index def6e31..f053f88 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(INSTALL_BIN_DIR ${PROJECT_SOURCE_DIR}/bin) add_compile_options(-W -Wall) set(CMAKE_CXX_STANDARD 20) if(APPLE) - include_directories(/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include) + #include_directories(/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include) endif() set(CMAKE_EXPORT_COMPILE_COMMANDS YES) From ad89d7a72a5e641f03184016d448be6bbea26fcb Mon Sep 17 00:00:00 2001 From: Zejun Lin <871886504@qq.com> Date: Sat, 25 Apr 2020 14:43:11 -0400 Subject: [PATCH 4/7] fix --- src/lib/commands.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/commands.hpp b/src/lib/commands.hpp index f189701..8b28c41 100644 --- a/src/lib/commands.hpp +++ b/src/lib/commands.hpp @@ -29,7 +29,7 @@ void cmd_hash_object(const std::vector &args); void git_cat_file(fs::path obj, const std::string& fmt); void git_init(fs::path project_base_path); void git_checkout(std::string hash); -void git_commit(); +void git_commit(std::string commit_message); void git_hash_object(fs::path path, const std::string& fmt); int test_function(void); From 11f7bdbe9357afaff83930dc5fd6edd37fe9da6f Mon Sep 17 00:00:00 2001 From: Zejun Lin <871886504@qq.com> Date: Sat, 25 Apr 2020 21:10:46 -0400 Subject: [PATCH 5/7] add git commit command and test code --- src/lib/commands.cpp | 27 +++++++++++++++--- src/lib/commands.hpp | 1 + src/lib/git_objects.cpp | 17 +++++++++++- src/lib/git_objects.hpp | 11 ++++---- src/lib/helper.cpp | 7 +++-- test/test.cpp | 61 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 110 insertions(+), 14 deletions(-) diff --git a/src/lib/commands.cpp b/src/lib/commands.cpp index bbf2eac..46d5b3d 100644 --- a/src/lib/commands.cpp +++ b/src/lib/commands.cpp @@ -19,10 +19,22 @@ void cmd_init(const std::vector& args){ { throw GIT_INIT_USAGE; } - git_init(fs::canonical(args[0])); + git_init(args[0]); } +void cmd_add(const std::vector &args){ + for(auto path: args){ + if (path != "/") path = fs::canonical(path); + if (fs::is_directory(path)){ + std::string ERROR = "TODO: add git add folder"; + } + else{ + git_add_file(path); + } + } +} + void cmd_cat_file(const std::vector &args){ if (args.size() <= 1 || CAT_FILE_SUBCMDS.find(args[0]) == CAT_FILE_SUBCMDS.end() || args[0] == "--help") { @@ -71,7 +83,9 @@ void git_init(fs::path project_base_path) { fs::create_directories(git_path / "branches"); // create refs dir with tags+heads subdirectory fs::create_directories(git_path / "refs" / "tags"); - fs::create_directories(git_path / "refs" / "heads"); + GitCommit root_commit = GitCommit(git_path); + write_file(git_path / "refs" / "heads" / "master", write_object(&root_commit)); + write_file(git_path / "index", root_commit.tree_hash); } @@ -91,10 +105,13 @@ void git_commit(std::string commit_message){ fs::path project_base_path = repo_find(fs::current_path()); fs::path git_path = project_base_path / ".cpp-git"; fs::path head_path = git_path / "HEAD"; - // Hash of the previous commit (aka HEAD) + + // Hash of the previous commit (aka HEAD), might be empty if it's the first commit auto parent_commit_hash = ref_resolve(head_path); + // Hash of the new tree in index std::string index_tree_hash = get_tree_hash_of_index(git_path); + // New commit, write to file and update HEAD GitCommit* new_commit_obj = new GitCommit(git_path, index_tree_hash, parent_commit_hash, commit_message); std::string new_commit_hash = write_object(new_commit_obj, true); @@ -277,8 +294,10 @@ std::string read_project_folder_and_write_tree(const fs::path& adding_directory, std::string ref_resolve(const fs::path& path) { std::string data = read_file(path); + //No content if it's an initial commit + if (data.size() == 0) return ""; if (data.rfind("ref: ", 0) == 0) - return ref_resolve(data.substr(5)); + return ref_resolve(repo_find(path)/ ".cpp-git" / data.substr(5)); else return data; } diff --git a/src/lib/commands.hpp b/src/lib/commands.hpp index 8b28c41..eb6352e 100644 --- a/src/lib/commands.hpp +++ b/src/lib/commands.hpp @@ -20,6 +20,7 @@ namespace fs = std::filesystem; /* ********* Functions ********* */ // Functions dealing with commands: validate, convert file path to absolute etc. void cmd_init(const std::vector& args); +void cmd_add(const std::vector &args); void cmd_cat_file(const std::vector& args); void cmd_checkout(const std::vector& args); void cmd_commit(const std::vector& args); diff --git a/src/lib/git_objects.cpp b/src/lib/git_objects.cpp index 38725c2..71093c4 100644 --- a/src/lib/git_objects.cpp +++ b/src/lib/git_objects.cpp @@ -1,6 +1,7 @@ #include "git_objects.hpp" #include #include +#include GitObject::GitObject(fs::path git_path) { this->git_path = git_path; @@ -10,10 +11,24 @@ GitCommit::GitCommit(fs::path git_path, const std::string& data) : GitObject(git to_internal(data); } +GitCommit::GitCommit(fs::path git_path, const std::string& tree_hash, + const std::string parent_hash, const std::string commit_message): + GitObject(git_path), + tree_hash(tree_hash), + parent_hash(parent_hash), + commit_message(commit_message){}; + +GitCommit::GitCommit(fs::path git_path) : GitObject(git_path), parent_hash(""), commit_message("") { + GitTree* tree_obj = new GitTree(git_path); + std::string tree_obj_hash = write_object(tree_obj, true); + this->tree_hash = tree_obj_hash; + delete tree_obj; +} + GitTree::GitTree(fs::path git_path, const std::string& data) : GitObject(git_path) { to_internal(data); } -GitTree::GitTree(fs::path git_path) : GitObject(git_path){}; +GitTree::GitTree(fs::path git_path) : GitObject(git_path), directory(std::vector{}){}; GitTag::GitTag(fs::path git_path, const std::string& data) : GitObject(git_path) { to_internal(data); } diff --git a/src/lib/git_objects.hpp b/src/lib/git_objects.hpp index 9957951..455fe73 100644 --- a/src/lib/git_objects.hpp +++ b/src/lib/git_objects.hpp @@ -1,6 +1,7 @@ #ifndef GIT_OBJECT_HPP #define GIT_OBJECT_HPP #include +#include #include #include namespace fs = std::filesystem; @@ -37,12 +38,10 @@ class GitCommit : public GitObject { std::string commit_message; virtual std::string get_fmt(void); GitCommit(fs::path git_path, const std::string& data); - GitCommit::GitCommit(fs::path git_path, const std::string& tree_hash, - const std::string parent_hash, const std::string commit_message): - GitObject(git_path), - tree_hash(tree_hash), - parent_hash(parent_hash), - commit_message(commit_message){}; + GitCommit(fs::path git_path, const std::string& tree_hash, + const std::string parent_hash, const std::string commit_message); + // create a root commit without parent and any file + GitCommit(fs::path git_path); void to_internal(const std::string& data); virtual std::string to_filesystem(void); }; diff --git a/src/lib/helper.cpp b/src/lib/helper.cpp index 623edfd..b1a090d 100644 --- a/src/lib/helper.cpp +++ b/src/lib/helper.cpp @@ -68,9 +68,10 @@ GitObject* read_object(fs::path git_path, std::string hash) { /* std::cout << "Read(File After EOF Remove): " << content.length() << std::endl; */ auto split_index = content.find('\0'); /* std::cout << "Split index: " << split_index << std::endl; */ - if (split_index == content.length() - 1) { - throw "not a valid file"; - } + // if (split_index == content.length() - 1) { + // std::cout<<"FFF"<{worktree}); + fs::path git_path = worktree / ".cpp-git"; + ASSERT_TRUE(fs::exists(git_path / "HEAD")); + ASSERT_TRUE(fs::exists(git_path / "objects")); + ASSERT_TRUE(fs::exists(git_path / "branches")); + ASSERT_TRUE(fs::exists(git_path / "refs" / "tags")); + ASSERT_TRUE(fs::exists(git_path / "refs" / "heads")); + ASSERT_TRUE(fs::exists(git_path / "refs" / "heads" / "master")); + ASSERT_EQ(read_file(git_path / "HEAD"), "ref: refs/heads/master"); +} + +TEST(GitCommand, git_commit){ + fs::path worktree = "test_git_commit"; + git_folder_setup(worktree); + worktree = fs::canonical(worktree); + fs::path git_path = worktree / ".cpp-git"; + fs::current_path(worktree);//change working directory + + // git add a new file + std::string filename = "test.txt"; + fs::path txtfile = worktree / filename; + std::string content = "Now test git_commit command"; + write_file(txtfile, content); + cmd_add(std::vector{txtfile}); + ASSERT_TRUE(fs::exists(git_path / "index")); + std::cout<<"Finish adding a new file"<(read_object(git_path, hash)); + ASSERT_EQ(commit_obj->commit_message, message); + std::cout<<"Finish testing content"<(read_object(git_path, commit_obj->tree_hash)); + ASSERT_EQ(tree_obj->directory.size(), 1); + ASSERT_EQ(tree_obj->directory[0].name, filename); + GitBlob* blob_obj = dynamic_cast(read_object(git_path, tree_obj->directory[0].hash)); + ASSERT_EQ(blob_obj->data, content); +} + From b4458a19557f2db84fd33de599be493955a8c78a Mon Sep 17 00:00:00 2001 From: Zejun Lin <871886504@qq.com> Date: Sun, 26 Apr 2020 11:50:59 -0400 Subject: [PATCH 6/7] fix wrong update of HEAD and add git reset command --- src/lib/commands.cpp | 33 +++++++++++--- src/lib/commands.hpp | 4 +- test/test.cpp | 100 ++++++++++++++++++++++++++++++++----------- 3 files changed, 106 insertions(+), 31 deletions(-) diff --git a/src/lib/commands.cpp b/src/lib/commands.cpp index 46d5b3d..3f57465 100644 --- a/src/lib/commands.cpp +++ b/src/lib/commands.cpp @@ -59,6 +59,13 @@ void cmd_commit(const std::vector& args){ git_commit(args[1]); } +void cmd_reset(const std::vector& args){ + if (args.size() == 0 || args[0] == "--mixed") + git_reset(false); + else + git_reset(true); +} + void git_cat_file(fs::path obj, const std::string& fmt){ fs::path repo = repo_find(fs::current_path()); GitObject* object = read_object(repo, object_find(repo, obj, fmt)); @@ -115,7 +122,23 @@ void git_commit(std::string commit_message){ // New commit, write to file and update HEAD GitCommit* new_commit_obj = new GitCommit(git_path, index_tree_hash, parent_commit_hash, commit_message); std::string new_commit_hash = write_object(new_commit_obj, true); - write_file(head_path, new_commit_hash); + /* TODO Write to master instead of HEAD */ + write_file(ref_resolve(head_path, true), new_commit_hash); +} + +void git_reset(bool hard){ + fs::path worktree = repo_find(fs::current_path()); + fs::path git_path = worktree / ".cpp-git"; + // Get tree_hash from HEAD + std::string head_commit_hash = ref_resolve(git_path / "HEAD"); + GitCommit* head_commit = dynamic_cast(read_object(git_path, head_commit_hash)); + std::string head_commit_tree_hash = head_commit->tree_hash; + write_file(git_path / "index", head_commit_tree_hash); + + if (hard){ + GitTree* tree = dynamic_cast(read_object(git_path, head_commit_tree_hash)); + walk_tree_and_replace(worktree, tree); + } } @@ -292,12 +315,12 @@ std::string read_project_folder_and_write_tree(const fs::path& adding_directory, return output; } -std::string ref_resolve(const fs::path& path) { +std::string ref_resolve(const fs::path& path, bool return_file_path) { std::string data = read_file(path); - //No content if it's an initial commit - if (data.size() == 0) return ""; if (data.rfind("ref: ", 0) == 0) - return ref_resolve(repo_find(path)/ ".cpp-git" / data.substr(5)); + return ref_resolve(repo_find(path)/ ".cpp-git" / data.substr(5), return_file_path); + else if (return_file_path) + return path; else return data; } diff --git a/src/lib/commands.hpp b/src/lib/commands.hpp index eb6352e..bae5ab0 100644 --- a/src/lib/commands.hpp +++ b/src/lib/commands.hpp @@ -26,12 +26,14 @@ void cmd_checkout(const std::vector& args); void cmd_commit(const std::vector& args); void cmd_show_ref(const std::vector &args); void cmd_hash_object(const std::vector &args); +void cmd_reset(const std::vector& args); // Actual functions executing commands void git_cat_file(fs::path obj, const std::string& fmt); void git_init(fs::path project_base_path); void git_checkout(std::string hash); void git_commit(std::string commit_message); void git_hash_object(fs::path path, const std::string& fmt); +void git_reset(bool hard); int test_function(void); @@ -39,6 +41,6 @@ std::string git_add_file(const fs::path& file_path); std::string read_project_folder_and_write_tree(const fs::path& adding_directory, bool root = false); std::string git_add_folder(const fs::path folder_path); -std::string ref_resolve(const fs::path& path); +std::string ref_resolve(const fs::path& path, bool return_file_path = false); std::unordered_map ref_list(const fs::path& base_path); #endif diff --git a/test/test.cpp b/test/test.cpp index 5497655..38cf423 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -402,50 +402,100 @@ TEST(GitCommand, git_init){ ASSERT_TRUE(fs::exists(git_path / "HEAD")); ASSERT_TRUE(fs::exists(git_path / "objects")); ASSERT_TRUE(fs::exists(git_path / "branches")); + ASSERT_TRUE(fs::exists(git_path / "index")); ASSERT_TRUE(fs::exists(git_path / "refs" / "tags")); ASSERT_TRUE(fs::exists(git_path / "refs" / "heads")); ASSERT_TRUE(fs::exists(git_path / "refs" / "heads" / "master")); ASSERT_EQ(read_file(git_path / "HEAD"), "ref: refs/heads/master"); } +void add_testing_file(fs::path file_path, std::string content){ + write_file(file_path, content); + cmd_add(std::vector{file_path}); + std::cout<<"Finish adding a new file: "<< file_path <{txtfile}); - ASSERT_TRUE(fs::exists(git_path / "index")); - std::cout<<"Finish adding a new file"<(read_object(git_path, hash)); + ASSERT_EQ(commit_obj->commit_message, message); + std::cout<<"Finish testing content"<(read_object(git_path, commit_obj->tree_hash)); + ASSERT_EQ(tree_obj->directory.size(), 1); + ASSERT_EQ(tree_obj->directory[0].name, filename); + GitBlob* blob_obj = dynamic_cast(read_object(git_path, tree_obj->directory[0].hash)); + ASSERT_EQ(blob_obj->data, content); } catch (char const *e) { std::cout << e << std::endl; throw e; } - std::cout<<"Finish invoking git commit"<(read_object(git_path, hash)); - ASSERT_EQ(commit_obj->commit_message, message); - std::cout<<"Finish testing content"<(read_object(git_path, commit_obj->tree_hash)); - ASSERT_EQ(tree_obj->directory.size(), 1); - ASSERT_EQ(tree_obj->directory[0].name, filename); - GitBlob* blob_obj = dynamic_cast(read_object(git_path, tree_obj->directory[0].hash)); - ASSERT_EQ(blob_obj->data, content); + fs::current_path(".."); } +TEST(GitCommand, git_reset){ + fs::path worktree = "test_git_reset"; + git_folder_setup(worktree); + worktree = fs::canonical(worktree); + fs::path git_path = worktree / ".cpp-git"; + fs::current_path(worktree);//change working directory + auto get_HEAD_tree_hash = [&](){ + std::string head_commit_hash = ref_resolve(git_path / "HEAD"); + return dynamic_cast(read_object(git_path, head_commit_hash))->tree_hash; + }; + try{ + // git add a new file + std::string filename = "test.txt", content = "Now test git_rest command"; + add_testing_file(worktree / filename, content); + + // get the initial tree hash + std::string HEAD_tree_hash = get_HEAD_tree_hash(); + // test git reset --mixed as default; + ASSERT_NE(read_file(git_path / "index"), HEAD_tree_hash); + cmd_reset(std::vector{}); + ASSERT_EQ(read_file(git_path / "index"), HEAD_tree_hash); + ASSERT_EQ(read_file(worktree / filename), content); + + // test git reset --hard + // commit to change HEAD + add_testing_file(worktree / filename, content); + cmd_commit(std::vector{"-m", "Init commit"}); + HEAD_tree_hash = get_HEAD_tree_hash(); + // Add modified file + std::string new_content = "Now test git_rest command with '--hard' option"; + add_testing_file(worktree / filename, new_content); + ASSERT_NE(read_file(git_path / "index"), HEAD_tree_hash); + cmd_reset(std::vector{"--hard"}); + // test if index is reset to head and files are replaced + ASSERT_EQ(read_file(git_path / "index"), HEAD_tree_hash); + ASSERT_EQ(read_file(worktree / filename), content); + } + catch (char const *e) + { + std::cout << e << std::endl; + throw e; + } + fs::current_path(".."); +} \ No newline at end of file From 1bf5afa6ac6c1e914f7a12866ca54fbc68ffc53e Mon Sep 17 00:00:00 2001 From: Zejun Lin <871886504@qq.com> Date: Sun, 26 Apr 2020 11:55:49 -0400 Subject: [PATCH 7/7] update TODO --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3a26a72..f08f87c 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,13 @@ * Add references/tags * add lazy write optimization to write_object + write test for it * Define TearDown to delete created files from testing -* conversion between relative to absolute path in interpreter code +* conversion between relative to absolute path in interpreter code [DONE] * git_path speedup optimization * implement git update-ref * fix memory leaks -- no delete after newing git object -* git reset --medium(aka default) = just change index file to point to HEAD commit -* git reset --hard = do above + walkTreeAndReplace on HEAD commit +* git reset --medium(aka default) = just change index file to point to HEAD commit [DONE] +* git reset --hard = do above + walkTreeAndReplace on HEAD commit [DONE] * git log: walk HEAD backwards , printing as you go along * filter * --stat = call "git status" between each commit @@ -30,7 +30,7 @@ * -a: show all branches * nothing: create a new branch and switch to it(Note this is different from default behavior) * git cat-file = take the hash and try to find the file. If found, read it in using read_file and print the contents. Otherwise throw not found error -* git commit +* git commit [DONE] * command * cat-file [DONE]