diff options
| author | Alexander Karatarakis <alkarata@microsoft.com> | 2018-02-23 18:15:26 -0800 |
|---|---|---|
| committer | Alexander Karatarakis <alkarata@microsoft.com> | 2018-02-23 18:19:04 -0800 |
| commit | 7f5efbe14419412d8c24df836a0b3b5192661aa3 (patch) | |
| tree | 2fff51aad17b5e286039dbe095a1cd70e4cba82f | |
| parent | 407767858336479eebe759404db689a9b1e16671 (diff) | |
| download | vcpkg-7f5efbe14419412d8c24df836a0b3b5192661aa3.tar.gz vcpkg-7f5efbe14419412d8c24df836a0b3b5192661aa3.zip | |
[vcpkgTools.xml] Reuse in vcpkg.exe
| -rw-r--r-- | toolsrc/src/vcpkg/vcpkgpaths.cpp | 171 |
1 files changed, 113 insertions, 58 deletions
diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 8ec7ba4cc..bf231cecd 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -15,35 +15,99 @@ namespace vcpkg static constexpr CStringView V_140 = "v140"; static constexpr CStringView V_141 = "v141"; - static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, - const std::array<int, 3>& expected_version) + struct ToolData { - static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###"); + std::array<int, 3> required_version; + fs::path downloaded_exe_path; + }; - const auto rc = System::cmd_execute_and_capture_output(Strings::format(R"(%s)", version_cmd)); - if (rc.exit_code != 0) - { - return false; - } + static Optional<std::array<int, 3>> parse_version_string(const std::string& version_as_string) + { + static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###"); std::match_results<std::string::const_iterator> match; - const auto found = std::regex_search(rc.output, match, RE); + const auto found = std::regex_search(version_as_string, match, RE); if (!found) { - return false; + return {}; } const int d1 = atoi(match[1].str().c_str()); const int d2 = atoi(match[2].str().c_str()); const int d3 = atoi(match[3].str().c_str()); - if (d1 > expected_version[0] || (d1 == expected_version[0] && d2 > expected_version[1]) || - (d1 == expected_version[0] && d2 == expected_version[1] && d3 >= expected_version[2])) + const std::array<int, 3> result = {d1, d2, d3}; + return result; + } + + static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool) + { + static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; + + const auto get_string_inside_tags = + [](const std::string& input, const std::regex& regex, const std::string& tag_name) -> std::string { + std::smatch match; + const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); + Checks::check_exit( + VCPKG_LINE_INFO, has_match, "Could not find tag <%s> in %s", tag_name, XML_PATH.generic_string()); + + return match[1]; + }; + + static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO); + static const std::regex VERSION_REGEX{ + Strings::format(R"###(<requiredVersion>([\s\S]*?)</requiredVersion>)###", tool)}; + static const std::regex EXE_RELATIVE_PATH_REGEX{ + Strings::format(R"###(<exeRelativePath>([\s\S]*?)</exeRelativePath>)###", tool)}; + + const std::regex tool_regex{Strings::format(R"###(<tool[\s]+name="%s">([\s\S]*?)</tool>)###", tool)}; + + std::smatch match_tool; + const bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); + Checks::check_exit(VCPKG_LINE_INFO, + has_match_tool, + "Could not find entry for tool [%s] in %s", + tool, + XML_PATH.generic_string()); + + const std::string tool_data_as_string = get_string_inside_tags(XML, tool_regex, tool); + + const std::string required_version_as_string = + get_string_inside_tags(tool_data_as_string, VERSION_REGEX, "requiredVersion"); + + const std::string exe_relative_path = + get_string_inside_tags(tool_data_as_string, EXE_RELATIVE_PATH_REGEX, "exeRelativePath"); + + const Optional<std::array<int, 3>> required_version = parse_version_string(required_version_as_string); + Checks::check_exit(VCPKG_LINE_INFO, + required_version.has_value(), + "Could not parse version for tool %s. Version string was: %s", + tool, + required_version_as_string); + + const fs::path exe_path = paths.downloads / exe_relative_path; + return ToolData{*required_version.get(), exe_path}; + } + + static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, + const std::array<int, 3>& expected_version) + { + const auto rc = System::cmd_execute_and_capture_output(Strings::format(R"(%s)", version_cmd)); + if (rc.exit_code != 0) + { + return false; + } + + const Optional<std::array<int, 3>> v = parse_version_string(rc.output); + if (!v.has_value()) { - // satisfactory version found - return true; + return false; } - return false; + const std::array<int, 3> actual_version = *v.get(); + return (actual_version[0] > expected_version[0] || + (actual_version[0] == expected_version[0] && actual_version[1] > expected_version[1]) || + (actual_version[0] == expected_version[0] && actual_version[1] == expected_version[1] && + actual_version[2] >= expected_version[2])); } static Optional<fs::path> find_if_has_equal_or_greater_version(const std::vector<fs::path>& candidate_paths, @@ -80,11 +144,10 @@ namespace vcpkg return data_lines; } - static fs::path fetch_tool(const fs::path& scripts_folder, - const std::string& tool_name, - const fs::path& expected_downloaded_path, - const std::array<int, 3>& version) + static fs::path fetch_tool(const fs::path& scripts_folder, const std::string& tool_name, const ToolData& tool_data) { + const std::array<int, 3>& version = tool_data.required_version; + const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", tool_name, @@ -101,6 +164,7 @@ namespace vcpkg Checks::check_exit(VCPKG_LINE_INFO, tool_path.size() == 1, "Expected tool path, but got %s", output); const fs::path actual_downloaded_path = Strings::trim(std::string{tool_path.at(0)}); + const fs::path& expected_downloaded_path = tool_data.downloaded_exe_path; std::error_code ec; const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); Checks::check_exit(VCPKG_LINE_INFO, @@ -111,22 +175,20 @@ namespace vcpkg return actual_downloaded_path; } - static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + static fs::path get_cmake_path(const VcpkgPaths& paths) { #if defined(_WIN32) - static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 10, 2}; + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "cmake"); #else - static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 5, 1}; + static const ToolData TOOL_DATA = ToolData{{3, 5, 1}, ""}; #endif static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - const std::vector<fs::path> from_path = Files::find_from_PATH("cmake"); - std::vector<fs::path> candidate_paths; - const fs::path downloaded_copy = downloads_folder / "cmake-3.10.2-win32-x86" / "bin" / "cmake.exe"; #if defined(_WIN32) - candidate_paths.push_back(downloaded_copy); + candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); #endif + const std::vector<fs::path> from_path = Files::find_from_PATH("cmake"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); #if defined(_WIN32) candidate_paths.push_back(System::get_program_files_platform_bitness() / "CMake" / "bin" / "cmake.exe"); @@ -134,51 +196,47 @@ namespace vcpkg #endif const Optional<fs::path> path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); if (const auto p = path.get()) { return *p; } - return fetch_tool(scripts_folder, "cmake", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(paths.scripts, "cmake", TOOL_DATA); } - fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + static fs::path get_nuget_path(const VcpkgPaths& paths) { - static constexpr std::array<int, 3> EXPECTED_VERSION = {4, 4, 0}; - - const fs::path downloaded_copy = downloads_folder / "nuget-4.4.0" / "nuget.exe"; - const std::vector<fs::path> from_path = Files::find_from_PATH("nuget"); + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "nuget"); std::vector<fs::path> candidate_paths; - candidate_paths.push_back(downloaded_copy); + candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); + const std::vector<fs::path> from_path = Files::find_from_PATH("nuget"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - auto path = find_if_has_equal_or_greater_version(candidate_paths, "", EXPECTED_VERSION); + auto path = find_if_has_equal_or_greater_version(candidate_paths, "", TOOL_DATA.required_version); if (const auto p = path.get()) { return *p; } - return fetch_tool(scripts_folder, "nuget", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(paths.scripts, "nuget", TOOL_DATA); } - fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + static fs::path get_git_path(const VcpkgPaths& paths) { #if defined(_WIN32) - static constexpr std::array<int, 3> EXPECTED_VERSION = {2, 16, 2}; + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "git"); #else - static constexpr std::array<int, 3> EXPECTED_VERSION = {2, 7, 4}; + static const ToolData TOOL_DATA = ToolData{{2, 7, 4}, ""}; #endif static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - const std::vector<fs::path> from_path = Files::find_from_PATH("git"); - - const fs::path downloaded_copy = downloads_folder / "MinGit-2.16.2-32-bit" / "cmd" / "git.exe"; std::vector<fs::path> candidate_paths; #if defined(_WIN32) - candidate_paths.push_back(downloaded_copy); + candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); #endif + const std::vector<fs::path> from_path = Files::find_from_PATH("git"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); #if defined(_WIN32) candidate_paths.push_back(System::get_program_files_platform_bitness() / "git" / "cmd" / "git.exe"); @@ -186,25 +244,23 @@ namespace vcpkg #endif const Optional<fs::path> path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); if (const auto p = path.get()) { return *p; } - return fetch_tool(scripts_folder, "git", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(paths.scripts, "git", TOOL_DATA); } - static fs::path get_ifw_installerbase_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + static fs::path get_ifw_installerbase_path(const VcpkgPaths& paths) { - static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 1, 81}; - static const std::string VERSION_CHECK_ARGUMENTS = "--framework-version"; + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "installerbase"); - const fs::path downloaded_copy = - downloads_folder / "QtInstallerFramework-win-x86" / "bin" / "installerbase.exe"; + static const std::string VERSION_CHECK_ARGUMENTS = "--framework-version"; std::vector<fs::path> candidate_paths; - candidate_paths.push_back(downloaded_copy); + candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); // TODO: Uncomment later // const std::vector<fs::path> from_path = Files::find_from_PATH("installerbase"); // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); @@ -214,13 +270,13 @@ namespace vcpkg // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); const Optional<fs::path> path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); if (const auto p = path.get()) { return *p; } - return fetch_tool(scripts_folder, "installerbase", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(paths.scripts, "installerbase", TOOL_DATA); } Expected<VcpkgPaths> VcpkgPaths::create(const fs::path& vcpkg_root_dir) @@ -299,23 +355,22 @@ namespace vcpkg const fs::path& VcpkgPaths::get_cmake_exe() const { - return this->cmake_exe.get_lazy([this]() { return get_cmake_path(this->downloads, this->scripts); }); + return this->cmake_exe.get_lazy([this]() { return get_cmake_path(*this); }); } const fs::path& VcpkgPaths::get_git_exe() const { - return this->git_exe.get_lazy([this]() { return get_git_path(this->downloads, this->scripts); }); + return this->git_exe.get_lazy([this]() { return get_git_path(*this); }); } const fs::path& VcpkgPaths::get_nuget_exe() const { - return this->nuget_exe.get_lazy([this]() { return get_nuget_path(this->downloads, this->scripts); }); + return this->nuget_exe.get_lazy([this]() { return get_nuget_path(*this); }); } const fs::path& VcpkgPaths::get_ifw_installerbase_exe() const { - return this->ifw_installerbase_exe.get_lazy( - [this]() { return get_ifw_installerbase_path(this->downloads, this->scripts); }); + return this->ifw_installerbase_exe.get_lazy([this]() { return get_ifw_installerbase_path(*this); }); } const fs::path& VcpkgPaths::get_ifw_binarycreator_exe() const |
