diff --git a/azure-pipelines/Format-CxxCode.ps1 b/azure-pipelines/Format-CxxCode.ps1 index 8826699aa4..2041ef0580 100755 --- a/azure-pipelines/Format-CxxCode.ps1 +++ b/azure-pipelines/Format-CxxCode.ps1 @@ -16,6 +16,10 @@ if ($null -ne $clangFormat) if ($IsWindows) { + if ([String]::IsNullOrEmpty($clangFormat) -or -not (Test-Path $clangFormat)) + { + $clangFormat = 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\x64\bin\clang-format.exe' + } if ([String]::IsNullOrEmpty($clangFormat) -or -not (Test-Path $clangFormat)) { $clangFormat = 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\Llvm\x64\bin\clang-format.exe' diff --git a/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg-configuration.json b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg-configuration.json new file mode 100644 index 0000000000..7122b60c21 --- /dev/null +++ b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg-configuration.json @@ -0,0 +1,13 @@ +{ + "default-registry": null, + "registries": [ + { + "kind": "filesystem", + "path": "./vcpkg_registry", + "packages": [ + "arrow", + "bloom-filter" + ] + } + ] +} diff --git a/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg.json b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg.json new file mode 100644 index 0000000000..34622305c2 --- /dev/null +++ b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg.json @@ -0,0 +1,15 @@ +{ + "name": "cycle-detected", + "version": "0.1.0", + "dependencies": [ + "arrow", + "bloom-filter" + ], + "overrides": [ + { + "name": "arrow", + "version": "6.0.0.20210925", + "port-version": 4 + } + ] +} diff --git a/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/arrow/portfile.cmake b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/arrow/portfile.cmake new file mode 100644 index 0000000000..d11c69f812 --- /dev/null +++ b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/arrow/portfile.cmake @@ -0,0 +1 @@ +// intentionally empty diff --git a/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/arrow/vcpkg.json b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/arrow/vcpkg.json new file mode 100644 index 0000000000..b8a79d3847 --- /dev/null +++ b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/arrow/vcpkg.json @@ -0,0 +1,5 @@ +{ + "name": "arrow", + "version": "6.0.0.20210925", + "description": "Cross-language development platform for in-memory analytics" +} diff --git a/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/bloom-filter/portfile.cmake b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/bloom-filter/portfile.cmake new file mode 100644 index 0000000000..d11c69f812 --- /dev/null +++ b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/bloom-filter/portfile.cmake @@ -0,0 +1 @@ +// intentionally empty diff --git a/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/bloom-filter/vcpkg.json b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/bloom-filter/vcpkg.json new file mode 100644 index 0000000000..2025d15a5d --- /dev/null +++ b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/ports/bloom-filter/vcpkg.json @@ -0,0 +1,7 @@ +{ + "name": "bloom-filter", + "version": "0.2.0", + "port-version": 1, + "description": "bloom filter", + "dependencies": ["arrow"] +} diff --git a/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/versions/a-/arrow.json b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/versions/a-/arrow.json new file mode 100644 index 0000000000..8728f8917f --- /dev/null +++ b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/versions/a-/arrow.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "version": "6.0.0.20210925", + "port-version": 4, + "path": "$/ports/arrow" + } + ] +} \ No newline at end of file diff --git a/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/versions/b-/bloom-filter.json b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/versions/b-/bloom-filter.json new file mode 100644 index 0000000000..8a4079a4a7 --- /dev/null +++ b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/versions/b-/bloom-filter.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "version": "0.2.0", + "port-version": 1, + "path": "$/ports/bloom-filter" + } + ] +} \ No newline at end of file diff --git a/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/versions/baseline.json b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/versions/baseline.json new file mode 100644 index 0000000000..f15584ae08 --- /dev/null +++ b/azure-pipelines/e2e_ports/mismatched-version-database/vcpkg_registry/versions/baseline.json @@ -0,0 +1,13 @@ +{ + "$doc": "https://github.com/microsoft/vcpkg/blob/master/docs/maintainers/registries.md#filesystem-registries", + "default": { + "arrow": { + "baseline": "6.0.0.20210925", + "port-version": 4 + }, + "bloom-filter": { + "baseline": "0.2.0", + "port-version": 1 + } + } +} \ No newline at end of file diff --git a/azure-pipelines/end-to-end-tests-dir/versions.ps1 b/azure-pipelines/end-to-end-tests-dir/versions.ps1 index 3ba90770b9..69a6bde41c 100644 --- a/azure-pipelines/end-to-end-tests-dir/versions.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/versions.ps1 @@ -71,12 +71,23 @@ Throw-IfFailed $CurrentTest = "default baseline" $out = Run-Vcpkg @commonArgs "--feature-flags=versions" install --x-manifest-root=$versionFilesPath/default-baseline-1 2>&1 | Out-String Throw-IfNotFailed -if ($out -notmatch ".*Error: while checking out baseline.*") +if ($out -notmatch ".*Error: while checking out baseline\.*") { $out throw "Expected to fail due to missing baseline" } +$CurrentTest = "mismatched version database" +$out = Run-Vcpkg @commonArgs "--feature-flags=versions" install --x-manifest-root="$PSScriptRoot/../e2e_ports/mismatched-version-database" 2>&1 | Out-String +Throw-IfNotFailed +if (($out -notmatch ".*Error: Failed to load port because version specs did not match*") -or + ($out -notmatch ".*Expected: arrow@6.0.0.20210925#4.*") -or + ($out -notmatch ".*Actual: arrow@6.0.0.20210925.*")) +{ + $out + throw "Expected to fail due to mismatched versions between portfile and the version database" +} + git -C "$env:VCPKG_ROOT" fetch https://github.com/vicroms/test-registries foreach ($opt_registries in @("",",registries")) { diff --git a/include/vcpkg/base/fwd/format.h b/include/vcpkg/base/fwd/format.h index 431d726e00..3afbdbec74 100644 --- a/include/vcpkg/base/fwd/format.h +++ b/include/vcpkg/base/fwd/format.h @@ -19,3 +19,14 @@ namespace fmt return fmt::formatter::format(static_cast(val), ctx); \ } \ } + +#define VCPKG_FORMAT_WITH_TO_STRING(Type) \ + template \ + struct fmt::formatter : fmt::formatter \ + { \ + template \ + auto format(Type const& val, FormatContext& ctx) const -> decltype(ctx.out()) \ + { \ + return fmt::formatter::format(val.to_string(), ctx); \ + } \ + } diff --git a/include/vcpkg/base/messages.h b/include/vcpkg/base/messages.h index 103a7378d6..56606d58b8 100644 --- a/include/vcpkg/base/messages.h +++ b/include/vcpkg/base/messages.h @@ -166,6 +166,8 @@ namespace vcpkg::msg DECLARE_MSG_ARG(triplet); DECLARE_MSG_ARG(url); DECLARE_MSG_ARG(value); + DECLARE_MSG_ARG(expected); + DECLARE_MSG_ARG(actual); DECLARE_MSG_ARG(elapsed); DECLARE_MSG_ARG(version); DECLARE_MSG_ARG(list); diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index 825247c5a9..5c541bd1b1 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -125,6 +125,7 @@ namespace vcpkg { return SchemedVersion{core_paragraph->version_scheme, core_paragraph->to_version()}; } + VersionSpec to_version_spec() const { return {core_paragraph->name, core_paragraph->to_version()}; } friend bool operator==(const SourceControlFile& lhs, const SourceControlFile& rhs); friend bool operator!=(const SourceControlFile& lhs, const SourceControlFile& rhs) { return !(lhs == rhs); } diff --git a/include/vcpkg/versions.h b/include/vcpkg/versions.h index e179106da1..90475beda8 100644 --- a/include/vcpkg/versions.h +++ b/include/vcpkg/versions.h @@ -1,5 +1,7 @@ #pragma once +#include + #include namespace vcpkg @@ -74,6 +76,8 @@ namespace vcpkg VersionSpec(const std::string& port_name, const std::string& version_string, int port_version); + std::string to_string() const; + friend bool operator==(const VersionSpec& lhs, const VersionSpec& rhs); friend bool operator!=(const VersionSpec& lhs, const VersionSpec& rhs); }; @@ -130,3 +134,5 @@ namespace vcpkg Minimum }; } + +VCPKG_FORMAT_WITH_TO_STRING(vcpkg::VersionSpec); diff --git a/locales/messages.json b/locales/messages.json index 7cfb47a9c0..397d243d61 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -62,5 +62,6 @@ "VcpkgHasCrashedArgument": "{value}|", "_VcpkgHasCrashedArgument.comment": "{LOCKED}", "VcpkgInvalidCommand": "invalid command: {value}", - "VcpkgSendMetricsButDisabled": "Warning: passed --sendmetrics, but metrics are disabled." + "VcpkgSendMetricsButDisabled": "Warning: passed --sendmetrics, but metrics are disabled.", + "VersionSpecMismatch": "Error: Failed to load port because version specs did not match\n Path: {path}\n Expected: {expected}\n Actual: {actual}" } diff --git a/src/vcpkg/dependencies.cpp b/src/vcpkg/dependencies.cpp index 39015b6347..8dc75931cc 100644 --- a/src/vcpkg/dependencies.cpp +++ b/src/vcpkg/dependencies.cpp @@ -1836,8 +1836,9 @@ namespace vcpkg::Dependencies ExpectedS VersionedPackageGraph::finalize_extract_plan( const PackageSpec& toplevel, UnsupportedPortAction unsupported_port_action) { - if (m_errors.size() > 0) + if (!m_errors.empty()) { + Util::sort_unique_erase(m_errors); return Strings::join("\n", m_errors); } diff --git a/src/vcpkg/portfileprovider.cpp b/src/vcpkg/portfileprovider.cpp index 938bedc74f..4f91c72eb1 100644 --- a/src/vcpkg/portfileprovider.cpp +++ b/src/vcpkg/portfileprovider.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -87,6 +88,12 @@ namespace vcpkg::PortFileProvider return Util::fmap(m, [](const auto& p) { return p.second; }); } + DECLARE_AND_REGISTER_MESSAGE(VersionSpecMismatch, + (msg::path, msg::expected, msg::actual), + "", + "Error: Failed to load port because version specs did not match\n Path: " + "{path}\n Expected: {expected}\n Actual: {actual}"); + namespace { struct BaselineProviderImpl : IBaselineProvider @@ -172,18 +179,19 @@ namespace vcpkg::PortFileProvider auto maybe_control_file = Paragraphs::try_load_port(m_fs, *path); if (auto scf = maybe_control_file.get()) { - if (scf->get()->core_paragraph->name == version_spec.port_name) + auto scf_vspec = scf->get()->to_version_spec(); + if (scf_vspec == version_spec) { return std::unique_ptr( new SourceControlFileAndLocation{std::move(*scf), std::move(*path)}); } else { - return Strings::format("Error: Failed to load port from %s: names did " - "not match: '%s' != '%s'", - *path, - version_spec.port_name, - scf->get()->core_paragraph->name); + return msg::format(msgVersionSpecMismatch, + msg::path = *path, + msg::expected = version_spec, + msg::actual = scf_vspec) + .extract_data(); } } else diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index ef58a4f779..3689a51340 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -1004,6 +1004,8 @@ namespace Optional RegistryImplementation::get_path_to_baseline_version(StringView port_name) const { + // This code does not defend against the files in the baseline not matching the declared baseline version. + // However, this is only used by `Paragraphs::try_load_all_registry_ports` so it is not high-impact const auto baseline_version = this->get_baseline_version(port_name); if (auto b = baseline_version.get()) { diff --git a/src/vcpkg/versions.cpp b/src/vcpkg/versions.cpp index 421d78c4a1..4e91c6fc3c 100644 --- a/src/vcpkg/versions.cpp +++ b/src/vcpkg/versions.cpp @@ -45,6 +45,8 @@ namespace vcpkg return Strings::format("%s -> %s", left.to_string(), right.to_string()); } + std::string VersionSpec::to_string() const { return Strings::concat(port_name, '@', version); } + namespace { Optional as_numeric(StringView str)