Clarify BuildInfo::version's purpose. (#1261)

* Add test case for the recording head version feature noted in https://github.com/microsoft/vcpkg-tool/pull/1259#discussion_r1378120355

* Sanitize detected head versions to make sure they are at least version-strings.
This commit is contained in:
Billy O'Neal 2023-11-03 16:06:51 -07:00 коммит произвёл GitHub
Родитель 1192e9f019
Коммит 82a7c96db2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 146 добавлений и 3 удалений

Просмотреть файл

@ -0,0 +1,4 @@
set(VCPKG_POLICY_EMPTY_PACKAGE enabled)
if (VCPKG_USE_HEAD_VERSION)
set(VCPKG_HEAD_VERSION "detected-head")
endif()

Просмотреть файл

@ -0,0 +1,4 @@
{
"name": "set-detected-head-version",
"version": "1.0.0"
}

Просмотреть файл

@ -1,9 +1,28 @@
. $PSScriptRoot/../end-to-end-tests-prelude.ps1
# Not a number
Refresh-TestRoot
$out = Run-VcpkgAndCaptureOutput @commonArgs install classic-versions-b
Throw-IfNotFailed
if ($out -notmatch ".*warning:.*dependency classic-versions-a.*at least version 2.*is currently 1.*")
{
throw "Expected to fail and print warning about mismatched versions"
}
Refresh-TestRoot
Run-Vcpkg @commonArgs install set-detected-head-version
Throw-IfFailed
$listResults = Run-VcpkgAndCaptureOutput @commonArgs list
if (-Not ($listResults.Trim() -match "set-detected-head-version:[\S]+[\s]+1.0.0"))
{
throw "Expected list to list the declared version"
}
Refresh-TestRoot
Run-Vcpkg @commonArgs install set-detected-head-version --head
Throw-IfFailed
$listResults = Run-VcpkgAndCaptureOutput @commonArgs list
if (-Not ($listResults.Trim() -match "set-detected-head-version:[\S]+[\s]+detected-head"))
{
throw "Expected list to list the detected version"
}

Просмотреть файл

@ -230,7 +230,7 @@ namespace vcpkg
LinkageType crt_linkage = LinkageType::DYNAMIC;
LinkageType library_linkage = LinkageType::DYNAMIC;
Optional<std::string> version;
Optional<std::string> detected_head_version;
BuildPolicies policies;
};

Просмотреть файл

@ -171,6 +171,9 @@ namespace vcpkg
bool try_extract_external_date_version(ParsedExternalVersion& out, StringView version);
// /(\d+)(\.\d+|$)(\.\d+)?.*/
bool try_extract_external_dot_version(ParsedExternalVersion& out, StringView version);
// remove as few characters as possible from `target` to make it a valid `version-string` [^#]+(#\d+)?, or empty
void sanitize_version_string(std::string& target);
}
VCPKG_FORMAT_WITH_TO_STRING(vcpkg::Version);

Просмотреть файл

@ -0,0 +1,50 @@
#include <vcpkg-test/util.h>
#include <vcpkg/versions.h>
#include <string>
using namespace vcpkg;
TEST_CASE ("sanitize", "[versions]")
{
std::string content;
sanitize_version_string(content);
CHECK(content.empty());
content = "some version text";
sanitize_version_string(content);
CHECK(content == "some version text");
content = "some version with missing number port version#";
sanitize_version_string(content);
CHECK(content == "some version with missing number port version");
content = "some version with port version#1";
sanitize_version_string(content);
CHECK(content == "some version with port version#1");
content = "some version with bad version # hashes";
sanitize_version_string(content);
CHECK(content == "some version with bad version hashes");
content = "some version with bad version # hashes#1";
sanitize_version_string(content);
CHECK(content == "some version with bad version hashes#1");
content = "1";
sanitize_version_string(content);
CHECK(content == "1");
content = "1234";
sanitize_version_string(content);
CHECK(content == "1234");
content = "#1234";
sanitize_version_string(content);
CHECK(content == "1234");
content = "#1234#1234";
sanitize_version_string(content);
CHECK(content == "1234#1234");
}

Просмотреть файл

@ -617,7 +617,7 @@ namespace vcpkg
action.spec.triplet(),
action.public_abi(),
fspecs_to_pspecs(find_itr->second));
if (const auto p_ver = build_info.version.get())
if (const auto p_ver = build_info.detected_head_version.get())
{
bpgh.version = *p_ver;
}
@ -1661,7 +1661,11 @@ namespace vcpkg
}
std::string version = parser.optional_field("Version");
if (!version.empty()) build_info.version = std::move(version);
if (!version.empty())
{
sanitize_version_string(version);
build_info.detected_head_version = std::move(version);
}
std::unordered_map<BuildPolicy, bool> policies;
for (const auto& policy : ALL_POLICIES)

Просмотреть файл

@ -539,4 +539,63 @@ namespace vcpkg
return true;
}
void sanitize_version_string(std::string& target)
{
// try to save a port-version, if any
const auto first = target.begin();
const auto last = target.end();
auto port_version_first = last; // given [^#]+(#\d+)?, points to the #
for (;;)
{
if (first == port_version_first)
{
// entire version number is digits
return;
}
auto prev = port_version_first;
--prev;
if (*prev == '#')
{
// found the port-version
if (prev == first)
{
// entire version looks like a port version; the string part of version-string can't be empty, so
// treat it as just the number
target.erase(first);
return;
}
if (port_version_first == last)
{
// version ends with just a #, remove it
}
else
{
port_version_first = prev;
}
break;
}
if (!ParserBase::is_ascii_digit(*prev))
{
// string does not end in a port-version
port_version_first = last;
break;
}
port_version_first = prev;
}
// remove any #s in the version
auto new_version_last = std::remove(first, port_version_first, '#');
// shift down the port-version part
if (new_version_last != port_version_first)
{
target.erase(std::copy(port_version_first, last, new_version_last), last);
}
}
}