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)