From e05d570292bee2c06ab27790cad1d968c1945e52 Mon Sep 17 00:00:00 2001 From: nicole mazzuca Date: Mon, 14 Mar 2022 16:10:03 -0700 Subject: [PATCH] Billy CRs for version parsing --- include/vcpkg/tools.h | 3 +++ src/vcpkg-test/tools.cpp | 43 ++++++++++++++++++++++++++++++++++++++++ src/vcpkg/tools.cpp | 31 +++++++++++------------------ src/vcpkg/versions.cpp | 13 ++---------- 4 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 src/vcpkg-test/tools.cpp diff --git a/include/vcpkg/tools.h b/include/vcpkg/tools.h index c8a4e7a490..2966388d75 100644 --- a/include/vcpkg/tools.h +++ b/include/vcpkg/tools.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -44,5 +45,7 @@ namespace vcpkg virtual const std::string& get_tool_version(const VcpkgPaths& paths, StringView tool) const = 0; }; + Optional> parse_tool_version_string(StringView string_version); + std::unique_ptr get_tool_cache(RequireExactVersions abiToolVersionHandling); } diff --git a/src/vcpkg-test/tools.cpp b/src/vcpkg-test/tools.cpp new file mode 100644 index 0000000000..33798569f0 --- /dev/null +++ b/src/vcpkg-test/tools.cpp @@ -0,0 +1,43 @@ +#include + +#include + +#include + +using namespace vcpkg; + +TEST_CASE("parse_tool_version_string", "[tools]") +{ + auto result = parse_tool_version_string("1.2.3"); + REQUIRE(result.has_value()); + CHECK(*result.get() == std::array{1, 2, 3}); + + result = parse_tool_version_string("3.22.3"); + REQUIRE(result.has_value()); + CHECK(*result.get() == std::array{3, 22, 3}); + + result = parse_tool_version_string("4.65"); + REQUIRE(result.has_value()); + CHECK(*result.get() == std::array{4, 65, 0}); + + result = parse_tool_version_string(R"(cmake version 3.22.2 +CMake suite maintained and supported by Kitware (kitware.com/cmake).)"); + REQUIRE(result.has_value()); + CHECK(*result.get() == std::array{3, 22, 2}); + + result = parse_tool_version_string(R"(aria2 version 1.35.0 +Copyright (C) 2006, 2019 Tatsuhiro Tsujikawa)"); + REQUIRE(result.has_value()); + CHECK(*result.get() == std::array{1, 35, 0}); + + result = parse_tool_version_string(R"(git version 2.17.1.windows.2)"); + REQUIRE(result.has_value()); + CHECK(*result.get() == std::array{2, 17, 1}); + + result = parse_tool_version_string(R"(git version 2.17.windows.2)"); + REQUIRE(result.has_value()); + CHECK(*result.get() == std::array{2, 17, 0}); + + result = parse_tool_version_string("4"); + CHECK_FALSE(result.has_value()); +} diff --git a/src/vcpkg/tools.cpp b/src/vcpkg/tools.cpp index 84faca7bc0..2f93f5c13c 100644 --- a/src/vcpkg/tools.cpp +++ b/src/vcpkg/tools.cpp @@ -26,39 +26,32 @@ namespace vcpkg }; // /\d+\.\d+(\.\d+)?/ - static Optional> parse_version_string(StringView string_version) + Optional> parse_tool_version_string(StringView string_version) { using P = Parse::ParserBase; // first, find the beginning of the version auto first = string_version.begin(); - auto last = string_version.end(); + const auto last = string_version.end(); // we're looking for the first instance of `.` + ParsedExternalVersion parsed_version{}; for (;;) { first = std::find_if(first, last, P::is_ascii_digit); - auto end_of_field = std::find_if_not(first, last, P::is_ascii_digit); - if (end_of_field == last) + if (first == last) { - break; + return nullopt; } - if (*end_of_field == '.') + + if (try_parse_external_dot_version(parsed_version, StringView{first, last}) && !parsed_version.minor.empty()) { - ++end_of_field; - if (end_of_field != last && P::is_ascii_digit(*end_of_field)) - { - break; - } + break; } - first = end_of_field; - } - ParsedExternalVersion parsed_version; - if (!try_parse_external_dot_version(parsed_version, StringView{first, last})) - { - return {}; + first = std::find_if_not(first, last, P::is_ascii_digit); } + parsed_version.normalize(); std::string buffer; @@ -144,7 +137,7 @@ namespace vcpkg const std::string sha512 = Strings::find_exactly_one_enclosed(tool_data, "", "").to_string(); auto archive_name = Strings::find_at_most_one_enclosed(tool_data, "", ""); - const Optional> version = parse_version_string(version_as_string); + const Optional> version = parse_tool_version_string(version_as_string); Checks::check_exit(VCPKG_LINE_INFO, version.has_value(), "Could not parse version for tool %s. Version string was: %s", @@ -197,7 +190,7 @@ namespace vcpkg auto maybe_version = tool_provider.get_version(paths, candidate); const auto version = maybe_version.get(); if (!version) continue; - const auto parsed_version = parse_version_string(*version); + const auto parsed_version = parse_tool_version_string(*version); if (!parsed_version) continue; auto& actual_version = *parsed_version.get(); if (!accept_version(actual_version)) continue; diff --git a/src/vcpkg/versions.cpp b/src/vcpkg/versions.cpp index 251716de15..a85e21b703 100644 --- a/src/vcpkg/versions.cpp +++ b/src/vcpkg/versions.cpp @@ -469,8 +469,6 @@ namespace vcpkg out.major = out.minor = out.patch = StringView{}; - if (first == last) return false; - if (*first == 'v') ++first; if (first == last) return false; auto major_last = std::find_if_not(first, last, P::is_ascii_digit); @@ -485,22 +483,15 @@ namespace vcpkg } auto minor_last = std::find_if_not(major_last + 1, last, P::is_ascii_digit); - if (minor_last == major_last + 1) - { - return false; - } out.minor = StringView{major_last + 1, minor_last}; - if (minor_last == last || *minor_last != '.') + if (minor_last == last || minor_last == major_last + 1 || *minor_last != '.') { return true; } auto patch_last = std::find_if_not(minor_last + 1, last, P::is_ascii_digit); - if (minor_last == major_last + 1) - { - return false; - } out.patch = StringView{minor_last + 1, patch_last}; + return true; } }