get_versions should return all versions so the best match can be found (#4945)

* get_versions should return all versions so the best match can be found

* [vcpkg] Consider more than one path when searching for system binaries
This commit is contained in:
Łukasz Mendakiewicz 2018-12-17 16:15:15 -08:00 committed by Robert Schumacher
parent fcde2e64eb
commit 9cbdb33caf
2 changed files with 237 additions and 274 deletions

View File

@ -8,7 +8,11 @@ namespace vcpkg::Archives
void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path)
{
Files::Filesystem& fs = paths.get_filesystem();
const fs::path to_path_partial = to_path.u8string() + ".partial";
const fs::path to_path_partial = to_path.u8string() + ".partial"
#if defined(_WIN32)
+ "." + std::to_string(GetCurrentProcessId())
#endif
;
std::error_code ec;
fs.remove_all(to_path, ec);

View File

@ -44,7 +44,7 @@ namespace vcpkg
return result;
}
static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool)
static ExpectedT<ToolData, std::string> parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool)
{
#if defined(_WIN32)
static constexpr StringLiteral OS_STRING = "windows";
@ -53,13 +53,13 @@ namespace vcpkg
#elif defined(__linux__)
static constexpr StringLiteral OS_STRING = "linux";
#else
return ToolData{};
return std::string("operating system is unknown");
#endif
#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__)
static const std::string XML_VERSION = "2";
static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml";
static const std::regex XML_VERSION_REGEX{R"###(<tools[\s]+version="([^"]+)">)###"};
static const std::regex XML_VERSION_REGEX {R"###(<tools[\s]+version="([^"]+)">)###"};
static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO);
std::smatch match_xml_version;
const bool has_xml_version = std::regex_search(XML.cbegin(), XML.cend(), match_xml_version, XML_VERSION_REGEX);
@ -67,22 +67,22 @@ namespace vcpkg
has_xml_version,
R"(Could not find <tools version="%s"> in %s)",
XML_VERSION,
XML_PATH.generic_string());
XML_PATH.u8string());
Checks::check_exit(VCPKG_LINE_INFO,
XML_VERSION == match_xml_version[1],
"Expected %s version: [%s], but was [%s]. Please re-run bootstrap-vcpkg.",
XML_PATH.generic_string(),
XML_PATH.u8string(),
XML_VERSION,
match_xml_version[1]);
const std::regex tool_regex{Strings::format(R"###(<tool[\s]+name="%s"[\s]+os="%s">)###", tool, OS_STRING)};
const std::regex tool_regex {Strings::format(R"###(<tool[\s]+name="%s"[\s]+os="%s">)###", tool, OS_STRING)};
std::smatch match_tool_entry;
const bool has_tool_entry = std::regex_search(XML.cbegin(), XML.cend(), match_tool_entry, tool_regex);
Checks::check_exit(VCPKG_LINE_INFO,
has_tool_entry,
"Could not find entry for tool [%s] in %s",
tool,
XML_PATH.generic_string());
if (!has_tool_entry)
{
return Strings::format(
"Could not find entry for tool %s in %s for os=%s", tool, XML_PATH.u8string(), OS_STRING);
}
const std::string tool_data =
StringRange::find_exactly_one_enclosed(XML, match_tool_entry[0], "</tool>").to_string();
@ -106,13 +106,13 @@ namespace vcpkg
const fs::path tool_dir_path = paths.tools / tool_dir_name;
const fs::path exe_path = tool_dir_path / exe_relative_path;
return ToolData{*version.get(),
exe_path,
url,
paths.downloads / archive_name.value_or(exe_relative_path).to_string(),
archive_name.has_value(),
tool_dir_path,
sha512};
return ToolData {*version.get(),
exe_path,
url,
paths.downloads / archive_name.value_or(exe_relative_path).to_string(),
archive_name.has_value(),
tool_dir_path,
sha512};
#endif
}
@ -122,55 +122,43 @@ namespace vcpkg
std::string version;
};
static Optional<PathAndVersion> find_first_with_sufficient_version(const std::vector<PathAndVersion>& candidates,
struct ToolProvider
{
virtual const std::string& tool_data_name() const = 0;
virtual const std::string& exe_stem() const = 0;
virtual std::array<int, 3> default_min_version() const = 0;
virtual void add_special_paths(std::vector<fs::path>& out_candidate_paths) const {}
virtual Optional<std::string> get_version(const fs::path& path_to_exe) const = 0;
};
static Optional<PathAndVersion> find_first_with_sufficient_version(const Files::Filesystem& fs,
const ToolProvider& tool_provider,
const std::vector<fs::path>& candidates,
const std::array<int, 3>& expected_version)
{
const auto it = Util::find_if(candidates, [&](const PathAndVersion& candidate) {
const auto parsed_version = parse_version_string(candidate.version);
if (!parsed_version.has_value())
{
return false;
}
const std::array<int, 3> actual_version = *parsed_version.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]);
});
if (it == candidates.cend())
for (auto&& candidate : candidates)
{
return nullopt;
if (!fs.exists(candidate)) continue;
auto maybe_version = tool_provider.get_version(candidate);
const auto version = maybe_version.get();
if (!version) continue;
const auto parsed_version = parse_version_string(*version);
if (!parsed_version) continue;
auto& actual_version = *parsed_version.get();
const auto version_acceptable =
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]);
if (!version_acceptable) continue;
return PathAndVersion {candidate, *version};
}
return *it;
return nullopt;
}
struct VersionProvider
{
virtual Optional<std::string> get_version(const fs::path& path_to_exe) const = 0;
std::vector<PathAndVersion> get_versions(const std::vector<fs::path>& candidate_paths) const
{
auto&& fs = Files::get_real_filesystem();
std::vector<PathAndVersion> output;
for (auto&& p : candidate_paths)
{
if (!fs.exists(p)) continue;
auto maybe_version = this->get_version(p);
if (const auto version = maybe_version.get())
{
output.emplace_back(PathAndVersion{p, *version});
return output;
}
}
return output;
}
};
static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data)
{
const std::array<int, 3>& version = tool_data.version;
@ -220,76 +208,90 @@ namespace vcpkg
}
static PathAndVersion fetch_tool(const VcpkgPaths& paths,
const std::string& tool_name,
const ToolData& tool_data,
const VersionProvider& version_provider)
const ToolProvider& tool_provider,
const ToolData& tool_data)
{
const auto downloaded_path = fetch_tool(paths, tool_name, tool_data);
const auto downloaded_version = version_provider.get_version(downloaded_path).value_or_exit(VCPKG_LINE_INFO);
const auto downloaded_path = fetch_tool(paths, tool_provider.tool_data_name(), tool_data);
const auto downloaded_version = tool_provider.get_version(downloaded_path).value_or_exit(VCPKG_LINE_INFO);
return {downloaded_path, downloaded_version};
}
namespace CMake
static PathAndVersion get_path(const VcpkgPaths& paths, const ToolProvider& tool)
{
struct CmakeVersionProvider : VersionProvider
auto& fs = paths.get_filesystem();
std::array<int, 3> min_version = tool.default_min_version();
std::vector<fs::path> candidate_paths;
auto maybe_tool_data = parse_tool_data_from_xml(paths, tool.tool_data_name());
if (auto tool_data = maybe_tool_data.get())
{
Optional<std::string> get_version(const fs::path& path_to_exe) const override
{
const std::string cmd = Strings::format(R"("%s" --version)", path_to_exe.u8string());
const auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
return nullopt;
}
candidate_paths.push_back(tool_data->exe_path);
min_version = tool_data->version;
}
/* Sample output:
cmake version 3.10.2
CMake suite maintained and supported by Kitware (kitware.com/cmake).
*/
return StringRange::find_exactly_one_enclosed(rc.output, "cmake version ", "\n").to_string();
}
};
static PathAndVersion get_path(const VcpkgPaths& paths)
auto& exe_stem = tool.exe_stem();
if (!exe_stem.empty())
{
if (System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
{
return {"cmake", "0"};
}
auto paths_from_path = fs.find_from_PATH(exe_stem);
candidate_paths.insert(candidate_paths.end(), paths_from_path.cbegin(), paths_from_path.cend());
}
std::vector<fs::path> candidate_paths;
#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__)
static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "cmake");
candidate_paths.push_back(TOOL_DATA.exe_path);
#else
static const ToolData TOOL_DATA = ToolData{{3, 5, 1}, ""};
#endif
const std::vector<fs::path> from_path = paths.get_filesystem().find_from_PATH("cmake");
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
tool.add_special_paths(candidate_paths);
const auto maybe_path = find_first_with_sufficient_version(fs, tool, candidate_paths, min_version);
if (const auto p = maybe_path.get())
{
return *p;
}
if (auto tool_data = maybe_tool_data.get())
{
return fetch_tool(paths, tool, *tool_data);
}
Checks::exit_with_message(VCPKG_LINE_INFO, maybe_tool_data.error());
}
struct CMakeProvider : ToolProvider
{
std::string m_exe = "cmake";
virtual const std::string& tool_data_name() const override { return m_exe; }
virtual const std::string& exe_stem() const override { return m_exe; }
virtual std::array<int, 3> default_min_version() const override { return {3, 5, 1}; }
virtual void add_special_paths(std::vector<fs::path>& out_candidate_paths) const override
{
#if defined(_WIN32)
const auto& program_files = System::get_program_files_platform_bitness();
if (const auto pf = program_files.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe");
if (const auto pf = program_files.get()) out_candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe");
const auto& program_files_32_bit = System::get_program_files_32_bit();
if (const auto pf = program_files_32_bit.get())
candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe");
const CmakeVersionProvider version_provider{};
const std::vector<PathAndVersion> candidates_with_versions = version_provider.get_versions(candidate_paths);
const auto maybe_path = find_first_with_sufficient_version(candidates_with_versions, TOOL_DATA.version);
if (const auto p = maybe_path.get())
out_candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe");
#endif
}
virtual Optional<std::string> get_version(const fs::path& path_to_exe) const override
{
const std::string cmd = Strings::format(R"("%s" --version)", path_to_exe.u8string());
const auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
return *p;
return nullopt;
}
return fetch_tool(paths, Tools::CMAKE, TOOL_DATA, version_provider);
/* Sample output:
cmake version 3.10.2
CMake suite maintained and supported by Kitware (kitware.com/cmake).
*/
return StringRange::find_exactly_one_enclosed(rc.output, "cmake version ", "\n").to_string();
}
}
};
static fs::path get_7za_path(const VcpkgPaths& paths)
{
#if defined(_WIN32)
static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "7zip");
static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "7zip").value_or_exit(VCPKG_LINE_INFO);
if (!paths.get_filesystem().exists(TOOL_DATA.exe_path))
{
return fetch_tool(paths, "7zip", TOOL_DATA);
@ -300,195 +302,131 @@ namespace vcpkg
#endif
}
namespace Ninja
struct NinjaProvider : ToolProvider
{
struct NinjaVersionProvider : VersionProvider
std::string m_exe = "ninja";
virtual const std::string& tool_data_name() const override { return m_exe; }
virtual const std::string& exe_stem() const override { return m_exe; }
virtual std::array<int, 3> default_min_version() const override { return {3, 5, 1}; }
virtual Optional<std::string> get_version(const fs::path& path_to_exe) const override
{
Optional<std::string> get_version(const fs::path& path_to_exe) const override
const std::string cmd = Strings::format(R"("%s" --version)", path_to_exe.u8string());
const auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
const std::string cmd = Strings::format(R"("%s" --version)", path_to_exe.u8string());
const auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
return nullopt;
}
/* Sample output:
1.8.2
*/
return rc.output;
}
};
static PathAndVersion get_path(const VcpkgPaths& paths)
{
if (System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
{
return {"ninja", "0"};
return nullopt;
}
static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "ninja");
std::vector<fs::path> candidate_paths;
candidate_paths.push_back(TOOL_DATA.exe_path);
const std::vector<fs::path> from_path = paths.get_filesystem().find_from_PATH("ninja");
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
const NinjaVersionProvider version_provider{};
const std::vector<PathAndVersion> candidates_with_versions = version_provider.get_versions(candidate_paths);
const auto maybe_path = find_first_with_sufficient_version(candidates_with_versions, TOOL_DATA.version);
if (const auto p = maybe_path.get())
{
return *p;
}
return fetch_tool(paths, Tools::NINJA, TOOL_DATA, version_provider);
/* Sample output:
1.8.2
*/
return rc.output;
}
}
};
namespace Nuget
struct NuGetProvider : ToolProvider
{
struct NugetVersionProvider : VersionProvider
std::string m_exe = "nuget";
virtual const std::string& tool_data_name() const override { return m_exe; }
virtual const std::string& exe_stem() const override { return m_exe; }
virtual std::array<int, 3> default_min_version() const override { return {4, 6, 2}; }
virtual Optional<std::string> get_version(const fs::path& path_to_exe) const override
{
Optional<std::string> get_version(const fs::path& path_to_exe) const override
const std::string cmd = Strings::format(R"("%s")", path_to_exe.u8string());
const auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
const std::string cmd = Strings::format(R"("%s")", path_to_exe.u8string());
const auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
return nullopt;
}
/* Sample output:
NuGet Version: 4.6.2.5055
usage: NuGet <command> [args] [options]
Type 'NuGet help <command>' for help on a specific command.
[[[List of available commands follows]]]
*/
return StringRange::find_exactly_one_enclosed(rc.output, "NuGet Version: ", "\n").to_string();
}
};
static PathAndVersion get_path(const VcpkgPaths& paths)
{
static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "nuget");
std::vector<fs::path> candidate_paths;
candidate_paths.push_back(TOOL_DATA.exe_path);
const std::vector<fs::path> from_path = paths.get_filesystem().find_from_PATH("nuget");
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
const NugetVersionProvider version_provider{};
const std::vector<PathAndVersion> candidates_with_versions = version_provider.get_versions(candidate_paths);
const auto maybe_path = find_first_with_sufficient_version(candidates_with_versions, TOOL_DATA.version);
if (const auto p = maybe_path.get())
{
return *p;
return nullopt;
}
return fetch_tool(paths, Tools::NUGET, TOOL_DATA, version_provider);
/* Sample output:
NuGet Version: 4.6.2.5055
usage: NuGet <command> [args] [options]
Type 'NuGet help <command>' for help on a specific command.
[[[List of available commands follows]]]
*/
return StringRange::find_exactly_one_enclosed(rc.output, "NuGet Version: ", "\n").to_string();
}
}
};
namespace Git
struct GitProvider : ToolProvider
{
struct GitVersionProvider : VersionProvider
std::string m_exe = "git";
virtual const std::string& tool_data_name() const override { return m_exe; }
virtual const std::string& exe_stem() const override { return m_exe; }
virtual std::array<int, 3> default_min_version() const override { return {2, 7, 4}; }
virtual void add_special_paths(std::vector<fs::path>& out_candidate_paths) const
{
Optional<std::string> get_version(const fs::path& path_to_exe) const override
{
const std::string cmd = Strings::format(R"("%s" --version)", path_to_exe.u8string());
const auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
return nullopt;
}
/* Sample output:
git version 2.17.1.windows.2
*/
const auto idx = rc.output.find("git version ");
Checks::check_exit(VCPKG_LINE_INFO,
idx != std::string::npos,
"Unexpected format of git version string: %s",
rc.output);
return rc.output.substr(idx);
}
};
static PathAndVersion get_path(const VcpkgPaths& paths)
{
static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "git");
std::vector<fs::path> candidate_paths;
#if defined(_WIN32)
candidate_paths.push_back(TOOL_DATA.exe_path);
#endif
const std::vector<fs::path> from_path = paths.get_filesystem().find_from_PATH("git");
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
const auto& program_files = System::get_program_files_platform_bitness();
if (const auto pf = program_files.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe");
if (const auto pf = program_files.get()) out_candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe");
const auto& program_files_32_bit = System::get_program_files_32_bit();
if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe");
const GitVersionProvider version_provider{};
const std::vector<PathAndVersion> candidates_with_versions = version_provider.get_versions(candidate_paths);
const auto maybe_path = find_first_with_sufficient_version(candidates_with_versions, TOOL_DATA.version);
if (const auto p = maybe_path.get())
{
return *p;
}
return fetch_tool(paths, Tools::GIT, TOOL_DATA, version_provider);
if (const auto pf = program_files_32_bit.get())
out_candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe");
#endif
}
}
namespace IfwInstallerBase
{
struct IfwInstallerBaseVersionProvider : VersionProvider
virtual Optional<std::string> get_version(const fs::path& path_to_exe) const override
{
Optional<std::string> get_version(const fs::path& path_to_exe) const override
const std::string cmd = Strings::format(R"("%s" --version)", path_to_exe.u8string());
const auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
const std::string cmd = Strings::format(R"("%s" --framework-version)", path_to_exe.u8string());
const auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
return nullopt;
}
/* Sample output:
3.1.81
*/
return rc.output;
return nullopt;
}
};
static PathAndVersion get_path(const VcpkgPaths& paths)
/* Sample output:
git version 2.17.1.windows.2
*/
const auto idx = rc.output.find("git version ");
Checks::check_exit(
VCPKG_LINE_INFO, idx != std::string::npos, "Unexpected format of git version string: %s", rc.output);
return rc.output.substr(idx);
}
};
struct IfwInstallerBaseProvider : ToolProvider
{
std::string m_exe = "";
std::string m_toolname = "installerbase";
virtual const std::string& tool_data_name() const override { return m_toolname; }
virtual const std::string& exe_stem() const override { return m_exe; }
virtual std::array<int, 3> default_min_version() const override { return {0, 0, 0}; }
virtual void add_special_paths(std::vector<fs::path>& out_candidate_paths) const
{
static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "installerbase");
std::vector<fs::path> candidate_paths;
candidate_paths.push_back(TOOL_DATA.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());
// candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" /
// "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe");
// candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" /
// "QtIFW-3.1.0" / "bin" / "installerbase.exe");
// candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) /
// "Qt" / "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe");
// candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) /
// "Qt" / "QtIFW-3.1.0" / "bin" / "installerbase.exe");
}
const IfwInstallerBaseVersionProvider version_provider{};
const std::vector<PathAndVersion> candidates_with_versions = version_provider.get_versions(candidate_paths);
const auto maybe_path = find_first_with_sufficient_version(candidates_with_versions, TOOL_DATA.version);
if (const auto p = maybe_path.get())
virtual Optional<std::string> get_version(const fs::path& path_to_exe) const override
{
const std::string cmd = Strings::format(R"("%s" --framework-version)", path_to_exe.u8string());
const auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
return *p;
return nullopt;
}
return fetch_tool(paths, Tools::IFW_INSTALLER_BASE, TOOL_DATA, version_provider);
/* Sample output:
3.1.81
*/
return rc.output;
}
}
};
struct ToolCacheImpl final : ToolCache
{
@ -506,12 +444,12 @@ namespace vcpkg
tool == Tools::IFW_INSTALLER_BASE)
return get_tool_pathversion(paths, tool).path;
if (tool == Tools::IFW_BINARYCREATOR)
return IfwInstallerBase::get_path(paths).path.parent_path() / "binarycreator.exe";
return get_tool_path(paths, Tools::IFW_INSTALLER_BASE).parent_path() / "binarycreator.exe";
if (tool == Tools::IFW_REPOGEN)
return IfwInstallerBase::get_path(paths).path.parent_path() / "repogen.exe";
return get_tool_path(paths, Tools::IFW_INSTALLER_BASE).parent_path() / "repogen.exe";
// For other tools, we simply always auto-download them.
const ToolData tool_data = parse_tool_data_from_xml(paths, tool);
const ToolData tool_data = parse_tool_data_from_xml(paths, tool).value_or_exit(VCPKG_LINE_INFO);
if (paths.get_filesystem().exists(tool_data.exe_path))
{
return tool_data.exe_path;
@ -522,12 +460,33 @@ namespace vcpkg
const PathAndVersion& get_tool_pathversion(const VcpkgPaths& paths, const std::string& tool) const
{
return path_version_cache.get_lazy(tool, [&]() {
if (tool == Tools::CMAKE) return CMake::get_path(paths);
if (tool == Tools::GIT) return Git::get_path(paths);
if (tool == Tools::NINJA) return Ninja::get_path(paths);
if (tool == Tools::NUGET) return Nuget::get_path(paths);
if (tool == Tools::IFW_INSTALLER_BASE) return IfwInstallerBase::get_path(paths);
return path_version_cache.get_lazy(tool, [&]() -> PathAndVersion {
if (tool == Tools::CMAKE)
{
if (System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
{
return {"cmake", "0"};
}
return get_path(paths, CMakeProvider());
}
if (tool == Tools::GIT)
{
if (System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
{
return {"git", "0"};
}
return get_path(paths, GitProvider());
}
if (tool == Tools::NINJA)
{
if (System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
{
return {"ninja", "0"};
}
return get_path(paths, NinjaProvider());
}
if (tool == Tools::NUGET) return get_path(paths, NuGetProvider());
if (tool == Tools::IFW_INSTALLER_BASE) return get_path(paths, IfwInstallerBaseProvider());
Checks::exit_with_message(VCPKG_LINE_INFO, "Finding version for %s is not implemented yet.", tool);
});