diff --git a/YaLibs/YaToolsIDALib/Repository.cpp b/YaLibs/YaToolsIDALib/Repository.cpp index f3cddc8d..e11142b8 100644 --- a/YaLibs/YaToolsIDALib/Repository.cpp +++ b/YaLibs/YaToolsIDALib/Repository.cpp @@ -47,12 +47,6 @@ namespace const int GIT_PUSH_RETRIES = 3; - bool is_git_working_dir(const std::string& path) - { - std::error_code ec; - return fs::is_directory(path + "/.git", ec) && !ec; - } - bool is_valid_xml_file(const std::string& filename) { std::shared_ptr reader(xmlReaderForFile(filename.c_str(), NULL, 0), &xmlFreeTextReader); @@ -256,8 +250,7 @@ Repository::Repository(const std::string& path) : repo_auto_sync_(true) , include_idb_(false) { - // check git working directory before creating repo - const bool repo_already_exists = is_git_working_dir(path); + const bool repo_already_exists = is_git_directory(path); git_ = MakeGit(path); if(!git_) @@ -273,10 +266,10 @@ Repository::Repository(const std::string& path) LOG(DEBUG, "Repo opened\n"); return; } - LOG(INFO, "Repo created\n"); include_idb_ = ask_for_idb_tracking(); LOG(INFO, "%s %s\n", include_idb_ ? "tracking" : "ignoring", get_original_idb_name().data()); + LOG(INFO, "Repo created\n"); // add .gitignore to repo const auto gitignore = fs::path(get_current_idb_path()).replace_filename(".gitignore"); diff --git a/YaLibs/YaToolsLib/Git.cpp b/YaLibs/YaToolsLib/Git.cpp index d5199b58..9c963fe3 100644 --- a/YaLibs/YaToolsLib/Git.cpp +++ b/YaLibs/YaToolsLib/Git.cpp @@ -140,14 +140,15 @@ namespace std::shared_ptr init(const std::string& path, Git::ECloneMode emode) { - const auto fullpath = fs::canonical(fs::absolute(path)); + const auto fullpath = fs::absolute(path); git_repository* ptr_repo = nullptr; auto err = git_repository_init(&ptr_repo, fullpath.generic_string().data(), emode == Git::CLONE_BARE); if(err != GIT_OK) - FAIL_WITH(std::nullptr_t(), "unable to initialize %srepository at %s", emode == Git::CLONE_BARE ? "bare " : "", fullpath.generic_string().data()); + err = git_repository_open(&ptr_repo, fullpath.string().data()); + if(err != GIT_OK) + FAIL_WITH(std::nullptr_t(), "unable to open git repository at %s", fullpath.generic_string().data()); - auto repo = make_unique(ptr_repo); - return std::make_shared(path, std::move(repo)); + return std::make_shared(path, std::move(make_unique(ptr_repo))); } } @@ -161,6 +162,15 @@ std::shared_ptr MakeGitBare(const std::string& path) return init(path, Git::CLONE_BARE); } +bool is_git_directory(const std::string& path) +{ + const auto fullpath = fs::absolute(path); + git_repository* ptr_repo = nullptr; + const auto err = git_repository_open(&ptr_repo, fullpath.generic_string().data()); + const auto repo = make_unique(ptr_repo); + return err == GIT_OK; +} + Git::Git(const std::string& path, std::unique_ptr&& repo) : path_(path) , repo_(std::move(repo)) diff --git a/YaLibs/YaToolsLib/Git.hpp b/YaLibs/YaToolsLib/Git.hpp index b8c2f384..dac3bbea 100644 --- a/YaLibs/YaToolsLib/Git.hpp +++ b/YaLibs/YaToolsLib/Git.hpp @@ -65,5 +65,6 @@ struct IGit std::shared_ptr MakeGit (const std::string& path); std::shared_ptr MakeGitBare (const std::string& path); +bool is_git_directory(const std::string& path); std::string diff_strings (const const_string_ref& left, const char* leftname, const const_string_ref& right, const char* rightname); std::string merge_strings(const const_string_ref& left, const char* leftname, const const_string_ref& right, const char* rightname); \ No newline at end of file diff --git a/tests/tests/test_git.py b/tests/tests/test_git.py index e42576c1..fcd9e370 100644 --- a/tests/tests/test_git.py +++ b/tests/tests/test_git.py @@ -37,3 +37,38 @@ def test_invalid_git(self): a.run( self.script("idc.AddEnum(-1, 'name', idaapi.hexflag())"), ) + + def test_git_submodule(self): + a, b = self.setup_repos() + + # setup git repo 'd' containing submodule 'a' at path 'modules/z' + d = os.path.abspath(os.path.join(a.path, "..", "d")) + os.makedirs(os.path.join(d, "modules")) + runtests.sysexec(d, ["git", "init"]) + with open(os.path.join(d, "modules", ".gitignore"), "wb") as fh: + fh.write("dummy file") + runtests.sysexec(d, ["git", "add", "-A"]) + runtests.sysexec(d, ["git", "commit", "-m", "init"]) + runtests.sysexec(d, ["git", "submodule", "add", "../c", "modules/z"]) + + # 'e' now contains our submodule + target = "Qt5Svgd.dll" + pe = os.path.abspath(os.path.join(d, "modules", "z")) + e = runtests.Repo(self, pe, target) + + # initialize YaCo + e.run_script(""" +import yaco_plugin +yaco_plugin.start() +""", target=target + ".i64") + + # check changes are properly propagated + e.run( + self.script("idaapi.add_enum(idaapi.BADADDR, 'name_a', idaapi.hexflag())"), + self.save_enum("name_a"), + ) + e.check_git(added=["enum"]) + + a.run( + self.check_enum("name_a"), + )