From 823c16ece7527de8e82a382795fb466cf06dfa09 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Thu, 6 Apr 2023 11:00:13 -0700 Subject: [PATCH] Don't emit the triplet warning with x-set-installed no args. (#1006) * Don't emit the triplet warning with x-set-installed no args. Also added e2e tests. * clang-format * Add purpose specific unit tests, including a new test for platform qualified expressions. * Add end to end test for the environment variable being set not emitting the warning. --- azure-pipelines/end-to-end-tests-dir/cli.ps1 | 143 ++++++++++++++++++ azure-pipelines/end-to-end-tests-prelude.ps1 | 10 +- include/vcpkg-test/util.h | 26 +--- include/vcpkg/input.h | 4 +- include/vcpkg/packagespec.h | 10 +- include/vcpkg/triplet.h | 2 +- src/vcpkg-test/specifier.cpp | 147 ++++++++++++++----- src/vcpkg-test/strings.cpp | 17 +++ src/vcpkg-test/util.cpp | 31 ++++ src/vcpkg/build.cpp | 15 +- src/vcpkg/commands.buildexternal.cpp | 12 +- src/vcpkg/commands.check-support.cpp | 8 +- src/vcpkg/commands.ci.cpp | 2 +- src/vcpkg/commands.dependinfo.cpp | 8 +- src/vcpkg/commands.setinstalled.cpp | 9 +- src/vcpkg/commands.upgrade.cpp | 23 ++- src/vcpkg/export.cpp | 14 +- src/vcpkg/input.cpp | 16 +- src/vcpkg/install.cpp | 11 +- src/vcpkg/packagespec.cpp | 46 ++++-- src/vcpkg/remove.cpp | 14 +- src/vcpkg/sourceparagraph.cpp | 2 +- src/vcpkg/triplet.cpp | 23 +-- 23 files changed, 457 insertions(+), 136 deletions(-) diff --git a/azure-pipelines/end-to-end-tests-dir/cli.ps1 b/azure-pipelines/end-to-end-tests-dir/cli.ps1 index 2377cab3c1..645bb4b7e0 100644 --- a/azure-pipelines/end-to-end-tests-dir/cli.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/cli.ps1 @@ -9,3 +9,146 @@ Throw-IfNotFailed Run-Vcpkg -TestArgs ($commonArgs + @("install", "vcpkg-hello-world-1", "--fast")) # --fast is not a switch Throw-IfNotFailed + +if ($IsWindows) { + $warningText = 'Starting with the September 2023 release' + + # build-external not tested + # ci not tested + # export not tested + + # depend-info + [string]$output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('depend-info', 'vcpkg-hello-world-1')) + Throw-IfFailed + if (-Not $output.Contains($warningText)) { + throw 'depend-info with unqualified spec should emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('depend-info', 'vcpkg-hello-world-1:x64-windows')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'depend-info with qualified parameters should not emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('depend-info', 'vcpkg-hello-world-1', '--triplet', 'x86-windows')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'depend-info with arg should not emit the triplet warning' + } + + # set-installed + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('x-set-installed')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'x-set-installed with no parameters should not emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('x-set-installed', 'vcpkg-hello-world-1')) + Throw-IfFailed + if (-Not $output.Contains($warningText)) { + throw 'x-set-installed with unqualified spec should emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('x-set-installed', 'vcpkg-hello-world-1:x64-windows')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'x-set-installed with qualified parameters should not emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('x-set-installed', 'vcpkg-hello-world-1', '--triplet', 'x86-windows')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'x-set-installed with arg should not emit the triplet warning' + } + + # install + Refresh-TestRoot + $sub = Join-Path $TestingRoot 'manifest-warn' + New-Item -ItemType Directory -Force $sub | Out-Null + Push-Location $sub + try { + Run-Vcpkg -TestArgs ($directoryArgs + @('new', '--application')) + Throw-IfFailed + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('install')) + Throw-IfFailed + if (-Not $output.Contains($warningText)) { + throw 'manifest install should emit the triplet warning' + } + } finally { + Pop-Location + } + + Refresh-TestRoot + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('install', 'vcpkg-hello-world-1')) + Throw-IfFailed + if (-Not $output.Contains($warningText)) { + throw 'install with unqualified spec should emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('install', 'vcpkg-hello-world-1:x64-windows')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'install with qualified parameters should not emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('install', 'vcpkg-hello-world-1', '--triplet', 'x86-windows')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'install with arg should not emit the triplet warning' + } + + # upgrade + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('upgrade')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'upgrade with no parameters should not emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('upgrade', 'vcpkg-hello-world-1')) + Throw-IfFailed + if (-Not $output.Contains($warningText)) { + throw 'upgrade with unqualified spec should emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('upgrade', 'vcpkg-hello-world-1:x64-windows')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'upgrade with qualified parameters should not emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('upgrade', 'vcpkg-hello-world-1', '--triplet', 'x86-windows')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'upgrade with arg should not emit the triplet warning' + } + + # remove + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('remove', 'vcpkg-hello-world-1')) + Throw-IfFailed + if (-Not $output.Contains($warningText)) { + throw 'remove with unqualified spec should emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('remove', 'vcpkg-hello-world-1:x64-windows')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'remove with qualified parameters should not emit the triplet warning' + } + + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('remove', 'vcpkg-hello-world-1', '--triplet', 'x86-windows')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'remove with arg should not emit the triplet warning' + } + + $env:VCPKG_DEFAULT_TRIPLET = 'x86-windows' + Refresh-TestRoot + $output = Run-VcpkgAndCaptureOutput -TestArgs ($directoryArgs + @('install', 'vcpkg-hello-world-1')) + Throw-IfFailed + if ($output.Contains($warningText)) { + throw 'install with environment variable set should not emit the triplet warning' + } + + Remove-Item env:VCPKG_DEFAULT_TRIPLET +} diff --git a/azure-pipelines/end-to-end-tests-prelude.ps1 b/azure-pipelines/end-to-end-tests-prelude.ps1 index 43b4d4717d..fc5abdbad5 100644 --- a/azure-pipelines/end-to-end-tests-prelude.ps1 +++ b/azure-pipelines/end-to-end-tests-prelude.ps1 @@ -6,15 +6,19 @@ $NuGetRoot = Join-Path $TestingRoot 'nuget' $NuGetRoot2 = Join-Path $TestingRoot 'nuget2' $ArchiveRoot = Join-Path $TestingRoot 'archives' $VersionFilesRoot = Join-Path $TestingRoot 'version-test' -$commonArgs = @( - "--triplet", - $Triplet, +$directoryArgs = @( "--x-buildtrees-root=$buildtreesRoot", "--x-install-root=$installRoot", "--x-packages-root=$packagesRoot", "--overlay-ports=$PSScriptRoot/e2e_ports/overlays", "--overlay-triplets=$PSScriptRoot/e2e_ports/triplets" ) + +$commonArgs = @( + "--triplet", + $Triplet +) + $directoryArgs + $Script:CurrentTest = 'unassigned' function Refresh-TestRoot { diff --git a/include/vcpkg-test/util.h b/include/vcpkg-test/util.h index 2d1568b3e1..d38fb11720 100644 --- a/include/vcpkg-test/util.h +++ b/include/vcpkg-test/util.h @@ -92,17 +92,8 @@ namespace vcpkg::Test const std::vector>& features = {}, const std::vector& default_features = {}); - inline auto test_parse_control_file(const std::vector>& v) - { - std::vector pghs; - for (auto&& p : v) - { - pghs.emplace_back(); - for (auto&& kv : p) - pghs.back().emplace(kv.first, std::make_pair(kv.second, vcpkg::TextRowCol{})); - } - return vcpkg::SourceControlFile::parse_control_file("", std::move(pghs)); - } + ParseExpected test_parse_control_file( + const std::vector>& v); std::unique_ptr make_status_pgh(const char* name, const char* depends = "", @@ -143,18 +134,7 @@ namespace vcpkg::Test PackageSpec emplace(vcpkg::SourceControlFileAndLocation&& scfl); }; - inline std::vector parse_test_fspecs(StringView sv, Triplet t = X86_WINDOWS) - { - std::vector ret; - ParserBase parser(sv, "test"); - while (!parser.at_eof()) - { - auto opt = parse_qualified_specifier(parser); - REQUIRE(opt.has_value()); - ret.push_back(opt.get()->to_full_spec(t, ImplicitDefault::YES).value_or_exit(VCPKG_LINE_INFO)); - } - return ret; - } + std::vector parse_test_fspecs(StringView sv); template void check_ranges(const R1& r1, const R2& r2) diff --git a/include/vcpkg/input.h b/include/vcpkg/input.h index 64f1635e31..4902eb9e4b 100644 --- a/include/vcpkg/input.h +++ b/include/vcpkg/input.h @@ -8,11 +8,13 @@ namespace vcpkg { PackageSpec check_and_get_package_spec(std::string&& spec_string, Triplet default_triplet, + bool& default_triplet_used, const LocalizedString& example_text, const VcpkgPaths& paths); - FullPackageSpec check_and_get_full_package_spec(std::string&& spec_string, + FullPackageSpec check_and_get_full_package_spec(std::string spec_string, Triplet default_triplet, + bool& default_triplet_used, const LocalizedString& example_text, const VcpkgPaths& paths); diff --git a/include/vcpkg/packagespec.h b/include/vcpkg/packagespec.h index 2602b9915c..737bb86e12 100644 --- a/include/vcpkg/packagespec.h +++ b/include/vcpkg/packagespec.h @@ -98,6 +98,8 @@ namespace vcpkg using std::vector::vector; }; + InternalFeatureSet internalize_feature_list(View fs, ImplicitDefault id); + /// /// /// Full specification of a package. Contains all information to reference @@ -109,12 +111,10 @@ namespace vcpkg PackageSpec package_spec; InternalFeatureSet features; - FullPackageSpec() = default; FullPackageSpec(PackageSpec spec, InternalFeatureSet features) : package_spec(std::move(spec)), features(std::move(features)) { } - FullPackageSpec(PackageSpec spec, View features, ImplicitDefault id); /// Splats into individual FeatureSpec's void expand_fspecs_to(std::vector& oFut) const; @@ -135,9 +135,11 @@ namespace vcpkg /// @param id add "default" if "core" is not present /// @return nullopt on success. On failure, caller should supplement returned string with more context. - ExpectedL to_full_spec(Triplet default_triplet, ImplicitDefault id) const; + ExpectedL to_full_spec(Triplet default_triplet, + bool& default_triplet_used, + ImplicitDefault id) const; - ExpectedL to_package_spec(Triplet default_triplet) const; + ExpectedL to_package_spec(Triplet default_triplet, bool& default_triplet_used) const; }; Optional parse_feature_name(ParserBase& parser); diff --git a/include/vcpkg/triplet.h b/include/vcpkg/triplet.h index faf1561216..14a2ff581f 100644 --- a/include/vcpkg/triplet.h +++ b/include/vcpkg/triplet.h @@ -43,7 +43,7 @@ namespace vcpkg Triplet default_triplet(const VcpkgCmdArguments& args); Triplet default_host_triplet(const VcpkgCmdArguments& args); - void print_default_triplet_warning(const VcpkgCmdArguments& args, View specs); + void print_default_triplet_warning(const VcpkgCmdArguments& arg); } VCPKG_FORMAT_AS(vcpkg::Triplet, vcpkg::StringView); diff --git a/src/vcpkg-test/specifier.cpp b/src/vcpkg-test/specifier.cpp index 8a86449856..06db33fbd9 100644 --- a/src/vcpkg-test/specifier.cpp +++ b/src/vcpkg-test/specifier.cpp @@ -38,23 +38,64 @@ TEST_CASE ("specifier parsing", "[specifier]") { SECTION ("parsed specifier from string") { - auto maybe_spec = vcpkg::parse_qualified_specifier("zlib"); - REQUIRE(maybe_spec.has_value()); - - auto& spec = *maybe_spec.get(); + auto spec = vcpkg::parse_qualified_specifier("zlib").value_or_exit(VCPKG_LINE_INFO); REQUIRE(spec.name == "zlib"); REQUIRE(!spec.features); REQUIRE(!spec.triplet); + REQUIRE(!spec.platform); + + bool default_triplet_used = false; + auto full_spec_implicit = spec.to_full_spec(Test::X86_WINDOWS, default_triplet_used, ImplicitDefault::YES) + .value_or_exit(VCPKG_LINE_INFO); + REQUIRE(default_triplet_used); + default_triplet_used = false; + REQUIRE(full_spec_implicit.package_spec.name() == "zlib"); + REQUIRE(full_spec_implicit.package_spec.triplet() == Test::X86_WINDOWS); + REQUIRE(full_spec_implicit.features == std::vector{"core", "default"}); + + auto full_spec_explicit = spec.to_full_spec(Test::X86_WINDOWS, default_triplet_used, ImplicitDefault::NO) + .value_or_exit(VCPKG_LINE_INFO); + REQUIRE(default_triplet_used); + default_triplet_used = false; + REQUIRE(full_spec_explicit.package_spec.name() == "zlib"); + REQUIRE(full_spec_explicit.package_spec.triplet() == Test::X86_WINDOWS); + REQUIRE(full_spec_explicit.features == std::vector{"core"}); + + auto package_spec = + spec.to_package_spec(Test::X86_WINDOWS, default_triplet_used).value_or_exit(VCPKG_LINE_INFO); + REQUIRE(default_triplet_used); + REQUIRE(package_spec.name() == "zlib"); + REQUIRE(package_spec.triplet() == Test::X86_WINDOWS); } SECTION ("parsed specifier from string with triplet") { - auto maybe_spec = vcpkg::parse_qualified_specifier("zlib:x64-uwp"); - REQUIRE(maybe_spec); - - auto& spec = *maybe_spec.get(); + auto spec = vcpkg::parse_qualified_specifier("zlib:x64-uwp").value_or_exit(VCPKG_LINE_INFO); REQUIRE(spec.name == "zlib"); - REQUIRE(spec.triplet.value_or("") == "x64-uwp"); + REQUIRE(!spec.features); + REQUIRE(spec.triplet.value_or_exit(VCPKG_LINE_INFO) == "x64-uwp"); + REQUIRE(!spec.platform); + + bool default_triplet_used = false; + auto full_spec_implicit = spec.to_full_spec(Test::X86_WINDOWS, default_triplet_used, ImplicitDefault::YES) + .value_or_exit(VCPKG_LINE_INFO); + REQUIRE(!default_triplet_used); + REQUIRE(full_spec_implicit.package_spec.name() == "zlib"); + REQUIRE(full_spec_implicit.package_spec.triplet() == Test::X64_UWP); + REQUIRE(full_spec_implicit.features == std::vector{"core", "default"}); + + auto full_spec_explicit = spec.to_full_spec(Test::X86_WINDOWS, default_triplet_used, ImplicitDefault::NO) + .value_or_exit(VCPKG_LINE_INFO); + REQUIRE(!default_triplet_used); + REQUIRE(full_spec_explicit.package_spec.name() == "zlib"); + REQUIRE(full_spec_explicit.package_spec.triplet() == Test::X64_UWP); + REQUIRE(full_spec_explicit.features == std::vector{"core"}); + + auto package_spec = + spec.to_package_spec(Test::X86_WINDOWS, default_triplet_used).value_or_exit(VCPKG_LINE_INFO); + REQUIRE(!default_triplet_used); + REQUIRE(package_spec.name() == "zlib"); + REQUIRE(package_spec.triplet() == Test::X64_UWP); } SECTION ("parsed specifier from string with colons") @@ -65,28 +106,50 @@ TEST_CASE ("specifier parsing", "[specifier]") SECTION ("parsed specifier from string with feature") { - auto maybe_spec = vcpkg::parse_qualified_specifier("zlib[feature]:x64-uwp"); - REQUIRE(maybe_spec); - - auto& spec = *maybe_spec.get(); + auto spec = vcpkg::parse_qualified_specifier("zlib[feature]:x64-uwp").value_or_exit(VCPKG_LINE_INFO); REQUIRE(spec.name == "zlib"); REQUIRE(spec.features.value_or(std::vector{}) == std::vector{"feature"}); REQUIRE(spec.triplet.value_or("") == "x64-uwp"); + REQUIRE(!spec.platform); + + bool default_triplet_used = false; + auto full_spec_implicit = spec.to_full_spec(Test::X86_WINDOWS, default_triplet_used, ImplicitDefault::YES) + .value_or_exit(VCPKG_LINE_INFO); + REQUIRE(!default_triplet_used); + REQUIRE(full_spec_implicit.package_spec.name() == "zlib"); + REQUIRE(full_spec_implicit.package_spec.triplet() == Test::X64_UWP); + REQUIRE(full_spec_implicit.features == std::vector{"feature", "core", "default"}); + + auto full_spec_explicit = spec.to_full_spec(Test::X86_WINDOWS, default_triplet_used, ImplicitDefault::NO) + .value_or_exit(VCPKG_LINE_INFO); + REQUIRE(!default_triplet_used); + REQUIRE(full_spec_explicit.package_spec.name() == "zlib"); + REQUIRE(full_spec_explicit.package_spec.triplet() == Test::X64_UWP); + REQUIRE(full_spec_explicit.features == std::vector{"feature", "core"}); + + auto maybe_package_spec = spec.to_package_spec(Test::X86_WINDOWS, default_triplet_used); + REQUIRE(!default_triplet_used); + REQUIRE(!maybe_package_spec.has_value()); + REQUIRE(maybe_package_spec.error() == + LocalizedString::from_raw("error: List of features is not allowed in this context")); } SECTION ("parsed specifier from string with many features") { - auto maybe_spec = vcpkg::parse_qualified_specifier("zlib[0, 1,2]"); - REQUIRE(maybe_spec); - - auto& spec = *maybe_spec.get(); - REQUIRE(spec.features.value_or(std::vector{}) == std::vector{"0", "1", "2"}); + auto spec = vcpkg::parse_qualified_specifier("zlib[0, 1,2]").value_or_exit(VCPKG_LINE_INFO); + REQUIRE(spec.name == "zlib"); + REQUIRE(spec.features.value_or_exit(VCPKG_LINE_INFO) == std::vector{"0", "1", "2"}); + REQUIRE(!spec.triplet); + REQUIRE(!spec.platform); } SECTION ("parsed specifier wildcard feature") { auto spec = vcpkg::parse_qualified_specifier("zlib[*]").value_or_exit(VCPKG_LINE_INFO); - REQUIRE(spec.features.value_or(std::vector{}) == std::vector{"*"}); + REQUIRE(spec.name == "zlib"); + REQUIRE(spec.features.value_or_exit(VCPKG_LINE_INFO) == std::vector{"*"}); + REQUIRE(!spec.triplet); + REQUIRE(!spec.platform); } SECTION ("dont expand wildcards") @@ -94,9 +157,11 @@ TEST_CASE ("specifier parsing", "[specifier]") std::vector specs; const auto fspecs = Test::parse_test_fspecs("zlib[core,0,1]:x86-uwp openssl[*]:x86-uwp"); for (auto&& fs : fspecs) + { fs.expand_fspecs_to(specs); - Util::sort(specs); + } + Util::sort(specs); std::vector spectargets{ {{"openssl", Test::X86_UWP}, "core"}, {{"openssl", Test::X86_UWP}, "default"}, @@ -105,24 +170,38 @@ TEST_CASE ("specifier parsing", "[specifier]") {{"zlib", Test::X86_UWP}, "0"}, {{"zlib", Test::X86_UWP}, "1"}, }; + Util::sort(spectargets); Test::check_ranges(specs, spectargets); } -} -#if defined(_WIN32) -TEST_CASE ("ascii to utf16", "[utf16]") -{ - SECTION ("ASCII to utf16") + SECTION ("parsed qualifier platform expression") { - auto str = vcpkg::Strings::to_utf16("abc"); - REQUIRE(str == L"abc"); - } - - SECTION ("ASCII to utf16 with whitespace") - { - auto str = vcpkg::Strings::to_utf16("abc -x86-windows"); - REQUIRE(str == L"abc -x86-windows"); + // this form was used in CONTROL files + auto spec = vcpkg::parse_qualified_specifier("zlib (windows)").value_or_exit(VCPKG_LINE_INFO); + REQUIRE(spec.name == "zlib"); + REQUIRE(!spec.features); + REQUIRE(!spec.triplet); + REQUIRE(to_string(spec.platform.value_or_exit(VCPKG_LINE_INFO)) == "windows"); + + bool default_triplet_used = false; + auto maybe_full_spec_implicit = + spec.to_full_spec(Test::X86_WINDOWS, default_triplet_used, ImplicitDefault::YES); + REQUIRE(!default_triplet_used); + REQUIRE(!maybe_full_spec_implicit.has_value()); + REQUIRE(maybe_full_spec_implicit.error() == + LocalizedString::from_raw("error: Platform qualifier is not allowed in this context")); + + auto maybe_full_spec_explicit = spec.to_full_spec(Test::X86_WINDOWS, default_triplet_used, ImplicitDefault::NO); + REQUIRE(!default_triplet_used); + REQUIRE(!maybe_full_spec_explicit.has_value()); + REQUIRE(maybe_full_spec_explicit.error() == + LocalizedString::from_raw("error: Platform qualifier is not allowed in this context")); + + auto maybe_package_spec = spec.to_package_spec(Test::X86_WINDOWS, default_triplet_used); + REQUIRE(!default_triplet_used); + REQUIRE(!maybe_package_spec.has_value()); + REQUIRE(maybe_package_spec.error() == + LocalizedString::from_raw("error: Platform qualifier is not allowed in this context")); } } -#endif diff --git a/src/vcpkg-test/strings.cpp b/src/vcpkg-test/strings.cpp index cebee1c511..7be8b72c20 100644 --- a/src/vcpkg-test/strings.cpp +++ b/src/vcpkg-test/strings.cpp @@ -232,3 +232,20 @@ TEST_CASE ("api_stable_format(sv,append_f)", "[strings]") }); REQUIRE(*res.get() == "123hello456"); } + +#if defined(_WIN32) +TEST_CASE ("ascii to utf16", "[utf16]") +{ + SECTION ("ASCII to utf16") + { + auto str = vcpkg::Strings::to_utf16("abc"); + REQUIRE(str == L"abc"); + } + + SECTION ("ASCII to utf16 with whitespace") + { + auto str = vcpkg::Strings::to_utf16("abc -x86-windows"); + REQUIRE(str == L"abc -x86-windows"); + } +} +#endif diff --git a/src/vcpkg-test/util.cpp b/src/vcpkg-test/util.cpp index fb7975c035..9f4cd35e1d 100644 --- a/src/vcpkg-test/util.cpp +++ b/src/vcpkg-test/util.cpp @@ -54,6 +54,21 @@ namespace vcpkg::Test return std::move(*m_pgh.get()); } + ParseExpected test_parse_control_file( + const std::vector>& v) + { + std::vector pghs; + for (auto&& p : v) + { + pghs.emplace_back(); + for (auto&& kv : p) + { + pghs.back().emplace(kv.first, std::make_pair(kv.second, vcpkg::TextRowCol{})); + } + } + return vcpkg::SourceControlFile::parse_control_file("", std::move(pghs)); + } + std::unique_ptr make_status_pgh(const char* name, const char* depends, const char* default_features, @@ -107,6 +122,22 @@ namespace vcpkg::Test #endif } + std::vector parse_test_fspecs(StringView sv) + { + std::vector ret; + ParserBase parser(sv, "test"); + while (!parser.at_eof()) + { + auto opt = parse_qualified_specifier(parser); + REQUIRE(opt.has_value()); + bool unused = false; + ret.push_back( + opt.get()->to_full_spec(X86_WINDOWS, unused, ImplicitDefault::YES).value_or_exit(VCPKG_LINE_INFO)); + } + + return ret; + } + const Path& base_temporary_directory() noexcept { const static Path BASE_TEMPORARY_DIRECTORY = internal_base_temporary_directory(); diff --git a/src/vcpkg/build.cpp b/src/vcpkg/build.cpp index 9e5b7520ac..a6ffb15efa 100644 --- a/src/vcpkg/build.cpp +++ b/src/vcpkg/build.cpp @@ -181,12 +181,17 @@ namespace vcpkg::Build { // Build only takes a single package and all dependencies must already be installed const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); - std::string first_arg = options.command_arguments[0]; - BinaryCache binary_cache{args, paths}; - const FullPackageSpec spec = check_and_get_full_package_spec( - std::move(first_arg), default_triplet, COMMAND_STRUCTURE.get_example_text(), paths); - print_default_triplet_warning(args, {&options.command_arguments[0], 1}); + bool default_triplet_used = false; + const FullPackageSpec spec = check_and_get_full_package_spec(options.command_arguments[0], + default_triplet, + default_triplet_used, + COMMAND_STRUCTURE.get_example_text(), + paths); + if (default_triplet_used) + { + print_default_triplet_warning(args); + } auto& fs = paths.get_filesystem(); auto registry_set = paths.make_registry_set(); diff --git a/src/vcpkg/commands.buildexternal.cpp b/src/vcpkg/commands.buildexternal.cpp index 8e7ffa0b03..18bc1a4c14 100644 --- a/src/vcpkg/commands.buildexternal.cpp +++ b/src/vcpkg/commands.buildexternal.cpp @@ -27,8 +27,16 @@ namespace vcpkg::Commands::BuildExternal BinaryCache binary_cache{args, paths}; - const FullPackageSpec spec = check_and_get_full_package_spec( - std::string(options.command_arguments[0]), default_triplet, COMMAND_STRUCTURE.get_example_text(), paths); + bool default_triplet_used = false; + const FullPackageSpec spec = check_and_get_full_package_spec(options.command_arguments[0], + default_triplet, + default_triplet_used, + COMMAND_STRUCTURE.get_example_text(), + paths); + if (default_triplet_used) + { + print_default_triplet_warning(args); + } auto overlays = paths.overlay_ports; overlays.insert(overlays.begin(), options.command_arguments[1]); diff --git a/src/vcpkg/commands.check-support.cpp b/src/vcpkg/commands.check-support.cpp index 2a8632d69d..4e241e647d 100644 --- a/src/vcpkg/commands.check-support.cpp +++ b/src/vcpkg/commands.check-support.cpp @@ -113,12 +113,16 @@ namespace vcpkg::Commands const bool use_json = Util::Sets::contains(options.switches, OPTION_JSON); Json::Array json_to_print; // only used when `use_json` + bool default_triplet_used = false; const std::vector specs = Util::fmap(options.command_arguments, [&](auto&& arg) { return check_and_get_full_package_spec( - std::string(arg), default_triplet, COMMAND_STRUCTURE.get_example_text(), paths); + arg, default_triplet, default_triplet_used, COMMAND_STRUCTURE.get_example_text(), paths); }); - print_default_triplet_warning(args, options.command_arguments); + if (default_triplet_used) + { + print_default_triplet_warning(args); + } auto& fs = paths.get_filesystem(); auto registry_set = paths.make_registry_set(); diff --git a/src/vcpkg/commands.ci.cpp b/src/vcpkg/commands.ci.cpp index bfaeae14f0..ee5b49d8f3 100644 --- a/src/vcpkg/commands.ci.cpp +++ b/src/vcpkg/commands.ci.cpp @@ -346,7 +346,7 @@ namespace vcpkg::Commands::CI { msg::println_warning(msgInternalCICommand); - print_default_triplet_warning(args, {}); + print_default_triplet_warning(args); const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const auto& settings = options.settings; diff --git a/src/vcpkg/commands.dependinfo.cpp b/src/vcpkg/commands.dependinfo.cpp index 48296658b1..38c0d14a7e 100644 --- a/src/vcpkg/commands.dependinfo.cpp +++ b/src/vcpkg/commands.dependinfo.cpp @@ -298,12 +298,16 @@ namespace vcpkg::Commands::DependInfo const SortMode sort_mode = get_sort_mode(options); const bool show_depth = Util::Sets::contains(options.switches, OPTION_SHOW_DEPTH); + bool default_triplet_used = false; const std::vector specs = Util::fmap(options.command_arguments, [&](auto&& arg) { return check_and_get_full_package_spec( - std::string{arg}, default_triplet, COMMAND_STRUCTURE.get_example_text(), paths); + arg, default_triplet, default_triplet_used, COMMAND_STRUCTURE.get_example_text(), paths); }); - print_default_triplet_warning(args, options.command_arguments); + if (default_triplet_used) + { + print_default_triplet_warning(args); + } auto& fs = paths.get_filesystem(); auto registry_set = paths.make_registry_set(); diff --git a/src/vcpkg/commands.setinstalled.cpp b/src/vcpkg/commands.setinstalled.cpp index 98a26c7801..d0d35649b3 100644 --- a/src/vcpkg/commands.setinstalled.cpp +++ b/src/vcpkg/commands.setinstalled.cpp @@ -157,13 +157,16 @@ namespace vcpkg::Commands::SetInstalled { // input sanitization const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); - + bool default_triplet_used = false; const std::vector specs = Util::fmap(options.command_arguments, [&](auto&& arg) { return check_and_get_full_package_spec( - std::string(arg), default_triplet, COMMAND_STRUCTURE.get_example_text(), paths); + arg, default_triplet, default_triplet_used, COMMAND_STRUCTURE.get_example_text(), paths); }); - print_default_triplet_warning(args, options.command_arguments); + if (default_triplet_used) + { + print_default_triplet_warning(args); + } BinaryCache binary_cache{args, paths}; diff --git a/src/vcpkg/commands.upgrade.cpp b/src/vcpkg/commands.upgrade.cpp index e078de4add..b9f789f02b 100644 --- a/src/vcpkg/commands.upgrade.cpp +++ b/src/vcpkg/commands.upgrade.cpp @@ -70,14 +70,8 @@ namespace vcpkg::Commands::Upgrade auto var_provider_storage = CMakeVars::make_triplet_cmake_var_provider(paths); auto& var_provider = *var_provider_storage; - // input sanitization - const std::vector specs = Util::fmap(options.command_arguments, [&](auto&& arg) { - return check_and_get_package_spec( - std::string(arg), default_triplet, COMMAND_STRUCTURE.get_example_text(), paths); - }); - ActionPlan action_plan; - if (specs.empty()) + if (options.command_arguments.empty()) { // If no packages specified, upgrade all outdated packages. auto outdated_packages = Update::find_outdated_packages(provider, status_db); @@ -97,7 +91,20 @@ namespace vcpkg::Commands::Upgrade } else { - print_default_triplet_warning(args, options.command_arguments); + // input sanitization + bool default_triplet_used = false; + const std::vector specs = Util::fmap(options.command_arguments, [&](auto&& arg) { + return check_and_get_package_spec(std::string(arg), + default_triplet, + default_triplet_used, + COMMAND_STRUCTURE.get_example_text(), + paths); + }); + + if (default_triplet_used) + { + print_default_triplet_warning(args); + } std::vector not_installed; std::vector no_control_file; diff --git a/src/vcpkg/export.cpp b/src/vcpkg/export.cpp index 55467692f9..9d09231982 100644 --- a/src/vcpkg/export.cpp +++ b/src/vcpkg/export.cpp @@ -417,11 +417,19 @@ namespace vcpkg::Export else { // input sanitization + bool default_triplet_used = false; ret.specs = Util::fmap(options.command_arguments, [&](auto&& arg) { - return check_and_get_package_spec( - std::string(arg), default_triplet, COMMAND_STRUCTURE.get_example_text(), paths); + return check_and_get_package_spec(std::string(arg), + default_triplet, + default_triplet_used, + COMMAND_STRUCTURE.get_example_text(), + paths); }); - print_default_triplet_warning(args, options.command_arguments); + + if (default_triplet_used) + { + print_default_triplet_warning(args); + } } if (!ret.raw && !ret.nuget && !ret.ifw && !ret.zip && !ret.seven_zip && !ret.dry_run && !ret.chocolatey && diff --git a/src/vcpkg/input.cpp b/src/vcpkg/input.cpp index 89bf9da938..b4efda0961 100644 --- a/src/vcpkg/input.cpp +++ b/src/vcpkg/input.cpp @@ -11,13 +11,15 @@ namespace vcpkg { PackageSpec check_and_get_package_spec(std::string&& spec_string, Triplet default_triplet, + bool& default_triplet_used, const LocalizedString& example_text, const VcpkgPaths& paths) { const std::string as_lowercase = Strings::ascii_to_lowercase(std::move(spec_string)); auto expected_spec = - parse_qualified_specifier(as_lowercase).then(&ParsedQualifiedSpecifier::to_package_spec, default_triplet); + parse_qualified_specifier(as_lowercase) + .then(&ParsedQualifiedSpecifier::to_package_spec, default_triplet, default_triplet_used); if (auto spec = expected_spec.get()) { check_triplet(spec->triplet(), paths); @@ -40,14 +42,18 @@ namespace vcpkg } } - FullPackageSpec check_and_get_full_package_spec(std::string&& full_package_spec_as_string, + FullPackageSpec check_and_get_full_package_spec(std::string full_package_spec_as_string, Triplet default_triplet, + bool& default_triplet_used, const LocalizedString& example_text, const VcpkgPaths& paths) { - const std::string as_lowercase = Strings::ascii_to_lowercase(std::move(full_package_spec_as_string)); - auto expected_spec = parse_qualified_specifier(as_lowercase) - .then(&ParsedQualifiedSpecifier::to_full_spec, default_triplet, ImplicitDefault::YES); + Strings::ascii_to_lowercase(full_package_spec_as_string); + auto expected_spec = parse_qualified_specifier(full_package_spec_as_string) + .then(&ParsedQualifiedSpecifier::to_full_spec, + default_triplet, + default_triplet_used, + ImplicitDefault::YES); if (const auto spec = expected_spec.get()) { check_triplet(spec->package_spec.triplet(), paths); diff --git a/src/vcpkg/install.cpp b/src/vcpkg/install.cpp index 83ae072047..c9c681e17a 100644 --- a/src/vcpkg/install.cpp +++ b/src/vcpkg/install.cpp @@ -1000,7 +1000,8 @@ namespace vcpkg print_usage(MANIFEST_COMMAND_STRUCTURE); Checks::exit_fail(VCPKG_LINE_INFO); } - print_default_triplet_warning(args, {}); + + print_default_triplet_warning(args); } else { @@ -1193,12 +1194,16 @@ namespace vcpkg PathsPortFileProvider provider( fs, *registry_set, make_overlay_provider(fs, paths.original_cwd, paths.overlay_ports)); + bool default_triplet_used = false; const std::vector specs = Util::fmap(options.command_arguments, [&](auto&& arg) { return check_and_get_full_package_spec( - std::string(arg), default_triplet, COMMAND_STRUCTURE.get_example_text(), paths); + arg, default_triplet, default_triplet_used, COMMAND_STRUCTURE.get_example_text(), paths); }); - print_default_triplet_warning(args, options.command_arguments); + if (default_triplet_used) + { + print_default_triplet_warning(args); + } // create the plan msg::println(msgComputingInstallPlan); diff --git a/src/vcpkg/packagespec.cpp b/src/vcpkg/packagespec.cpp index a2f32f0f07..83dafb7627 100644 --- a/src/vcpkg/packagespec.cpp +++ b/src/vcpkg/packagespec.cpp @@ -7,6 +7,23 @@ #include #include +namespace +{ + using namespace vcpkg; + Triplet resolve_triplet(const Optional& specified_triplet, + Triplet default_triplet, + bool& default_triplet_used) + { + if (auto pspecified = specified_triplet.get()) + { + return Triplet::from_canonical_name(*pspecified); + } + + default_triplet_used = true; + return default_triplet; + } +} // unnamed namespace + namespace vcpkg { std::string FeatureSpec::to_string() const @@ -26,7 +43,7 @@ namespace vcpkg return fmt::format("{}[{}]", package_name, feature_name); } - static InternalFeatureSet normalize_feature_list(View fs, ImplicitDefault id) + InternalFeatureSet internalize_feature_list(View fs, ImplicitDefault id) { InternalFeatureSet ret; bool core = false; @@ -50,11 +67,6 @@ namespace vcpkg return ret; } - FullPackageSpec::FullPackageSpec(PackageSpec spec, View features, ImplicitDefault id) - : package_spec(std::move(spec)), features(normalize_feature_list(features, id)) - { - } - void FullPackageSpec::expand_fspecs_to(std::vector& out) const { for (auto&& feature : features) @@ -80,31 +92,39 @@ namespace vcpkg return left.name() == right.name() && left.triplet() == right.triplet(); } - ExpectedL ParsedQualifiedSpecifier::to_full_spec(Triplet default_triplet, ImplicitDefault id) const + ExpectedL ParsedQualifiedSpecifier::to_full_spec(Triplet default_triplet, + bool& default_triplet_used, + ImplicitDefault id) const { if (platform) { return msg::format_error(msgIllegalPlatformSpec); } - const Triplet t = triplet ? Triplet::from_canonical_name(*triplet.get()) : default_triplet; - const View fs = !features.get() ? View{} : *features.get(); - return FullPackageSpec{{name, t}, fs, id}; + View fs{}; + if (auto pfeatures = features.get()) + { + fs = *pfeatures; + } + + return FullPackageSpec{{name, resolve_triplet(triplet, default_triplet, default_triplet_used)}, + internalize_feature_list(fs, id)}; } - ExpectedL ParsedQualifiedSpecifier::to_package_spec(Triplet default_triplet) const + ExpectedL ParsedQualifiedSpecifier::to_package_spec(Triplet default_triplet, + bool& default_triplet_used) const { if (platform) { return msg::format_error(msgIllegalPlatformSpec); } + if (features) { return msg::format_error(msgIllegalFeatures); } - const Triplet t = triplet ? Triplet::from_canonical_name(*triplet.get()) : default_triplet; - return PackageSpec{name, t}; + return PackageSpec{name, resolve_triplet(triplet, default_triplet, default_triplet_used)}; } ExpectedL parse_qualified_specifier(StringView input) diff --git a/src/vcpkg/remove.cpp b/src/vcpkg/remove.cpp index 5633f3e426..7d4431d9ba 100644 --- a/src/vcpkg/remove.cpp +++ b/src/vcpkg/remove.cpp @@ -225,12 +225,20 @@ namespace vcpkg::Remove msg::println_error(msgInvalidOptionForRemove); Checks::exit_fail(VCPKG_LINE_INFO); } + + bool default_triplet_used = false; specs = Util::fmap(options.command_arguments, [&](auto&& arg) { - return check_and_get_package_spec( - std::string(arg), default_triplet, COMMAND_STRUCTURE.get_example_text(), paths); + return check_and_get_package_spec(std::string(arg), + default_triplet, + default_triplet_used, + COMMAND_STRUCTURE.get_example_text(), + paths); }); - print_default_triplet_warning(args, options.command_arguments); + if (default_triplet_used) + { + print_default_triplet_warning(args); + } } const Purge purge = Util::Sets::contains(options.switches, OPTION_PURGE) ? Purge::YES : Purge::NO; diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 3c4d52f38e..b7c77e6e71 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -42,7 +42,7 @@ namespace vcpkg FullPackageSpec Dependency::to_full_spec(Triplet target, Triplet host_triplet, ImplicitDefault id) const { - return FullPackageSpec{{name, host ? host_triplet : target}, features, id}; + return FullPackageSpec{{name, host ? host_triplet : target}, internalize_feature_list(features, id)}; } bool operator==(const Dependency& lhs, const Dependency& rhs) diff --git a/src/vcpkg/triplet.cpp b/src/vcpkg/triplet.cpp index 1ecec3ac2a..58c913c19c 100644 --- a/src/vcpkg/triplet.cpp +++ b/src/vcpkg/triplet.cpp @@ -115,30 +115,15 @@ namespace vcpkg return system_triplet(); } - void print_default_triplet_warning(const VcpkgCmdArguments& args, View specs) + void print_default_triplet_warning(const VcpkgCmdArguments& args) { (void)args; - (void)specs; -#if defined(_WIN32) // The triplet is not set by --triplet or VCPKG_DEFAULT_TRIPLET +#if defined(_WIN32) if (!args.triplet.has_value()) { - if (specs.size() == 0) - { - msg::println_warning(msgDefaultTriplet, msg::triplet = default_host_triplet(args)); - return; - } - for (auto&& arg : specs) - { - const std::string as_lowercase = Strings::ascii_to_lowercase(std::string{arg}); - auto maybe_qpkg = parse_qualified_specifier(as_lowercase); - if (maybe_qpkg.has_value() && !maybe_qpkg.get()->triplet.has_value()) - { - msg::println_warning(msgDefaultTriplet, msg::triplet = default_host_triplet(args)); - return; - } - } + msg::println_warning(msgDefaultTriplet, msg::triplet = default_host_triplet(args)); } -#endif +#endif // ^^^ _WIN32 } }