From e7a6683e9d6b2f5d0bf24e9cc46b246eff7696f3 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Sat, 12 Aug 2023 00:09:41 -0700 Subject: [PATCH 01/48] Make registries distinguish between 'baseline is broken' and 'baseline missing'. --- include/vcpkg/paragraphparser.h | 4 +- include/vcpkg/paragraphs.h | 25 +- include/vcpkg/registries.h | 19 +- include/vcpkg/sourceparagraph.h | 4 +- src/vcpkg-test/manifests.cpp | 6 +- src/vcpkg-test/registries.cpp | 2 +- src/vcpkg/binaryparagraph.cpp | 2 +- src/vcpkg/commands.add-version.cpp | 14 +- src/vcpkg/commands.add.cpp | 7 +- src/vcpkg/commands.autocomplete.cpp | 4 +- src/vcpkg/commands.build.cpp | 2 +- src/vcpkg/commands.ci-verify-versions.cpp | 17 +- src/vcpkg/commands.format-manifest.cpp | 4 +- src/vcpkg/commands.install.cpp | 2 +- src/vcpkg/paragraphs.cpp | 110 ++++--- src/vcpkg/portfileprovider.cpp | 40 ++- src/vcpkg/registries.cpp | 346 +++++++++++----------- src/vcpkg/sourceparagraph.cpp | 5 +- 18 files changed, 350 insertions(+), 263 deletions(-) diff --git a/include/vcpkg/paragraphparser.h b/include/vcpkg/paragraphparser.h index 0ba8eb7b55..7dcc2059ee 100644 --- a/include/vcpkg/paragraphparser.h +++ b/include/vcpkg/paragraphparser.h @@ -49,11 +49,11 @@ namespace vcpkg using ParseExpected = vcpkg::ExpectedT, std::unique_ptr>; template - ExpectedL

map_parse_expected_to_localized_string(ParseExpected

&& parse_expected) + ExpectedL> map_parse_expected_to_localized_string(ParseExpected

&& parse_expected) { if (auto value = parse_expected.get()) { - return std::move(**value); + return std::move(*value); } return LocalizedString::from_raw(parse_expected.error()->to_string()); diff --git a/include/vcpkg/paragraphs.h b/include/vcpkg/paragraphs.h index 9718544f72..00c93261d0 100644 --- a/include/vcpkg/paragraphs.h +++ b/include/vcpkg/paragraphs.h @@ -5,9 +5,13 @@ #include #include +#include #include +#include +#include + namespace vcpkg::Paragraphs { uint64_t get_load_ports_stats(); @@ -22,11 +26,20 @@ namespace vcpkg::Paragraphs bool is_port_directory(const ReadOnlyFilesystem& fs, const Path& maybe_directory); - ParseExpected try_load_port(const ReadOnlyFilesystem& fs, const Path& port_directory); - ParseExpected try_load_port_text(const std::string& text, - StringView origin, - bool is_manifest, - MessageSink& warning_sink); + // If an error occurs, the Expected will be in the error state. + // Otherwise, if the port is known, the Optional contains the loaded port information. + // Otherwise, the Optional is disengaged. + ExpectedL> try_load_port(const ReadOnlyFilesystem& fs, + StringView port_name, + const Path& port_directory); + // Identical to try_load_port, but the port unknown condition is mapped to an error. + ExpectedL> try_load_port_required(const ReadOnlyFilesystem& fs, + StringView port_name, + const Path& port_directory); + ExpectedL> try_load_port_text(const std::string& text, + StringView origin, + bool is_manifest, + MessageSink& warning_sink); ExpectedL try_load_cached_package(const ReadOnlyFilesystem& fs, const Path& package_dir, @@ -35,7 +48,7 @@ namespace vcpkg::Paragraphs struct LoadResults { std::vector paragraphs; - std::vector> errors; + std::vector> errors; }; LoadResults try_load_all_registry_ports(const ReadOnlyFilesystem& fs, const RegistrySet& registries); diff --git a/include/vcpkg/registries.h b/include/vcpkg/registries.h index 717f4975c6..d059681609 100644 --- a/include/vcpkg/registries.h +++ b/include/vcpkg/registries.h @@ -76,19 +76,24 @@ namespace vcpkg { virtual StringLiteral kind() const = 0; - // returns nullptr if the port doesn't exist + // If an error occurs, the ExpectedL will be in an error state. + // Otherwise, if the port is known, returns a pointer to RegistryEntry describing the port. + // Otherwise, returns a nullptr unique_ptr. virtual ExpectedL> get_port_entry(StringView port_name) const = 0; - // appends the names of the ports to the out parameter - // may result in duplicated port names; make sure to Util::sort_unique_erase at the end + // Appends the names of the known ports to the out parameter. + // May result in duplicated port names; make sure to Util::sort_unique_erase at the end virtual ExpectedL append_all_port_names(std::vector& port_names) const = 0; - // appends the names of the ports to the out parameter if this can be known without + // Appends the names of the ports to the out parameter if this can be known without // network access. - // returns true if names were appended, otherwise returns false. + // Returns true iff names were appended. virtual ExpectedL try_append_all_port_names_no_network(std::vector& port_names) const = 0; - virtual ExpectedL get_baseline_version(StringView port_name) const = 0; + // If an error occurs, the ExpectedL will be in an error state. + // Otherwise, if the port is in the baseline, returns the version that baseline denotes. + // Otherwise, the Optional is disengaged. + virtual ExpectedL> get_baseline_version(StringView port_name) const = 0; virtual ~RegistryImplementation() = default; }; @@ -130,7 +135,7 @@ namespace vcpkg // the returned list is sorted by priority. std::vector registries_for_port(StringView name) const; - ExpectedL baseline_for_port(StringView port_name) const; + ExpectedL> baseline_for_port(StringView port_name) const; View registries() const { return registries_; } diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index fd2d0c3eae..77a02aa64a 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -214,8 +214,8 @@ namespace vcpkg std::string registry_location; }; - void print_error_message(Span> error_info_list); - inline void print_error_message(const std::unique_ptr& error_info_list) + void print_error_message(View error_info_list); + inline void print_error_message(const LocalizedString& error_info_list) { return print_error_message({&error_info_list, 1}); } diff --git a/src/vcpkg-test/manifests.cpp b/src/vcpkg-test/manifests.cpp index 696a9fc88e..4ca7936de3 100644 --- a/src/vcpkg-test/manifests.cpp +++ b/src/vcpkg-test/manifests.cpp @@ -45,7 +45,7 @@ static ParseExpected test_parse_project_manifest(const Json:: auto res = SourceControlFile::parse_project_manifest_object("", obj, null_sink); if (!res.has_value() && print == PrintErrors::Yes) { - print_error_message(res.error()); + print_error_message(LocalizedString::from_raw(res.error()->to_string())); } return res; } @@ -56,7 +56,7 @@ static ParseExpected test_parse_port_manifest(const Json::Obj auto res = SourceControlFile::parse_port_manifest_object("", obj, null_sink); if (!res.has_value() && print == PrintErrors::Yes) { - print_error_message(res.error()); + print_error_message(LocalizedString::from_raw(res.error()->to_string())); } return res; } @@ -886,7 +886,7 @@ TEST_CASE ("manifest construct maximum", "[manifests]") auto res = SourceControlFile::parse_port_manifest_object("", object, null_sink); if (!res.has_value()) { - print_error_message(res.error()); + print_error_message(LocalizedString::from_raw(res.error()->to_string())); } REQUIRE(res.has_value()); REQUIRE(*res.get() != nullptr); diff --git a/src/vcpkg-test/registries.cpp b/src/vcpkg-test/registries.cpp index 811ce92e96..f2de758545 100644 --- a/src/vcpkg-test/registries.cpp +++ b/src/vcpkg-test/registries.cpp @@ -28,7 +28,7 @@ namespace return !no_network_port_names.empty(); } - ExpectedL get_baseline_version(StringView) const override + ExpectedL> get_baseline_version(StringView) const override { return LocalizedString::from_raw("error"); } diff --git a/src/vcpkg/binaryparagraph.cpp b/src/vcpkg/binaryparagraph.cpp index b412fa9154..212e13e9b3 100644 --- a/src/vcpkg/binaryparagraph.cpp +++ b/src/vcpkg/binaryparagraph.cpp @@ -90,7 +90,7 @@ namespace vcpkg if (const auto err = parser.error_info(this->spec.to_string())) { msg::println_error(msgErrorParsingBinaryParagraph, msg::spec = this->spec); - print_error_message(err); + print_error_message(LocalizedString::from_raw(err->to_string())); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/commands.add-version.cpp b/src/vcpkg/commands.add-version.cpp index f63020f8e5..78bd2e1361 100644 --- a/src/vcpkg/commands.add-version.cpp +++ b/src/vcpkg/commands.add-version.cpp @@ -412,17 +412,17 @@ namespace vcpkg continue; } - auto maybe_scf = Paragraphs::try_load_port(fs, paths.builtin_ports_directory() / port_name); - if (!maybe_scf) + auto maybe_scf = + Paragraphs::try_load_port_required(fs, port_name, paths.builtin_ports_directory() / port_name); + auto scf = maybe_scf.get(); + if (!scf) { msg::println_error(msgAddVersionLoadPortFailed, msg::package_name = port_name); - print_error_message(maybe_scf.error()); + msg::println(Color::error, maybe_scf.error()); Checks::check_exit(VCPKG_LINE_INFO, !add_all); continue; } - const auto& scf = maybe_scf.value(VCPKG_LINE_INFO); - if (!skip_formatting_check) { // check if manifest file is property formatted @@ -430,7 +430,7 @@ namespace vcpkg if (fs.exists(path_to_manifest, IgnoreErrors{})) { const auto current_file_content = fs.read_contents(path_to_manifest, VCPKG_LINE_INFO); - const auto json = serialize_manifest(*scf); + const auto json = serialize_manifest(**scf); const auto formatted_content = Json::stringify(json); if (current_file_content != formatted_content) { @@ -454,7 +454,7 @@ namespace vcpkg msg::println_warning(msgAddVersionUncommittedChanges, msg::package_name = port_name); } - const auto& schemed_version = scf->to_schemed_version(); + const auto& schemed_version = (*scf)->to_schemed_version(); auto git_tree_it = git_tree_map.find(port_name); if (git_tree_it == git_tree_map.end()) diff --git a/src/vcpkg/commands.add.cpp b/src/vcpkg/commands.add.cpp index c3244a2d1e..34c413d92e 100644 --- a/src/vcpkg/commands.add.cpp +++ b/src/vcpkg/commands.add.cpp @@ -96,14 +96,15 @@ namespace vcpkg auto maybe_manifest_scf = SourceControlFile::parse_project_manifest_object(manifest->path, manifest->manifest, stdout_sink); - if (!maybe_manifest_scf) + auto pmanifest_scf = maybe_manifest_scf.get(); + if (!pmanifest_scf) { - print_error_message(maybe_manifest_scf.error()); + print_error_message(LocalizedString::from_raw(maybe_manifest_scf.error()->to_string())); msg::println(Color::error, msg::msgSeeURL, msg::url = docs::manifests_url); Checks::exit_fail(VCPKG_LINE_INFO); } - auto& manifest_scf = *maybe_manifest_scf.value(VCPKG_LINE_INFO); + auto& manifest_scf = **pmanifest_scf; for (const auto& spec : specs) { auto dep = Util::find_if(manifest_scf.core_paragraph->dependencies, [&spec](Dependency& dep) { diff --git a/src/vcpkg/commands.autocomplete.cpp b/src/vcpkg/commands.autocomplete.cpp index 39321f0014..d43c755a25 100644 --- a/src/vcpkg/commands.autocomplete.cpp +++ b/src/vcpkg/commands.autocomplete.cpp @@ -104,8 +104,8 @@ namespace vcpkg StringView port_name{last_arg.begin(), colon}; StringView triplet_prefix{colon + 1, last_arg.end()}; // TODO: Support autocomplete for ports in --overlay-ports - auto maybe_port = - Paragraphs::try_load_port(paths.get_filesystem(), paths.builtin_ports_directory() / port_name); + auto maybe_port = Paragraphs::try_load_port_required( + paths.get_filesystem(), port_name, paths.builtin_ports_directory() / port_name); if (!maybe_port) { Checks::exit_success(VCPKG_LINE_INFO); diff --git a/src/vcpkg/commands.build.cpp b/src/vcpkg/commands.build.cpp index 9f9d1e0040..9af5c20830 100644 --- a/src/vcpkg/commands.build.cpp +++ b/src/vcpkg/commands.build.cpp @@ -1684,7 +1684,7 @@ namespace vcpkg if (const auto err = parser.error_info("PostBuildInformation")) { - print_error_message(err); + print_error_message(LocalizedString::from_raw(err->to_string())); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index 15a3d0c3ea..ee9d6c469f 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -72,7 +72,8 @@ namespace const auto& file = maybe_file.value_or_exit(VCPKG_LINE_INFO); auto maybe_scf = Paragraphs::try_load_port_text(file, treeish, control_file == "vcpkg.json", stdout_sink); - if (!maybe_scf) + auto scf = maybe_scf.get(); + if (!scf) { return {msg::format_error(msgWhileParsingVersionsForPort, msg::package_name = port_name, @@ -82,12 +83,11 @@ namespace .append_raw('\n') .append(msgWhileLoadingPortFromGitTree, msg::commit_sha = treeish) .append_raw('\n') - .append_raw(maybe_scf.error()->error), + .append(maybe_scf.error()), expected_right_tag}; } - const auto& scf = maybe_scf.value(VCPKG_LINE_INFO); - auto&& git_tree_version = scf->to_schemed_version(); + auto&& git_tree_version = (*scf)->to_schemed_version(); if (version_entry.first.version != git_tree_version.version) { return { @@ -122,16 +122,17 @@ namespace } } - auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), port_path); - if (!maybe_scf) + auto maybe_scf = Paragraphs::try_load_port_required(paths.get_filesystem(), port_name, port_path); + auto scf = maybe_scf.get(); + if (!scf) { return {msg::format_error(msgWhileLoadingLocalPort, msg::package_name = port_name) .append_raw('\n') - .append_raw(maybe_scf.error()->error), + .append(maybe_scf.error()), expected_right_tag}; } - const auto local_port_version = maybe_scf.value(VCPKG_LINE_INFO)->to_schemed_version(); + const auto local_port_version = (*scf)->to_schemed_version(); auto versions_end = versions->end(); auto it = diff --git a/src/vcpkg/commands.format-manifest.cpp b/src/vcpkg/commands.format-manifest.cpp index 3e5659f828..be23ab175b 100644 --- a/src/vcpkg/commands.format-manifest.cpp +++ b/src/vcpkg/commands.format-manifest.cpp @@ -49,7 +49,7 @@ namespace if (!scf) { msg::println_error(msgFailedToParseManifest, msg::path = path_string); - print_error_message(scf.error()); + print_error_message(LocalizedString::from_raw(scf.error()->to_string())); msg::println(); return nullopt; } @@ -82,7 +82,7 @@ namespace if (!scf_res) { msg::println_error(msgFailedToParseControl, msg::path = control_path); - print_error_message(scf_res.error()); + print_error_message(LocalizedString::from_raw(scf_res.error()->to_string())); return {}; } diff --git a/src/vcpkg/commands.install.cpp b/src/vcpkg/commands.install.cpp index 6c333d2c1f..5755636079 100644 --- a/src/vcpkg/commands.install.cpp +++ b/src/vcpkg/commands.install.cpp @@ -1104,7 +1104,7 @@ namespace vcpkg SourceControlFile::parse_project_manifest_object(manifest->path, manifest->manifest, stdout_sink); if (!maybe_manifest_scf) { - print_error_message(maybe_manifest_scf.error()); + print_error_message(LocalizedString::from_raw(maybe_manifest_scf.error()->to_string())); msg::println(msgExtendedDocumentationAtUrl, msg::url = docs::manifests_url); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/paragraphs.cpp b/src/vcpkg/paragraphs.cpp index 8166b9adc3..93eba01246 100644 --- a/src/vcpkg/paragraphs.cpp +++ b/src/vcpkg/paragraphs.cpp @@ -13,6 +13,8 @@ #include #include +#include + static std::atomic g_load_ports_stats(0); namespace vcpkg @@ -373,29 +375,29 @@ namespace vcpkg::Paragraphs fs.exists(maybe_directory / "vcpkg.json", IgnoreErrors{}); } - static ParseExpected try_load_manifest_text(const std::string& text, - StringView origin, - MessageSink& warning_sink) + static ExpectedL> try_load_manifest_text(const std::string& text, + StringView origin, + MessageSink& warning_sink) { auto res = Json::parse(text, origin); if (auto val = res.get()) { if (val->value.is_object()) { - return SourceControlFile::parse_port_manifest_object( - origin, val->value.object(VCPKG_LINE_INFO), warning_sink); + return map_parse_expected_to_localized_string(SourceControlFile::parse_port_manifest_object( + origin, val->value.object(VCPKG_LINE_INFO), warning_sink)); } - return ParseControlErrorInfo::from_error(origin, msg::format(msgJsonValueNotObject)); + return msg::format(msgJsonValueNotObject); } - return ParseControlErrorInfo::from_error(origin, LocalizedString::from_raw(res.error()->to_string())); + return LocalizedString::from_raw(res.error()->to_string()); } - ParseExpected try_load_port_text(const std::string& text, - StringView origin, - bool is_manifest, - MessageSink& warning_sink) + ExpectedL> try_load_port_text(const std::string& text, + StringView origin, + bool is_manifest, + MessageSink& warning_sink) { StatsTimer timer(g_load_ports_stats); @@ -407,19 +409,21 @@ namespace vcpkg::Paragraphs ExpectedL> pghs = parse_paragraphs(StringView{text}, origin); if (auto vector_pghs = pghs.get()) { - return SourceControlFile::parse_control_file(origin, std::move(*vector_pghs)); + return map_parse_expected_to_localized_string( + SourceControlFile::parse_control_file(origin, std::move(*vector_pghs))); } - return ParseControlErrorInfo::from_error(origin, std::move(pghs).error()); + return std::move(pghs).error(); } - ParseExpected try_load_port(const ReadOnlyFilesystem& fs, const Path& port_directory) + ExpectedL> try_load_port(const ReadOnlyFilesystem& fs, + StringView port_name, + const Path& port_directory) { StatsTimer timer(g_load_ports_stats); const auto manifest_path = port_directory / "vcpkg.json"; const auto control_path = port_directory / "CONTROL"; - const auto port_name = port_directory.filename(); std::error_code ec; auto manifest_contents = fs.read_contents(manifest_path, ec); if (ec) @@ -439,31 +443,60 @@ namespace vcpkg::Paragraphs ExpectedL> pghs = get_paragraphs(fs, control_path); if (auto vector_pghs = pghs.get()) { - return SourceControlFile::parse_control_file(control_path, std::move(*vector_pghs)); + auto maybe_parsed_control = + SourceControlFile::parse_control_file(control_path, std::move(*vector_pghs)); + if (auto parsed_control = maybe_parsed_control.get()) + { + return std::move(*parsed_control); + } + + return LocalizedString::from_raw(maybe_parsed_control.error()->to_string()); } - return ParseControlErrorInfo::from_error(port_name, std::move(pghs).error()); + return std::move(pghs).error(); } if (fs.exists(port_directory, IgnoreErrors{})) { - return ParseControlErrorInfo::from_error(port_name, - msg::format_error(msgPortMissingManifest, - msg::package_name = port_name, - msg::path = port_directory)); + return msg::format_error( + msgPortMissingManifest, msg::package_name = port_name, msg::path = port_directory); } - return ParseControlErrorInfo::from_error( - port_name, msg::format_error(msgPortDoesNotExist, msg::package_name = port_name)); + return std::unique_ptr(); } if (fs.exists(control_path, IgnoreErrors{})) { - return ParseControlErrorInfo::from_error( - port_name, msg::format_error(msgManifestConflict, msg::path = port_directory)); + return msg::format_error(msgManifestConflict, msg::path = port_directory); } - return try_load_manifest_text(manifest_contents, manifest_path, stdout_sink); + auto maybe_parsed = try_load_manifest_text(manifest_contents, manifest_path, stdout_sink); + if (auto parsed = maybe_parsed.get()) + { + return std::move(*parsed); + } + + return std::move(maybe_parsed).error(); + } + + ExpectedL> try_load_port_required(const ReadOnlyFilesystem& fs, + StringView port_name, + const Path& port_directory) + { + auto maybe_maybe_res = try_load_port(fs, port_name, port_directory); + auto maybe_res = maybe_maybe_res.get(); + if (!maybe_res) + { + return std::move(maybe_maybe_res).error(); + } + + auto res = maybe_res->get(); + if (!res) + { + return msg::format_error(msgPortDoesNotExist, msg::package_name = port_name); + } + + return std::move(*maybe_res); } ExpectedL try_load_cached_package(const ReadOnlyFilesystem& fs, @@ -513,7 +546,7 @@ namespace vcpkg::Paragraphs continue; } - auto maybe_baseline_version = impl->get_baseline_version(port_name); + auto maybe_baseline_version = impl->get_baseline_version(port_name).value_or_exit(VCPKG_LINE_INFO); auto baseline_version = maybe_baseline_version.get(); if (!baseline_version) continue; // port is attributed to this registry, but it is not in the baseline auto maybe_port_entry = impl->get_port_entry(port_name); @@ -523,7 +556,7 @@ namespace vcpkg::Paragraphs auto maybe_port_location = (*port_entry)->get_version(*baseline_version); const auto port_location = maybe_port_location.get(); if (!port_location) continue; // baseline version was not in version db (registry consistency issue) - auto maybe_spgh = try_load_port(fs, port_location->path); + auto maybe_spgh = try_load_port_required(fs, port_name, port_location->path); if (const auto spgh = maybe_spgh.get()) { ret.paragraphs.push_back({ @@ -534,7 +567,9 @@ namespace vcpkg::Paragraphs } else { - ret.errors.emplace_back(std::move(maybe_spgh).error()); + ret.errors.emplace_back(std::piecewise_construct, + std::forward_as_tuple(port_name.data(), port_name.size()), + std::forward_as_tuple(std::move(maybe_spgh).error())); } } @@ -547,14 +582,20 @@ namespace vcpkg::Paragraphs { if (Debug::g_debugging) { - print_error_message(results.errors); + print_error_message(LocalizedString::from_raw( + Strings::join("\n", + results.errors, + [](const std::pair& err) -> const LocalizedString& { + return err.second; + }))); } else { for (auto&& error : results.errors) { - msg::println_warning(msgErrorWhileParsing, msg::path = error->name); + msg::println_warning(msgErrorWhileParsing, msg::path = error.first); } + msg::println_warning(msgGetParseFailureInfo); } } @@ -580,14 +621,17 @@ namespace vcpkg::Paragraphs for (auto&& path : port_dirs) { - auto maybe_spgh = try_load_port(fs, path); + auto port_name = path.filename(); + auto maybe_spgh = try_load_port_required(fs, port_name, path); if (const auto spgh = maybe_spgh.get()) { ret.paragraphs.push_back({std::move(*spgh), std::move(path)}); } else { - ret.errors.emplace_back(std::move(maybe_spgh).error()); + ret.errors.emplace_back(std::piecewise_construct, + std::forward_as_tuple(port_name.data(), port_name.size()), + std::forward_as_tuple(std::move(maybe_spgh).error())); } } diff --git a/src/vcpkg/portfileprovider.cpp b/src/vcpkg/portfileprovider.cpp index 410d4cc301..6830d1ef37 100644 --- a/src/vcpkg/portfileprovider.cpp +++ b/src/vcpkg/portfileprovider.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -108,22 +109,27 @@ namespace vcpkg virtual ExpectedL get_baseline_version(StringView port_name) const override { - auto it = m_baseline_cache.find(port_name); - if (it != m_baseline_cache.end()) - { - return it->second; - } - else - { - auto version = registry_set.baseline_for_port(port_name); - m_baseline_cache.emplace(port_name.to_string(), version); - return version; - } + return m_baseline_cache.get_lazy(port_name, [this, port_name]() -> ExpectedL { + auto maybe_maybe_version = registry_set.baseline_for_port(port_name); + auto maybe_version = maybe_maybe_version.get(); + if (!maybe_version) + { + return std::move(maybe_maybe_version).error(); + } + + auto version = maybe_version->get(); + if (!version) + { + return msg::format_error(msgPortNotInBaseline, msg::package_name = port_name); + } + + return std::move(*version); + }); } private: const RegistrySet& registry_set; - mutable std::map, std::less<>> m_baseline_cache; + mutable Cache> m_baseline_cache; }; struct VersionedPortfileProviderImpl : IFullVersionedPortfileProvider @@ -182,7 +188,8 @@ namespace vcpkg auto maybe_path = ent->get()->get_version(version_spec.version); if (auto path = maybe_path.get()) { - auto maybe_control_file = Paragraphs::try_load_port(m_fs, path->path); + auto maybe_control_file = + Paragraphs::try_load_port_required(m_fs, version_spec.port_name, path->path); if (auto scf = maybe_control_file.get()) { auto scf_vspec = scf->get()->to_version_spec(); @@ -289,7 +296,7 @@ namespace vcpkg // Try loading individual port if (Paragraphs::is_port_directory(m_fs, ports_dir)) { - auto maybe_scf = Paragraphs::try_load_port(m_fs, ports_dir); + auto maybe_scf = Paragraphs::try_load_port_required(m_fs, port_name, ports_dir); if (auto scfp = maybe_scf.get()) { auto& scf = *scfp; @@ -313,7 +320,7 @@ namespace vcpkg auto ports_spec = ports_dir / port_name; if (Paragraphs::is_port_directory(m_fs, ports_spec)) { - auto found_scf = Paragraphs::try_load_port(m_fs, ports_spec); + auto found_scf = Paragraphs::try_load_port_required(m_fs, port_name, ports_spec); if (auto scfp = found_scf.get()) { auto& scf = *scfp; @@ -321,6 +328,7 @@ namespace vcpkg { return SourceControlFileAndLocation{std::move(scf), std::move(ports_spec)}; } + Checks::msg_exit_maybe_upgrade( VCPKG_LINE_INFO, msg::format(msgFailedToLoadPort, msg::package_name = port_name, msg::path = ports_spec) @@ -363,7 +371,7 @@ namespace vcpkg // Try loading individual port if (Paragraphs::is_port_directory(m_fs, ports_dir)) { - auto maybe_scf = Paragraphs::try_load_port(m_fs, ports_dir); + auto maybe_scf = Paragraphs::try_load_port_required(m_fs, ports_dir.filename(), ports_dir); if (auto scfp = maybe_scf.get()) { SourceControlFileAndLocation scfl{std::move(*scfp), ports_dir}; diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index fc80a08108..eabf8e8a5d 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -257,7 +257,7 @@ namespace ExpectedL try_append_all_port_names_no_network(std::vector& port_names) const override; - ExpectedL get_baseline_version(StringView) const override; + ExpectedL> get_baseline_version(StringView) const override; private: friend struct GitRegistryEntry; @@ -454,23 +454,21 @@ namespace ExpectedL try_append_all_port_names_no_network(std::vector& port_names) const override; - ExpectedL get_baseline_version(StringView port_name) const override; + ExpectedL> get_baseline_version(StringView port_name) const override; ~BuiltinFilesRegistry() = default; DelayedInit m_baseline; private: - const ExpectedL& get_scf(const Path& path) const + const ExpectedL>& get_scf(StringView port_name, const Path& path) const { - return m_scfs.get_lazy(path, [this, &path]() { - return map_parse_expected_to_localized_string(Paragraphs::try_load_port(m_fs, path)); - }); + return m_scfs.get_lazy(path, [&, this]() { return Paragraphs::try_load_port(m_fs, port_name, path); }); } const ReadOnlyFilesystem& m_fs; const Path m_builtin_ports_directory; - Cache> m_scfs; + Cache>> m_scfs; }; constexpr StringLiteral BuiltinFilesRegistry::s_kind; @@ -495,12 +493,12 @@ namespace ExpectedL try_append_all_port_names_no_network(std::vector& port_names) const override; - ExpectedL get_baseline_version(StringView port_name) const override; + ExpectedL> get_baseline_version(StringView port_name) const override; ~BuiltinGitRegistry() = default; std::string m_baseline_identifier; - DelayedInit m_baseline; + DelayedInit> m_baseline; private: std::unique_ptr m_files_impl; @@ -532,7 +530,7 @@ namespace return msg::format_error(msgErrorRequireBaseline); } - ExpectedL get_baseline_version(StringView) const override + ExpectedL> get_baseline_version(StringView) const override { return msg::format_error(msgErrorRequireBaseline); } @@ -556,14 +554,14 @@ namespace ExpectedL try_append_all_port_names_no_network(std::vector& port_names) const override; - ExpectedL get_baseline_version(StringView) const override; + ExpectedL> get_baseline_version(StringView) const override; private: const ReadOnlyFilesystem& m_fs; Path m_path; std::string m_baseline_identifier; - DelayedInit m_baseline; + DelayedInit>> m_baseline; }; Path relative_path_to_versions(StringView port_name); @@ -685,40 +683,48 @@ namespace ExpectedL> BuiltinFilesRegistry::get_port_entry(StringView port_name) const { auto port_directory = m_builtin_ports_directory / port_name; - if (m_fs.exists(port_directory, IgnoreErrors{})) + const auto& maybe_maybe_scf = get_scf(port_name, port_directory); + const auto maybe_scf = maybe_maybe_scf.get(); + if (!maybe_scf) { - const auto& found_scf = get_scf(port_directory); - if (auto scf = found_scf.get()) - { - if (scf->core_paragraph->name == port_name) - { - return std::make_unique( - scf->core_paragraph->name, port_directory, scf->to_version()); - } + return maybe_maybe_scf.error(); + } - return msg::format_error(msgUnexpectedPortName, - msg::expected = scf->core_paragraph->name, - msg::actual = port_name, - msg::path = port_directory); - } + auto scf = maybe_scf->get(); + if (!scf) + { + return std::unique_ptr(); + } - return found_scf.error(); + if (scf->core_paragraph->name == port_name) + { + return std::make_unique( + scf->core_paragraph->name, port_directory, scf->to_version()); } - return nullptr; + return msg::format_error(msgUnexpectedPortName, + msg::expected = scf->core_paragraph->name, + msg::actual = port_name, + msg::path = port_directory); } - ExpectedL BuiltinFilesRegistry::get_baseline_version(StringView port_name) const + ExpectedL> BuiltinFilesRegistry::get_baseline_version(StringView port_name) const { // if a baseline is not specified, use the ports directory version - auto port_path = m_builtin_ports_directory / port_name; - const auto& maybe_scf = get_scf(port_path); - if (auto pscf = maybe_scf.get()) + const auto& maybe_maybe_scf = get_scf(port_name, m_builtin_ports_directory / port_name); + auto maybe_scf = maybe_maybe_scf.get(); + if (!maybe_scf) { - return pscf->to_version(); + return maybe_maybe_scf.error(); } - return maybe_scf.error(); + auto scf = maybe_scf->get(); + if (!scf) + { + return Optional(); + } + + return scf->to_version(); } ExpectedL BuiltinFilesRegistry::append_all_port_names(std::vector& out) const @@ -772,31 +778,49 @@ namespace return res; } - ExpectedL BuiltinGitRegistry::get_baseline_version(StringView port_name) const + ExpectedL> BuiltinGitRegistry::get_baseline_version(StringView port_name) const { - const auto& baseline = m_baseline.get([this]() -> Baseline { + const auto& maybe_baseline = m_baseline.get([this]() -> ExpectedL { auto maybe_path = git_checkout_baseline(m_paths, m_baseline_identifier); - if (!maybe_path) + auto path = maybe_path.get(); + if (!path) { - msg::println(Color::error, LocalizedString::from_raw(maybe_path.error())); - msg::println(Color::error, LocalizedString::from_raw(m_paths.get_current_git_sha_baseline_message())); - Checks::exit_fail(VCPKG_LINE_INFO); + return std::move(maybe_path) + .error() + .append_raw('\n') + .append_raw(m_paths.get_current_git_sha_baseline_message()); } - auto b = load_baseline_versions(m_paths.get_filesystem(), *maybe_path.get()).value_or_exit(VCPKG_LINE_INFO); - if (auto p = b.get()) + + auto maybe_maybe_baseline = load_baseline_versions(m_paths.get_filesystem(), *path); + auto maybe_baseline = maybe_maybe_baseline.get(); + if (!maybe_baseline) + { + return std::move(maybe_maybe_baseline).error(); + } + + auto baseline = maybe_baseline->get(); + if (!baseline) { - return std::move(*p); + return msg::format_error( + msgCouldNotFindBaseline, msg::commit_sha = m_baseline_identifier, msg::path = *path); } - Checks::msg_exit_with_message( - VCPKG_LINE_INFO, msgBaselineFileNoDefaultField, msg::commit_sha = m_baseline_identifier); + + return std::move(*baseline); }); - auto it = baseline.find(port_name); - if (it != baseline.end()) + auto baseline = maybe_baseline.get(); + if (!baseline) + { + return maybe_baseline.error(); + } + + auto it = baseline->find(port_name); + if (it != baseline->end()) { return it->second; } - return msg::format(msg::msgErrorMessage).append(msgPortNotInBaseline, msg::package_name = port_name); + + return Optional(); } ExpectedL BuiltinGitRegistry::append_all_port_names(std::vector& out) const @@ -818,41 +842,32 @@ namespace // } BuiltinGitRegistry::RegistryImplementation // { FilesystemRegistry::RegistryImplementation - ExpectedL FilesystemRegistry::get_baseline_version(StringView port_name) const + ExpectedL> FilesystemRegistry::get_baseline_version(StringView port_name) const { - const auto& baseline = m_baseline.get([this]() -> Baseline { + const auto& maybe_maybe_baseline = m_baseline.get([this]() -> ExpectedL> { auto path_to_baseline = m_path / registry_versions_dir_name / "baseline.json"; - auto res_baseline = load_baseline_versions(m_fs, path_to_baseline, m_baseline_identifier); - if (auto opt_baseline = res_baseline.get()) - { - if (auto p = opt_baseline->get()) - { - return std::move(*p); - } - - if (m_baseline_identifier.size() == 0) - { - return {}; - } - - Checks::msg_exit_with_error(VCPKG_LINE_INFO, - msgCouldNotFindBaseline, - msg::commit_sha = m_baseline_identifier, - msg::path = path_to_baseline); - } - - Checks::msg_exit_maybe_upgrade(VCPKG_LINE_INFO, res_baseline.error()); + return load_baseline_versions(m_fs, path_to_baseline, m_baseline_identifier); }); - auto it = baseline.find(port_name); - if (it != baseline.end()) + auto maybe_baseline = maybe_maybe_baseline.get(); + if (!maybe_baseline) { - return it->second; + return maybe_maybe_baseline.error(); } - else + + auto baseline = maybe_baseline->get(); + if (!baseline) { - return msg::format(msg::msgErrorMessage).append(msgPortNotInBaseline, msg::package_name = port_name); + return Optional(); } + + auto it = baseline->find(port_name); + if (it != baseline->end()) + { + return it->second; + } + + return Optional(); } ExpectedL> FilesystemRegistry::get_port_entry(StringView port_name) const @@ -964,109 +979,108 @@ namespace { } - ExpectedL GitRegistry::get_baseline_version(StringView port_name) const + ExpectedL> GitRegistry::get_baseline_version(StringView port_name) const { - const auto& baseline = - m_baseline - .get([this, port_name]() -> ExpectedL { - // We delay baseline validation until here to give better error messages and suggestions - if (!is_git_commit_sha(m_baseline_identifier)) - { - auto& maybe_lock_entry = get_lock_entry(); - auto lock_entry = maybe_lock_entry.get(); - if (!lock_entry) - { - return maybe_lock_entry.error(); - } - - auto maybe_up_to_date = lock_entry->ensure_up_to_date(m_paths); - if (maybe_up_to_date) - { - return msg::format_error(msgGitRegistryMustHaveBaseline, - msg::url = m_repo, - msg::commit_sha = lock_entry->commit_id()); - } - - return std::move(maybe_up_to_date).error(); - } + const auto& maybe_baseline = m_baseline.get([this, port_name]() -> ExpectedL { + // We delay baseline validation until here to give better error messages and suggestions + if (!is_git_commit_sha(m_baseline_identifier)) + { + auto& maybe_lock_entry = get_lock_entry(); + auto lock_entry = maybe_lock_entry.get(); + if (!lock_entry) + { + return maybe_lock_entry.error(); + } - auto path_to_baseline = Path(registry_versions_dir_name.to_string()) / "baseline.json"; - auto maybe_contents = - m_paths.git_show_from_remote_registry(m_baseline_identifier, path_to_baseline); - if (!maybe_contents) - { - auto& maybe_lock_entry = get_lock_entry(); - auto lock_entry = maybe_lock_entry.get(); - if (!lock_entry) - { - return maybe_lock_entry.error(); - } - - auto maybe_up_to_date = lock_entry->ensure_up_to_date(m_paths); - if (!maybe_up_to_date) - { - return std::move(maybe_up_to_date).error(); - } - - maybe_contents = m_paths.git_show_from_remote_registry(m_baseline_identifier, path_to_baseline); - } + auto maybe_up_to_date = lock_entry->ensure_up_to_date(m_paths); + if (maybe_up_to_date) + { + return msg::format_error( + msgGitRegistryMustHaveBaseline, msg::url = m_repo, msg::commit_sha = lock_entry->commit_id()); + } - if (!maybe_contents) - { - msg::println(msgFetchingBaselineInfo, msg::package_name = m_repo); - auto maybe_err = m_paths.git_fetch(m_repo, m_baseline_identifier); - if (!maybe_err) - { - get_global_metrics_collector().track_define( - DefineMetric::RegistriesErrorCouldNotFindBaseline); - return msg::format_error(msgFailedToFetchRepo, msg::url = m_repo) - .append_raw('\n') - .append(maybe_err.error()); - } + return std::move(maybe_up_to_date).error(); + } - maybe_contents = m_paths.git_show_from_remote_registry(m_baseline_identifier, path_to_baseline); - } + auto path_to_baseline = Path(registry_versions_dir_name.to_string()) / "baseline.json"; + auto maybe_contents = m_paths.git_show_from_remote_registry(m_baseline_identifier, path_to_baseline); + if (!maybe_contents) + { + auto& maybe_lock_entry = get_lock_entry(); + auto lock_entry = maybe_lock_entry.get(); + if (!lock_entry) + { + return maybe_lock_entry.error(); + } - if (!maybe_contents) - { - get_global_metrics_collector().track_define(DefineMetric::RegistriesErrorCouldNotFindBaseline); - return msg::format_error(msgCouldNotFindBaselineInCommit, - msg::url = m_repo, - msg::commit_sha = m_baseline_identifier, - msg::package_name = port_name) - .append_raw('\n') - .append_raw(maybe_contents.error()); - } + auto maybe_up_to_date = lock_entry->ensure_up_to_date(m_paths); + if (!maybe_up_to_date) + { + return std::move(maybe_up_to_date).error(); + } - auto contents = maybe_contents.get(); - auto res_baseline = parse_baseline_versions(*contents, "default", path_to_baseline); - if (auto opt_baseline = res_baseline.get()) - { - if (auto p = opt_baseline->get()) - { - return std::move(*p); - } - - get_global_metrics_collector().track_define(DefineMetric::RegistriesErrorCouldNotFindBaseline); - return msg::format_error( - msgBaselineMissingDefault, msg::commit_sha = m_baseline_identifier, msg::url = m_repo); - } + maybe_contents = m_paths.git_show_from_remote_registry(m_baseline_identifier, path_to_baseline); + } - return msg::format_error(msgErrorWhileFetchingBaseline, - msg::value = m_baseline_identifier, - msg::package_name = m_repo) + if (!maybe_contents) + { + msg::println(msgFetchingBaselineInfo, msg::package_name = m_repo); + auto maybe_err = m_paths.git_fetch(m_repo, m_baseline_identifier); + if (!maybe_err) + { + get_global_metrics_collector().track_define(DefineMetric::RegistriesErrorCouldNotFindBaseline); + return msg::format_error(msgFailedToFetchRepo, msg::url = m_repo) .append_raw('\n') - .append(res_baseline.error()); - }) - .value_or_exit(VCPKG_LINE_INFO); + .append(maybe_err.error()); + } + + maybe_contents = m_paths.git_show_from_remote_registry(m_baseline_identifier, path_to_baseline); + } + + if (!maybe_contents) + { + get_global_metrics_collector().track_define(DefineMetric::RegistriesErrorCouldNotFindBaseline); + return msg::format_error(msgCouldNotFindBaselineInCommit, + msg::url = m_repo, + msg::commit_sha = m_baseline_identifier, + msg::package_name = port_name) + .append_raw('\n') + .append_raw(maybe_contents.error()); + } + + auto contents = maybe_contents.get(); + auto res_baseline = parse_baseline_versions(*contents, "default", path_to_baseline); + if (auto opt_baseline = res_baseline.get()) + { + if (auto p = opt_baseline->get()) + { + return std::move(*p); + } + + get_global_metrics_collector().track_define(DefineMetric::RegistriesErrorCouldNotFindBaseline); + return msg::format_error( + msgBaselineMissingDefault, msg::commit_sha = m_baseline_identifier, msg::url = m_repo); + } + + return msg::format_error( + msgErrorWhileFetchingBaseline, msg::value = m_baseline_identifier, msg::package_name = m_repo) + .append_raw('\n') + .append(res_baseline.error()); + }); + + auto baseline = maybe_baseline.get(); + if (!baseline) + { + return maybe_baseline.error(); + } - auto it = baseline.find(port_name); - if (it != baseline.end()) + auto it = baseline->find(port_name); + if (it != baseline->end()) { return it->second; } - return msg::format(msg::msgErrorMessage).append(msgPortNotInBaseline, msg::package_name = port_name); + return Optional(); } ExpectedL GitRegistry::append_all_port_names(std::vector& out) const @@ -1513,7 +1527,7 @@ namespace vcpkg return Util::fmap(std::move(candidates), [](const RegistryCandidate& target) { return target.impl; }); } - ExpectedL RegistrySet::baseline_for_port(StringView port_name) const + ExpectedL> RegistrySet::baseline_for_port(StringView port_name) const { auto impl = registry_for_port(port_name); if (!impl) return msg::format(msg::msgErrorMessage).append(msgNoRegistryForPort, msg::package_name = port_name); diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 3cab387036..5e21d6a32e 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -1521,9 +1521,10 @@ namespace vcpkg return Strings::starts_with(sv, "Error") || Strings::starts_with(sv, "error: "); } - void print_error_message(Span> error_info_list) + void print_error_message(View error_info_list) { - auto msg = ParseControlErrorInfo::format_errors(error_info_list); + auto msg = Strings::join("\n", error_info_list, [](const LocalizedString& ls) { return ls.data(); }); + msg.push_back('\n'); // To preserve previous behavior, each line starting with "Error" should be error-colored. All other lines // should be neutral color. From 09e135ca29de13d20c9eb2a6c589d5ade88de6cf Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 14 Aug 2023 21:29:12 -0700 Subject: [PATCH 02/48] Fix move on constant variable. --- src/vcpkg/registries.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index eabf8e8a5d..51e97532fc 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -586,7 +586,7 @@ namespace const auto super_directories = maybe_super_directories.get(); if (!super_directories) { - return std::move(maybe_super_directories.error()); + return maybe_super_directories.error(); } for (auto&& super_directory : *super_directories) From 4d8ca9e1c61b952fb29e202f2f4f1b6807432d75 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 18 Sep 2023 18:06:56 -0700 Subject: [PATCH 03/48] Fix merge conflict error. --- src/vcpkg/paragraphs.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/vcpkg/paragraphs.cpp b/src/vcpkg/paragraphs.cpp index 93eba01246..238846dc83 100644 --- a/src/vcpkg/paragraphs.cpp +++ b/src/vcpkg/paragraphs.cpp @@ -431,11 +431,9 @@ namespace vcpkg::Paragraphs const auto exists = ec != std::errc::no_such_file_or_directory; if (exists) { - auto formatted = msg::format_error(msgFailedToParseManifest, msg::path = manifest_path) - .append_raw("\n") - .append(format_filesystem_call_error(ec, "read_contents", {manifest_path})); - - return ParseControlErrorInfo::from_error(port_name, std::move(formatted)); + return msg::format_error(msgFailedToParseManifest, msg::path = manifest_path) + .append_raw("\n") + .append(format_filesystem_call_error(ec, "read_contents", {manifest_path})); } if (fs.exists(control_path, IgnoreErrors{})) From 21bb63300bf39c89315cb54526c5aa05e0f48861 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 20 Sep 2023 19:36:53 -0700 Subject: [PATCH 04/48] Substantially overhaul how x-ci-verify-versions works: * Print error messages naming the file we're complaining about so that IDEs etc. can go to the file, (Using the standard path: kind: message format) * Record the location in try_load_port and friends instead of requiring callers recover that themselves. * Make load_git_versions_file return the expected path of the versions file so that callers need not recover that themselves. * Delete registry_location from SourceControlFileAndLocation because it is not ever set. (I don't mind this member existing if there's data to go there but right now, there is not). * Deduplicate 'try vcpkg.json, also try CONTROL' behavior from x-add-version and x-ci-verify-versions. * Don't stop validating versions information at the first error. The remaining places that are still thinking about adding / "vcpkg.json" are now only: * format-manifest when deciding the new path after parsing a CONTROL * new when deciding the new path * inside try_load_port and friends themselves * the horrible mess that is how vcpkgpaths loads the consumer-manifest --- include/vcpkg/base/expected.h | 12 + include/vcpkg/base/message-data.inc.h | 97 ++-- include/vcpkg/base/messages.h | 29 +- include/vcpkg/paragraphs.h | 28 +- include/vcpkg/registries.h | 26 +- include/vcpkg/sourceparagraph.h | 3 - include/vcpkg/versions.h | 1 + locales/messages.json | 45 +- src/vcpkg-test/spdx.cpp | 3 +- src/vcpkg/base/messages.cpp | 23 +- src/vcpkg/commands.add-version.cpp | 65 +-- src/vcpkg/commands.autocomplete.cpp | 2 +- src/vcpkg/commands.ci-verify-versions.cpp | 522 +++++++++++++--------- src/vcpkg/commands.format-manifest.cpp | 181 +++----- src/vcpkg/paragraphs.cpp | 203 +++++---- src/vcpkg/portfileprovider.cpp | 54 +-- src/vcpkg/registries.cpp | 255 ++++++----- src/vcpkg/spdx.cpp | 2 +- src/vcpkg/vcpkgpaths.cpp | 27 +- src/vcpkg/versions.cpp | 2 + 20 files changed, 825 insertions(+), 755 deletions(-) diff --git a/include/vcpkg/base/expected.h b/include/vcpkg/base/expected.h index 682e2af90c..a392aaba88 100644 --- a/include/vcpkg/base/expected.h +++ b/include/vcpkg/base/expected.h @@ -220,6 +220,12 @@ namespace vcpkg return std::move(*m_t.get()); } + Error& error() & + { + unreachable_if_not_error(VCPKG_LINE_INFO); + return m_error; + } + const Error& error() const& { unreachable_if_not_error(VCPKG_LINE_INFO); @@ -232,6 +238,12 @@ namespace vcpkg return std::move(m_error); } + const Error&& error() const&& + { + unreachable_if_not_error(VCPKG_LINE_INFO); + return std::move(m_error); + } + typename ExpectedHolder::const_pointer get() const noexcept { if (value_is_error) diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 168d21f128..30b394297a 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -899,10 +899,6 @@ DECLARE_MESSAGE(ConsideredVersions, "requirement of {version}:") DECLARE_MESSAGE(ConstraintViolation, (), "", "Found a constraint violation:") DECLARE_MESSAGE(ContinueCodeUnitInStart, (), "", "found continue code unit in start position") -DECLARE_MESSAGE(ControlAndManifestFilesPresent, - (msg::path), - "", - "Both a manifest file and a CONTROL file exist in port directory: {path}") DECLARE_MESSAGE(ControlCharacterInString, (), "", "Control character in string") DECLARE_MESSAGE(CopyrightIsDir, (msg::path), "", "`{path}` being a directory is deprecated.") DECLARE_MESSAGE(CorruptedDatabase, (), "", "Database corrupted.") @@ -1085,7 +1081,11 @@ DECLARE_MESSAGE(ErrorInvalidManifestModeOption, (msg::option), "", "The option --{option} is not supported in manifest mode.") -DECLARE_MESSAGE(ErrorMessage, (), "", "error: ") +DECLARE_MESSAGE(ErrorMessage, + (), + "This identifies errors printed on the command line; Visual Studio and other IDEs look for this so " + "it's possible that it should remain unlocalized?", + "error: ") DECLARE_MESSAGE( ErrorMessageMustUsePrintError, (msg::value), @@ -1119,7 +1119,6 @@ DECLARE_MESSAGE(ErrorInvalidExtractOption, (msg::option, msg::value), "The keyword 'AUTO' should not be localized", "--{option} must be set to a nonnegative integer or 'AUTO'.") -DECLARE_MESSAGE(ErrorsFound, (), "", "Found the following errors:") DECLARE_MESSAGE(ErrorUnableToDetectCompilerInfo, (), "failure output will be displayed at the top of this", @@ -1257,7 +1256,6 @@ DECLARE_MESSAGE(FailedToParseCMakeConsoleOut, DECLARE_MESSAGE(FailedToParseBaseline, (msg::path), "", "Failed to parse baseline: {path}") DECLARE_MESSAGE(FailedToParseConfig, (msg::path), "", "Failed to parse configuration: {path}") DECLARE_MESSAGE(FailedToParseControl, (msg::path), "", "Failed to parse CONTROL file: {path}") -DECLARE_MESSAGE(FailedToParseManifest, (msg::path), "", "Failed to parse manifest file: {path}") DECLARE_MESSAGE(FailedToParseNoTopLevelObj, (msg::path), "", "Failed to parse {path}, expected a top-level object.") DECLARE_MESSAGE(FailedToParseNoVersionsArray, (msg::path), "", "Failed to parse {path}, expected a 'versions' array.") DECLARE_MESSAGE(FailedToParseSerializedBinParagraph, @@ -1273,7 +1271,6 @@ DECLARE_MESSAGE(FailedToParseVersionXML, "Could not parse version for tool {tool_name}. Version string was: {version}") DECLARE_MESSAGE(FailedToProvisionCe, (), "", "Failed to provision vcpkg-artifacts.") DECLARE_MESSAGE(FailedToReadParagraph, (msg::path), "", "Failed to read paragraphs from {path}") -DECLARE_MESSAGE(FailedToRemoveControl, (msg::path), "", "Failed to remove control file {path}") DECLARE_MESSAGE(FailedToRunToolToDetermineVersion, (msg::tool_name, msg::path), "Additional information, such as the command line output, if any, will be appended on " @@ -1282,7 +1279,6 @@ DECLARE_MESSAGE(FailedToRunToolToDetermineVersion, DECLARE_MESSAGE(FailedToStoreBackToMirror, (), "", "failed to store back to mirror:") DECLARE_MESSAGE(FailedToStoreBinaryCache, (msg::path), "", "Failed to store binary cache {path}") DECLARE_MESSAGE(FailedToTakeFileSystemLock, (msg::path), "", "Failed to take the filesystem lock on {path}") -DECLARE_MESSAGE(FailedToWriteManifest, (msg::path), "", "Failed to write manifest file {path}") DECLARE_MESSAGE(FailedVendorAuthentication, (msg::vendor, msg::url), "", @@ -1395,6 +1391,10 @@ DECLARE_MESSAGE(GitUnexpectedCommandOutputCmd, (msg::command_line), "", "git produced unexpected output when running {command_line}") +DECLARE_MESSAGE(GitCommitUpdateVersionDatabase, + (), + "This is a command line; only the 'update version database' part should be localized", + "git commit -m \"Update version database\"") DECLARE_MESSAGE(GraphCycleDetected, (msg::package_name), "A list of package names comprising the cycle will be printed after this message.", @@ -2065,10 +2065,7 @@ DECLARE_MESSAGE(LocalPortfileVersion, (), "", "Using local portfile versions. To update the local portfiles, use `git pull`.") -DECLARE_MESSAGE(ManifestConflict, - (msg::path), - "", - "Found both a manifest and CONTROL files in port \"{path}\"; please rename one or the other") +DECLARE_MESSAGE(ManifestConflict2, (), "", "Found both a manifest and CONTROL files; please rename one or the other") DECLARE_MESSAGE(ManifestFormatCompleted, (), "", "Succeeded in formatting the manifest files.") DECLARE_MESSAGE(MismatchedBinParagraphs, (), @@ -2189,7 +2186,10 @@ DECLARE_MESSAGE(NonZeroRemainingArgs, "the command '{command_name}' does not accept any additional arguments") DECLARE_MESSAGE(NoOutdatedPackages, (), "", "There are no outdated packages.") DECLARE_MESSAGE(NoRegistryForPort, (msg::package_name), "", "no registry configured for port {package_name}") -DECLARE_MESSAGE(NoteMessage, (), "", "note: ") +DECLARE_MESSAGE(NoteMessage, + (), + "This is stapled to ErrorMessage or WarningMessage to provide additional context", + "note: ") DECLARE_MESSAGE(NoUrlsAndHashSpecified, (msg::sha), "", "No urls specified to download SHA: {sha}") DECLARE_MESSAGE(NoUrlsAndNoHashSpecified, (), "", "No urls specified and no hash specified.") DECLARE_MESSAGE(NugetOutputNotCapturedBecauseInteractiveSpecified, @@ -2484,10 +2484,10 @@ DECLARE_MESSAGE(PortNotInBaseline, DECLARE_MESSAGE(PortsAdded, (msg::count), "", "The following {count} ports were added:") DECLARE_MESSAGE(PortsDiffHelp, (), "", "The argument should be a branch/tag/hash to checkout.") DECLARE_MESSAGE(PortDoesNotExist, (msg::package_name), "", "{package_name} does not exist") -DECLARE_MESSAGE(PortMissingManifest, - (msg::package_name, msg::path), +DECLARE_MESSAGE(PortMissingManifest2, + (msg::package_name), "", - "{package_name} has no vcpkg.json or CONTROL file in {path}") + "{package_name} port manifest missing (no vcpkg.json or CONTROL file)") DECLARE_MESSAGE(PortsNoDiff, (), "", "There were no changes in the ports between the two commits.") DECLARE_MESSAGE(PortsRemoved, (msg::count), "", "The following {count} ports were removed:") DECLARE_MESSAGE(PortsUpdated, (msg::count), "", "\nThe following {count} ports were updated:") @@ -2944,6 +2944,7 @@ DECLARE_MESSAGE(VcvarsRunFailedExitCode, (msg::exit_code), "", "while trying to get a Visual Studio environment, vcvarsall.bat returned {exit_code}") +DECLARE_MESSAGE(VersionBaselineMatch, (msg::version_spec), "", "message: {version_spec} matches the current baseline") DECLARE_MESSAGE(VersionBaselineMismatch, (msg::expected, msg::actual, msg::package_name), "{expected} and {actual} are versions", @@ -2981,10 +2982,8 @@ DECLARE_MESSAGE(VersionConstraintViolated, DECLARE_MESSAGE(VersionDatabaseFileMissing, (msg::package_name, msg::path), "", - "{package_name} is missing a version database file at {path}\n" - "Run:\n" - "vcpkg x-add-version {package_name}\n" - "to create the versions file.") + "missing a version database file at {path}\n" + "note: run 'vcpkg x-add-version {package_name}' to create the version database file.") DECLARE_MESSAGE(VersionBuiltinPortTreeEntryMissing, (msg::package_name, msg::expected, msg::actual), "{expected} and {actual} are versions like 1.0.", @@ -3045,13 +3044,11 @@ DECLARE_MESSAGE(VersionNotFound, (msg::expected, msg::actual), "{expected} and {actual} are versions", "{expected} not available, only {actual} is available") -DECLARE_MESSAGE(VersionNotFoundInVersionsFile, - (msg::version, msg::package_name), +DECLARE_MESSAGE(VersionNotFoundInVersionsFile2, + (msg::version_spec, msg::package_name, msg::path), "", - "Version {version} was not found in versions file for {package_name}.\n" - "Run:\n" - "vcpkg x-add-version {package_name}\n" - "to add the new port version.") + "{version_spec} was not found in versions database {path}.\n" + "note: run 'vcpkg x-add-version {package_name}' to add the new port version.") DECLARE_MESSAGE(VersionRejectedDueToBaselineMissing, (msg::path, msg::json_field), "", @@ -3069,29 +3066,33 @@ DECLARE_MESSAGE(VersionSchemeMismatch, "{expected} and {actual} are version schemes; it here refers to the {version}", "The version database declares {version} as {expected}, but {path} declares it as {actual}. " "Versions must be unique, even if they are declared with different schemes.\n" - "Run:\n" + "note: run:\n" "vcpkg x-add-version {package_name} --overwrite-version\n" "to overwrite the scheme declared in the version database with that declared in the port.") -DECLARE_MESSAGE(VersionShaMismatch, - (msg::version, msg::expected, msg::actual, msg::package_name), - "{expected} and {actual} are git commit SHAs", - "{version} is declared with {expected}, but the local port has a different SHA {actual}.\n" - "Please update the port's version fields and then run:\n" - "vcpkg x-add-version {package_name}\n" - "git add versions\n" - "git commit -m \"Update version database\"\n" - "to add the new version.") +DECLARE_MESSAGE( + VersionShaMismatch1, + (msg::version_spec, msg::expected, msg::actual, msg::package_name, msg::path), + "{expected} and {actual} are git tree SHAs. Console commands the user can run are printed after. 'git tree' is " + "https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish", + "{version_spec} is declared to have git tree {expected}, but the local port {path} has git tree " + "{actual}.\n" + "note: If {version_spec} is already published, update the {package_name} manifest with a new version or " + "port-version, then add the new version by running:") +DECLARE_MESSAGE(VersionShaMismatch2, + (msg::version_spec), + "Console commands the user can run are printed after. 'git tree' is " + "https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish", + "note: If {version_spec} is not yet published, overwrite the previous git tree by running:") DECLARE_MESSAGE(VersionShaMissing, (msg::package_name, msg::path), "", - "while validating {package_name}, missing Git SHA.\n" - "Run:\n" + "Unknown git tree. This is usually caused by uncommitted changes.\n" + "note: You can commit your changes and add them to the version database by running:\n" "git add \"{path}\"\n" - "git commit -m \"wip\"\n" + "git commit -m wip\n" "vcpkg x-add-version {package_name}\n" "git add versions\n" - "git commit --amend -m \"[{package_name}] Add new port\"\n" - "to commit the new port and create its version file.") + "git commit --amend -m \"[{package_name}] Add new port\"") DECLARE_MESSAGE(VersionSharpMustBeFollowedByPortVersion, (), "", @@ -3106,13 +3107,20 @@ DECLARE_MESSAGE(VersionSpecMismatch, "Failed to load port because versions are inconsistent. The file \"{path}\" contains the version " "{actual_version}, but the version database indicates that it should be {expected_version}.") DECLARE_MESSAGE(VersionTableHeader, (), "", "Version") -DECLARE_MESSAGE(VersionVerifiedOK, (msg::version_spec, msg::commit_sha), "", "OK: {version_spec} -> {commit_sha}") +DECLARE_MESSAGE(VersionVerifiedOK2, + (msg::version_spec, msg::commit_sha), + "", + "message: {version_spec} is correctly in the version database ({commit_sha})") DECLARE_MESSAGE(VSExaminedInstances, (), "", "The following Visual Studio instances were considered:") DECLARE_MESSAGE(VSExaminedPaths, (), "", "The following paths were examined for Visual Studio instances:") DECLARE_MESSAGE(VSNoInstances, (), "", "Could not locate a complete Visual Studio instance") DECLARE_MESSAGE(WaitingForChildrenToExit, (), "", "Waiting for child processes to exit...") DECLARE_MESSAGE(WaitingToTakeFilesystemLock, (msg::path), "", "waiting to take filesystem lock on {path}...") -DECLARE_MESSAGE(WarningMessage, (), "", "warning: ") +DECLARE_MESSAGE(WarningMessage, + (), + "This identifies warnings printed on the command line; Visual Studio and other IDEs look for this so " + "it's possible that it should remain unlocalized?", + "warning: ") DECLARE_MESSAGE(WarningMessageMustUsePrintWarning, (msg::value), "{value} is is a localized message name like WarningMessageMustUsePrintWarning", @@ -3126,7 +3134,6 @@ DECLARE_MESSAGE(WhileCheckingOutPortTreeIsh, "", "while checking out port {package_name} with git tree {commit_sha}") DECLARE_MESSAGE(WhileGettingLocalTreeIshObjectsForPorts, (), "", "while getting local treeish objects for ports") -DECLARE_MESSAGE(WhileLoadingLocalPort, (msg::package_name), "", "while attempting to load local port {package_name}") DECLARE_MESSAGE(WhileLoadingPortFromGitTree, (msg::commit_sha), "", "while trying to load port from: {commit_sha}") DECLARE_MESSAGE(WhileLookingForSpec, (msg::spec), "", "while looking for {spec}:") DECLARE_MESSAGE(WhileParsingVersionsForPort, diff --git a/include/vcpkg/base/messages.h b/include/vcpkg/base/messages.h index 5260b09dbc..980df1b6d7 100644 --- a/include/vcpkg/base/messages.h +++ b/include/vcpkg/base/messages.h @@ -84,27 +84,42 @@ namespace vcpkg static LocalizedString from_raw(std::basic_string&& s) noexcept; static LocalizedString from_raw(StringView s); - LocalizedString& append_raw(char c); - LocalizedString& append_raw(StringView s); + LocalizedString& append_raw(char c) &; + LocalizedString&& append_raw(char c) &&; + LocalizedString& append_raw(StringView s) &; + LocalizedString&& append_raw(StringView s) &&; template().to_string(std::declval()))> - LocalizedString& append_raw(const T& s) + LocalizedString& append_raw(const T& s) & { s.to_string(m_data); return *this; } - LocalizedString& append(const LocalizedString& s); + template().to_string(std::declval()))> + LocalizedString&& append_raw(const T& s) && + { + return std::move(append_raw(s)); + } + LocalizedString& append(const LocalizedString& s) &; + LocalizedString&& append(const LocalizedString& s) &&; template - LocalizedString& append(VCPKG_DECL_MSG_ARGS) + LocalizedString& append(VCPKG_DECL_MSG_ARGS) & { msg::format_to(*this, VCPKG_EXPAND_MSG_ARGS); return *this; } - LocalizedString& append_indent(size_t indent = 1); + template + LocalizedString&& append(VCPKG_DECL_MSG_ARGS) && + { + return std::move(append(VCPKG_EXPAND_MSG_ARGS)); + } + LocalizedString& append_indent(size_t indent = 1) &; + LocalizedString&& append_indent(size_t indent = 1) &&; // 0 items - Does nothing // 1 item - .append_raw(' ').append(item) // 2+ items - foreach: .append_raw('\n').append_indent(indent).append(item) - LocalizedString& append_floating_list(int indent, View items); + LocalizedString& append_floating_list(int indent, View items) &; + LocalizedString&& append_floating_list(int indent, View items) &&; friend bool operator==(const LocalizedString& lhs, const LocalizedString& rhs) noexcept; friend bool operator!=(const LocalizedString& lhs, const LocalizedString& rhs) noexcept; friend bool operator<(const LocalizedString& lhs, const LocalizedString& rhs) noexcept; diff --git a/include/vcpkg/paragraphs.h b/include/vcpkg/paragraphs.h index 00c93261d0..37d03b07ab 100644 --- a/include/vcpkg/paragraphs.h +++ b/include/vcpkg/paragraphs.h @@ -26,20 +26,24 @@ namespace vcpkg::Paragraphs bool is_port_directory(const ReadOnlyFilesystem& fs, const Path& maybe_directory); + struct PortLoadResult + { + ExpectedL maybe_scfl; + std::string on_disk_contents; + }; + // If an error occurs, the Expected will be in the error state. - // Otherwise, if the port is known, the Optional contains the loaded port information. - // Otherwise, the Optional is disengaged. - ExpectedL> try_load_port(const ReadOnlyFilesystem& fs, - StringView port_name, - const Path& port_directory); + // Otherwise, if the port is known, the maybe_scfl->source_control_file contains the loaded port information. + // Otherwise, maybe_scfl->source_control_file is nullptr. + PortLoadResult try_load_port(const ReadOnlyFilesystem& fs, StringView port_name, const Path& port_directory); // Identical to try_load_port, but the port unknown condition is mapped to an error. - ExpectedL> try_load_port_required(const ReadOnlyFilesystem& fs, - StringView port_name, - const Path& port_directory); - ExpectedL> try_load_port_text(const std::string& text, - StringView origin, - bool is_manifest, - MessageSink& warning_sink); + PortLoadResult try_load_port_required(const ReadOnlyFilesystem& fs, + StringView port_name, + const Path& port_directory); + ExpectedL try_load_port_manifest_text(StringView text, + StringView origin, + MessageSink& warning_sink); + ExpectedL try_load_control_file_text(StringView text, StringView origin); ExpectedL try_load_cached_package(const ReadOnlyFilesystem& fs, const Path& package_dir, diff --git a/include/vcpkg/registries.h b/include/vcpkg/registries.h index de08cb421a..f618a5840a 100644 --- a/include/vcpkg/registries.h +++ b/include/vcpkg/registries.h @@ -175,8 +175,24 @@ namespace vcpkg std::string git_tree; }; - ExpectedL>> get_builtin_versions(const VcpkgPaths& paths, - StringView port_name); + struct GitVersionsLoadResult + { + ExpectedL>> entries; + Path versions_file_path; + }; + + struct FilesystemVersionDbEntry + { + SchemedVersion version; + Path p; + }; + + GitVersionsLoadResult load_git_versions_file(const ReadOnlyFilesystem& fs, + const Path& registry_versions, + StringView port_name); + + ExpectedL>> load_filesystem_versions_file( + const ReadOnlyFilesystem& fs, const Path& registry_versions, StringView port_name, const Path& registry_root); ExpectedL>> get_builtin_baseline(const VcpkgPaths& paths); @@ -187,12 +203,6 @@ namespace vcpkg // Note that the * is included in the match size to distinguish from 0 == no match. size_t package_pattern_match(StringView name, StringView pattern); - struct FilesystemVersionDbEntry - { - SchemedVersion version; - Path p; - }; - std::unique_ptr>> make_git_version_db_deserializer(); std::unique_ptr>> make_filesystem_version_db_deserializer( const Path& root); diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index 77a02aa64a..bcb134d444 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -209,9 +209,6 @@ namespace vcpkg std::unique_ptr source_control_file; Path source_location; - /// Should model SPDX PackageDownloadLocation. Empty implies NOASSERTION. - /// See https://spdx.github.io/spdx-spec/package-information/#77-package-download-location-field - std::string registry_location; }; void print_error_message(View error_info_list); diff --git a/include/vcpkg/versions.h b/include/vcpkg/versions.h index 1cb1cfce93..8b91e474a2 100644 --- a/include/vcpkg/versions.h +++ b/include/vcpkg/versions.h @@ -73,6 +73,7 @@ namespace vcpkg Version version; friend bool operator==(const SchemedVersion& lhs, const SchemedVersion& rhs); + friend bool operator!=(const SchemedVersion& lhs, const SchemedVersion& rhs); }; StringLiteral to_string_literal(VersionScheme scheme); diff --git a/locales/messages.json b/locales/messages.json index a5d60e5f45..a5dd100192 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -525,8 +525,6 @@ "_ConsideredVersions.comment": "An example of {version} is 1.3.8.", "ConstraintViolation": "Found a constraint violation:", "ContinueCodeUnitInStart": "found continue code unit in start position", - "ControlAndManifestFilesPresent": "Both a manifest file and a CONTROL file exist in port directory: {path}", - "_ControlAndManifestFilesPresent.comment": "An example of {path} is /foo/bar.", "ControlCharacterInString": "Control character in string", "CopyrightIsDir": "`{path}` being a directory is deprecated.", "_CopyrightIsDir.comment": "An example of {path} is /foo/bar.", @@ -650,6 +648,7 @@ "ErrorInvalidManifestModeOption": "The option --{option} is not supported in manifest mode.", "_ErrorInvalidManifestModeOption.comment": "An example of {option} is editable.", "ErrorMessage": "error: ", + "_ErrorMessage.comment": "This identifies errors printed on the command line; Visual Studio and other IDEs look for this so it's possible that it should remain unlocalized?", "ErrorMessageMustUsePrintError": "The message named {value} starts with error:, it must be changed to prepend ErrorMessage in code instead.", "_ErrorMessageMustUsePrintError.comment": "{value} is is a localized message name like ErrorMessageMustUsePrintError", "ErrorMissingVcpkgRoot": "Could not detect vcpkg-root. If you are trying to use a copy of vcpkg that you've built, you must define the VCPKG_ROOT environment variable to point to a cloned copy of https://github.com/Microsoft/vcpkg.", @@ -678,7 +677,6 @@ "_ErrorWhileParsing.comment": "An example of {path} is /foo/bar.", "ErrorWhileWriting": "Error occurred while writing {path}.", "_ErrorWhileWriting.comment": "An example of {path} is /foo/bar.", - "ErrorsFound": "Found the following errors:", "ExamplesHeader": "Examples:", "_ExamplesHeader.comment": "Printed before a list of example command lines", "ExceededRecursionDepth": "Recursion depth exceeded.", @@ -770,8 +768,6 @@ "_FailedToParseConfig.comment": "An example of {path} is /foo/bar.", "FailedToParseControl": "Failed to parse CONTROL file: {path}", "_FailedToParseControl.comment": "An example of {path} is /foo/bar.", - "FailedToParseManifest": "Failed to parse manifest file: {path}", - "_FailedToParseManifest.comment": "An example of {path} is /foo/bar.", "FailedToParseNoTopLevelObj": "Failed to parse {path}, expected a top-level object.", "_FailedToParseNoTopLevelObj.comment": "An example of {path} is /foo/bar.", "FailedToParseNoVersionsArray": "Failed to parse {path}, expected a 'versions' array.", @@ -785,8 +781,6 @@ "FailedToProvisionCe": "Failed to provision vcpkg-artifacts.", "FailedToReadParagraph": "Failed to read paragraphs from {path}", "_FailedToReadParagraph.comment": "An example of {path} is /foo/bar.", - "FailedToRemoveControl": "Failed to remove control file {path}", - "_FailedToRemoveControl.comment": "An example of {path} is /foo/bar.", "FailedToRunToolToDetermineVersion": "Failed to run \"{path}\" to determine the {tool_name} version.", "_FailedToRunToolToDetermineVersion.comment": "Additional information, such as the command line output, if any, will be appended on the line after this message An example of {tool_name} is aria2. An example of {path} is /foo/bar.", "FailedToStoreBackToMirror": "failed to store back to mirror:", @@ -794,8 +788,6 @@ "_FailedToStoreBinaryCache.comment": "An example of {path} is /foo/bar.", "FailedToTakeFileSystemLock": "Failed to take the filesystem lock on {path}", "_FailedToTakeFileSystemLock.comment": "An example of {path} is /foo/bar.", - "FailedToWriteManifest": "Failed to write manifest file {path}", - "_FailedToWriteManifest.comment": "An example of {path} is /foo/bar.", "FailedVendorAuthentication": "One or more {vendor} credential providers failed to authenticate. See '{url}' for more details on how to provide credentials.", "_FailedVendorAuthentication.comment": "An example of {vendor} is Azure. An example of {url} is https://github.com/microsoft/vcpkg.", "FetchingBaselineInfo": "Fetching baseline information from {package_name}...", @@ -855,6 +847,8 @@ "GetParseFailureInfo": "Use '--debug' to get more information about the parse failures.", "GitCommandFailed": "failed to execute: {command_line}", "_GitCommandFailed.comment": "An example of {command_line} is vcpkg install zlib.", + "GitCommitUpdateVersionDatabase": "git commit -m \"Update version database\"", + "_GitCommitUpdateVersionDatabase.comment": "This is a command line; only the 'update version database' part should be localized", "GitFailedToFetch": "failed to fetch ref {value} from repository {url}", "_GitFailedToFetch.comment": "{value} is a git ref like 'origin/main' An example of {url} is https://github.com/microsoft/vcpkg.", "GitFailedToInitializeLocalRepository": "failed to initialize local repository {path}", @@ -1169,8 +1163,7 @@ "_LocalizedMessageMustNotContainIndents.comment": "{value} is is a localized message name like LocalizedMessageMustNotContainIndents. The 'LocalizedString::append_indent' part is locale-invariant.", "LocalizedMessageMustNotEndWithNewline": "The message named {value} ends with a newline which should be added by formatting rather than by localization.", "_LocalizedMessageMustNotEndWithNewline.comment": "{value} is a localized message name like LocalizedMessageMustNotEndWithNewline", - "ManifestConflict": "Found both a manifest and CONTROL files in port \"{path}\"; please rename one or the other", - "_ManifestConflict.comment": "An example of {path} is /foo/bar.", + "ManifestConflict2": "Found both a manifest and CONTROL files; please rename one or the other", "ManifestFormatCompleted": "Succeeded in formatting the manifest files.", "MismatchedBinParagraphs": "The serialized binary paragraph was different from the original binary paragraph. Please open an issue at https://github.com/microsoft/vcpkg with the following output:", "MismatchedFiles": "file to store does not match hash", @@ -1239,6 +1232,7 @@ "NonZeroRemainingArgs": "the command '{command_name}' does not accept any additional arguments", "_NonZeroRemainingArgs.comment": "An example of {command_name} is install.", "NoteMessage": "note: ", + "_NoteMessage.comment": "This is stapled to ErrorMessage or WarningMessage to provide additional context", "NugetOutputNotCapturedBecauseInteractiveSpecified": "NuGet command failed and output was not captured because --interactive was specified", "NugetPackageFileSucceededButCreationFailed": "NuGet package creation succeeded, but no .nupkg was produced. Expected: \"{path}\"", "_NugetPackageFileSucceededButCreationFailed.comment": "An example of {path} is /foo/bar.", @@ -1382,8 +1376,8 @@ "_PortDependencyConflict.comment": "An example of {package_name} is zlib.", "PortDoesNotExist": "{package_name} does not exist", "_PortDoesNotExist.comment": "An example of {package_name} is zlib.", - "PortMissingManifest": "{package_name} has no vcpkg.json or CONTROL file in {path}", - "_PortMissingManifest.comment": "An example of {package_name} is zlib. An example of {path} is /foo/bar.", + "PortMissingManifest2": "{package_name} port manifest missing (no vcpkg.json or CONTROL file)", + "_PortMissingManifest2.comment": "An example of {package_name} is zlib.", "PortNotInBaseline": "the baseline does not contain an entry for port {package_name}", "_PortNotInBaseline.comment": "An example of {package_name} is zlib.", "PortSupportsField": "(supports: \"{supports_expression}\")", @@ -1650,6 +1644,8 @@ "VcvarsRunFailed": "failed to run vcvarsall.bat to get a Visual Studio environment", "VcvarsRunFailedExitCode": "while trying to get a Visual Studio environment, vcvarsall.bat returned {exit_code}", "_VcvarsRunFailedExitCode.comment": "An example of {exit_code} is 127.", + "VersionBaselineMatch": "message: {version_spec} matches the current baseline", + "_VersionBaselineMatch.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0.", "VersionBaselineMismatch": "The latest version is {expected}, but the baseline file contains {actual}.\nRun:\nvcpkg x-add-version {package_name}\ngit add versions\ngit commit -m \"Update version database\"\nto update the baseline version.", "_VersionBaselineMismatch.comment": "{expected} and {actual} are versions An example of {package_name} is zlib.", "VersionBuiltinPortTreeEntryMissing": "no version database entry for {package_name} at {expected}; using the checked out ports tree version ({actual}).", @@ -1665,7 +1661,7 @@ "_VersionConstraintViolated.comment": "An example of {spec} is zlib:x64-windows. An example of {expected_version} is 1.3.8. An example of {actual_version} is 1.3.8.", "VersionDatabaseEntryMissing": "no version entry for {package_name} at {version}.", "_VersionDatabaseEntryMissing.comment": "An example of {package_name} is zlib. An example of {version} is 1.3.8.", - "VersionDatabaseFileMissing": "{package_name} is missing a version database file at {path}\nRun:\nvcpkg x-add-version {package_name}\nto create the versions file.", + "VersionDatabaseFileMissing": "missing a version database file at {path}\nnote: run 'vcpkg x-add-version {package_name}' to create the version database file.", "_VersionDatabaseFileMissing.comment": "An example of {package_name} is zlib. An example of {path} is /foo/bar.", "VersionGitEntryMissing": "no version database entry for {package_name} at {version}.\nAvailable versions:", "_VersionGitEntryMissing.comment": "A list of versions, 1 per line, are printed after this message. An example of {package_name} is zlib. An example of {version} is 1.3.8.", @@ -1693,31 +1689,34 @@ "_VersionMissingRequiredFeature.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {feature} is avisynthplus. An example of {constraint_origin} is zlib:x64-windows@1.0.0.", "VersionNotFound": "{expected} not available, only {actual} is available", "_VersionNotFound.comment": "{expected} and {actual} are versions", - "VersionNotFoundInVersionsFile": "Version {version} was not found in versions file for {package_name}.\nRun:\nvcpkg x-add-version {package_name}\nto add the new port version.", - "_VersionNotFoundInVersionsFile.comment": "An example of {version} is 1.3.8. An example of {package_name} is zlib.", + "VersionNotFoundInVersionsFile2": "{version_spec} was not found in versions database {path}.\nnote: run 'vcpkg x-add-version {package_name}' to add the new port version.", + "_VersionNotFoundInVersionsFile2.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {package_name} is zlib. An example of {path} is /foo/bar.", "VersionRejectedDueToBaselineMissing": "{path} was rejected because it uses \"{json_field}\" and does not have a \"builtin-baseline\". This can be fixed by removing the uses of \"{json_field}\" or adding a \"builtin-baseline\".\nSee `vcpkg help versioning` for more information.", "_VersionRejectedDueToBaselineMissing.comment": "An example of {path} is /foo/bar. An example of {json_field} is identifer.", "VersionRejectedDueToFeatureFlagOff": "{path} was rejected because it uses \"{json_field}\" and the `versions` feature flag is disabled. This can be fixed by removing \"{json_field}\" or enabling the `versions` feature flag.\nSee `vcpkg help versioning` for more information.", "_VersionRejectedDueToFeatureFlagOff.comment": "An example of {path} is /foo/bar. An example of {json_field} is identifer.", - "VersionSchemeMismatch": "The version database declares {version} as {expected}, but {path} declares it as {actual}. Versions must be unique, even if they are declared with different schemes.\nRun:\nvcpkg x-add-version {package_name} --overwrite-version\nto overwrite the scheme declared in the version database with that declared in the port.", + "VersionSchemeMismatch": "The version database declares {version} as {expected}, but {path} declares it as {actual}. Versions must be unique, even if they are declared with different schemes.\nnote: run:\nvcpkg x-add-version {package_name} --overwrite-version\nto overwrite the scheme declared in the version database with that declared in the port.", "_VersionSchemeMismatch.comment": "{expected} and {actual} are version schemes; it here refers to the {version} An example of {version} is 1.3.8. An example of {path} is /foo/bar. An example of {package_name} is zlib.", - "VersionShaMismatch": "{version} is declared with {expected}, but the local port has a different SHA {actual}.\nPlease update the port's version fields and then run:\nvcpkg x-add-version {package_name}\ngit add versions\ngit commit -m \"Update version database\"\nto add the new version.", - "_VersionShaMismatch.comment": "{expected} and {actual} are git commit SHAs An example of {version} is 1.3.8. An example of {package_name} is zlib.", - "VersionShaMissing": "while validating {package_name}, missing Git SHA.\nRun:\ngit add \"{path}\"\ngit commit -m \"wip\"\nvcpkg x-add-version {package_name}\ngit add versions\ngit commit --amend -m \"[{package_name}] Add new port\"\nto commit the new port and create its version file.", + "VersionShaMismatch1": "{version_spec} is declared to have git tree {expected}, but the local port {path} has git tree {actual}.\nnote: If {version_spec} is already published, update the {package_name} manifest with a new version or port-version, then add the new version by running:", + "_VersionShaMismatch1.comment": "{expected} and {actual} are git tree SHAs. Console commands the user can run are printed after. 'git tree' is https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {package_name} is zlib. An example of {path} is /foo/bar.", + "VersionShaMismatch2": "note: If {version_spec} is not yet published, overwrite the previous git tree by running:", + "_VersionShaMismatch2.comment": "Console commands the user can run are printed after. 'git tree' is https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish An example of {version_spec} is zlib:x64-windows@1.0.0.", + "VersionShaMissing": "Unknown git tree. This is usually caused by uncommitted changes.\nnote: You can commit your changes and add them to the version database by running:\ngit add \"{path}\"\ngit commit -m wip\nvcpkg x-add-version {package_name}\ngit add versions\ngit commit --amend -m \"[{package_name}] Add new port\"", "_VersionShaMissing.comment": "An example of {package_name} is zlib. An example of {path} is /foo/bar.", "VersionSharpMustBeFollowedByPortVersion": "'#' in version text must be followed by a port version", "VersionSharpMustBeFollowedByPortVersionNonNegativeInteger": "'#' in version text must be followed by a port version (a non-negative integer)", "VersionSpecMismatch": "Failed to load port because versions are inconsistent. The file \"{path}\" contains the version {actual_version}, but the version database indicates that it should be {expected_version}.", "_VersionSpecMismatch.comment": "An example of {path} is /foo/bar. An example of {expected_version} is 1.3.8. An example of {actual_version} is 1.3.8.", "VersionTableHeader": "Version", - "VersionVerifiedOK": "OK: {version_spec} -> {commit_sha}", - "_VersionVerifiedOK.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", + "VersionVerifiedOK2": "message: {version_spec} is correctly in the version database ({commit_sha})", + "_VersionVerifiedOK2.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "WaitingForChildrenToExit": "Waiting for child processes to exit...", "WaitingToTakeFilesystemLock": "waiting to take filesystem lock on {path}...", "_WaitingToTakeFilesystemLock.comment": "An example of {path} is /foo/bar.", "WarnOnParseConfig": "Found the following warnings in configuration {path}:", "_WarnOnParseConfig.comment": "An example of {path} is /foo/bar.", "WarningMessage": "warning: ", + "_WarningMessage.comment": "This identifies warnings printed on the command line; Visual Studio and other IDEs look for this so it's possible that it should remain unlocalized?", "WarningMessageMustUsePrintWarning": "The message named {value} starts with warning:, it must be changed to prepend WarningMessage in code instead.", "_WarningMessageMustUsePrintWarning.comment": "{value} is is a localized message name like WarningMessageMustUsePrintWarning", "WarningsTreatedAsErrors": "previous warnings being interpreted as errors", @@ -1726,8 +1725,6 @@ "WhileCheckingOutPortTreeIsh": "while checking out port {package_name} with git tree {commit_sha}", "_WhileCheckingOutPortTreeIsh.comment": "An example of {package_name} is zlib. An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "WhileGettingLocalTreeIshObjectsForPorts": "while getting local treeish objects for ports", - "WhileLoadingLocalPort": "while attempting to load local port {package_name}", - "_WhileLoadingLocalPort.comment": "An example of {package_name} is zlib.", "WhileLoadingPortFromGitTree": "while trying to load port from: {commit_sha}", "_WhileLoadingPortFromGitTree.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "WhileLookingForSpec": "while looking for {spec}:", diff --git a/src/vcpkg-test/spdx.cpp b/src/vcpkg-test/spdx.cpp index 937dcda4a8..290b1aeda7 100644 --- a/src/vcpkg-test/spdx.cpp +++ b/src/vcpkg-test/spdx.cpp @@ -9,7 +9,6 @@ TEST_CASE ("spdx maximum serialization", "[spdx]") { PackageSpec spec{"zlib", Test::ARM_UWP}; SourceControlFileAndLocation scfl; - scfl.registry_location = "git://some-vcs-url"; auto& scf = *(scfl.source_control_file = std::make_unique()); auto& cpgh = *(scf.core_paragraph = std::make_unique()); cpgh.name = "zlib"; @@ -99,7 +98,7 @@ TEST_CASE ("spdx maximum serialization", "[spdx]") "name": "zlib", "SPDXID": "SPDXRef-port", "versionInfo": "1.0#5", - "downloadLocation": "git://some-vcs-url", + "downloadLocation": "NOASSERTION", "homepage": "homepage", "licenseConcluded": "MIT", "licenseDeclared": "NOASSERTION", diff --git a/src/vcpkg/base/messages.cpp b/src/vcpkg/base/messages.cpp index f7fba88f65..c2ca00e5d3 100644 --- a/src/vcpkg/base/messages.cpp +++ b/src/vcpkg/base/messages.cpp @@ -28,31 +28,39 @@ namespace vcpkg template LocalizedString LocalizedString::from_raw(std::basic_string&& s) noexcept; LocalizedString LocalizedString::from_raw(StringView s) { return LocalizedString(s); } - LocalizedString& LocalizedString::append_raw(char c) + LocalizedString& LocalizedString::append_raw(char c) & { m_data.push_back(c); return *this; } - LocalizedString& LocalizedString::append_raw(StringView s) + LocalizedString&& LocalizedString::append_raw(char c) && { return std::move(append_raw(c)); } + + LocalizedString& LocalizedString::append_raw(StringView s) & { m_data.append(s.begin(), s.size()); return *this; } - LocalizedString& LocalizedString::append(const LocalizedString& s) + LocalizedString&& LocalizedString::append_raw(StringView s) && { return std::move(append_raw(s)); } + + LocalizedString& LocalizedString::append(const LocalizedString& s) & { m_data.append(s.m_data); return *this; } - LocalizedString& LocalizedString::append_indent(size_t indent) + LocalizedString&& LocalizedString::append(const LocalizedString& s) && { return std::move(append(s)); } + + LocalizedString& LocalizedString::append_indent(size_t indent) & { m_data.append(indent * 2, ' '); return *this; } - LocalizedString& LocalizedString::append_floating_list(int indent, View items) + LocalizedString&& LocalizedString::append_indent(size_t indent) && { return std::move(append_indent(indent)); } + + LocalizedString& LocalizedString::append_floating_list(int indent, View items) & { switch (items.size()) { @@ -70,6 +78,11 @@ namespace vcpkg return *this; } + LocalizedString&& LocalizedString::append_floating_list(int indent, View items) && + { + return std::move(append_floating_list(indent, items)); + } + bool operator==(const LocalizedString& lhs, const LocalizedString& rhs) noexcept { return lhs.data() == rhs.data(); diff --git a/src/vcpkg/commands.add-version.cpp b/src/vcpkg/commands.add-version.cpp index 4e5af3c8db..11f1d20e5a 100644 --- a/src/vcpkg/commands.add-version.cpp +++ b/src/vcpkg/commands.add-version.cpp @@ -187,49 +187,41 @@ namespace const std::string& port_name, const SchemedVersion& port_version, const std::string& git_tree, - const Path& version_db_file_path, bool overwrite_version, bool print_success, bool keep_going, bool skip_version_format_check) { auto& fs = paths.get_filesystem(); - if (!fs.exists(version_db_file_path, IgnoreErrors{})) + auto maybe_maybe_versions = load_git_versions_file(fs, paths.builtin_registry_versions, port_name); + auto maybe_versions = maybe_maybe_versions.entries.get(); + if (!maybe_versions) + { + msg::println(Color::error, maybe_maybe_versions.entries.error()); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + auto versions = maybe_versions->get(); + if (!versions) { if (!skip_version_format_check) { check_used_version_scheme(port_version, port_name); } std::vector new_entry{{port_version, git_tree}}; - write_versions_file(fs, new_entry, version_db_file_path); + write_versions_file(fs, new_entry, maybe_maybe_versions.versions_file_path); if (print_success) { msg::println(Color::success, msg::format(msgAddVersionAddedVersionToFile, msg::version = port_version.version, - msg::path = version_db_file_path) + msg::path = maybe_maybe_versions.versions_file_path) .append_raw(' ') .append(msgAddVersionNewFile)); } return UpdateResult::Updated; } - auto maybe_maybe_versions = get_builtin_versions(paths, port_name); - auto maybe_versions = maybe_maybe_versions.get(); - if (!maybe_versions) - { - msg::println_error(msg::format(msgAddVersionUnableToParseVersionsFile, msg::path = version_db_file_path) - .append_raw('\n') - .append(maybe_maybe_versions.error())); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - auto versions = maybe_versions->get(); - if (!versions) - { - Checks::unreachable(VCPKG_LINE_INFO, "Version file existed but was still unknown"); - } - const auto& versions_end = versions->end(); auto found_same_sha = std::find_if( versions->begin(), versions_end, [&](auto&& entry) -> bool { return entry.git_tree == git_tree; }); @@ -242,7 +234,7 @@ namespace msg::println(Color::success, msgAddVersionVersionAlreadyInFile, msg::version = port_version.version, - msg::path = version_db_file_path); + msg::path = maybe_maybe_versions.versions_file_path); } return UpdateResult::NotUpdated; } @@ -300,13 +292,13 @@ namespace check_used_version_scheme(port_version, port_name); } - write_versions_file(fs, *versions, version_db_file_path); + write_versions_file(fs, *versions, maybe_maybe_versions.versions_file_path); if (print_success) { msg::println(Color::success, msgAddVersionAddedVersionToFile, msg::version = port_version.version, - msg::path = version_db_file_path); + msg::path = maybe_maybe_versions.versions_file_path); } return UpdateResult::Updated; } @@ -405,15 +397,9 @@ namespace vcpkg { auto port_dir = paths.builtin_ports_directory() / port_name; - if (!fs.exists(port_dir, IgnoreErrors{})) - { - msg::println_error(msgPortDoesNotExist, msg::package_name = port_name); - Checks::check_exit(VCPKG_LINE_INFO, !add_all); - continue; - } - auto maybe_scf = - Paragraphs::try_load_port_required(fs, port_name, paths.builtin_ports_directory() / port_name); + Paragraphs::try_load_port_required(fs, port_name, paths.builtin_ports_directory() / port_name) + .maybe_scfl; auto scf = maybe_scf.get(); if (!scf) { @@ -426,15 +412,15 @@ namespace vcpkg if (!skip_formatting_check) { // check if manifest file is property formatted - const auto path_to_manifest = paths.builtin_ports_directory() / port_name / "vcpkg.json"; - if (fs.exists(path_to_manifest, IgnoreErrors{})) + + if (Path{scf->source_location}.filename() == "vcpkg.json") { - const auto current_file_content = fs.read_contents(path_to_manifest, VCPKG_LINE_INFO); - const auto json = serialize_manifest(**scf); + const auto current_file_content = fs.read_contents(scf->source_location, VCPKG_LINE_INFO); + const auto json = serialize_manifest(*scf->source_control_file); const auto formatted_content = Json::stringify(json); if (current_file_content != formatted_content) { - auto command_line = fmt::format("vcpkg format-manifest ports/{}/vcpkg.json", port_name); + auto command_line = fmt::format("vcpkg format-manifest {}", scf->source_location); msg::println_error( msg::format(msgAddVersionPortHasImproperFormat, msg::package_name = port_name) .append_raw('\n') @@ -454,8 +440,7 @@ namespace vcpkg msg::println_warning(msgAddVersionUncommittedChanges, msg::package_name = port_name); } - const auto& schemed_version = (*scf)->to_schemed_version(); - + auto schemed_version = scf->source_control_file->to_schemed_version(); auto git_tree_it = git_tree_map.find(port_name); if (git_tree_it == git_tree_map.end()) { @@ -469,14 +454,10 @@ namespace vcpkg Checks::exit_fail(VCPKG_LINE_INFO); } const auto& git_tree = git_tree_it->second; - - char prefix[] = {port_name[0], '-', '\0'}; - auto port_versions_path = paths.builtin_registry_versions / prefix / Strings::concat(port_name, ".json"); auto updated_versions_file = update_version_db_file(paths, port_name, schemed_version, git_tree, - port_versions_path, overwrite_version, verbose, add_all, diff --git a/src/vcpkg/commands.autocomplete.cpp b/src/vcpkg/commands.autocomplete.cpp index d43c755a25..d948728cb9 100644 --- a/src/vcpkg/commands.autocomplete.cpp +++ b/src/vcpkg/commands.autocomplete.cpp @@ -106,7 +106,7 @@ namespace vcpkg // TODO: Support autocomplete for ports in --overlay-ports auto maybe_port = Paragraphs::try_load_port_required( paths.get_filesystem(), port_name, paths.builtin_ports_directory() / port_name); - if (!maybe_port) + if (!maybe_port.maybe_scfl) { Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index d067c95906..8eccea66e4 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -2,8 +2,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -12,7 +12,6 @@ #include #include #include -#include using namespace vcpkg; @@ -30,187 +29,294 @@ namespace } } - ExpectedL verify_version_in_db(const VcpkgPaths& paths, - const std::map> baseline, - StringView port_name, - const Path& port_path, - const Path& versions_file_path, - const std::string& local_git_tree, - bool verify_git_trees) + struct CiVerifyVersionsDbEntry { - auto maybe_maybe_versions = vcpkg::get_builtin_versions(paths, port_name); - const auto maybe_versions = maybe_maybe_versions.get(); - if (!maybe_versions) - { - return {msg::format_error( - msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file_path) - .append(std::move(maybe_maybe_versions).error()), - expected_right_tag}; - } + SourceControlFileAndLocation scf; + Path port_directory; + std::vector entries; + Path versions_file_path; + }; + + void add_parse_from_git_tree_failure_notes(LocalizedString& target, + const std::string& port_name, + const Path& versions_file_path, + const SchemedVersion& version, + StringView treeish) + { + target.append_raw('\n') + .append(msgNoteMessage) + .append(msgWhileLoadingPortFromGitTree, msg::commit_sha = treeish) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgWhileValidatingVersion, msg::version = version.version) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file_path); + } + + void verify_git_tree(LocalizedString& errors, + MessageSink& success_sink, + const VcpkgPaths& paths, + const std::string& port_name, + const Path& versions_file_path, + const GitVersionDbEntry& version_entry) + { + bool success = true; + auto treeish = version_entry.git_tree + ":CONTROL"; + auto maybe_maybe_loaded_manifest = + paths.git_show(treeish, paths.root / ".git") + .then([&](std::string&& file) -> ExpectedL { + auto maybe_scf = Paragraphs::try_load_control_file_text(file, treeish); + if (!maybe_scf) + { + add_parse_from_git_tree_failure_notes( + maybe_scf.error(), port_name, versions_file_path, version_entry.version, treeish); + } + + return maybe_scf; + }); - const auto versions = maybe_versions->get(); - if (!versions || versions->empty()) + auto maybe_loaded_manifest = maybe_maybe_loaded_manifest.get(); + if (!maybe_loaded_manifest) { - return {msg::format_error( - msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file_path) - .append_raw('\n') - .append(msgInvalidNoVersions), - expected_right_tag}; + success = false; + errors.append(std::move(maybe_maybe_loaded_manifest).error()).append_raw('\n'); + return; } - if (verify_git_trees) + if (!maybe_loaded_manifest->source_control_file) { - for (auto&& version_entry : *versions) - { - bool version_ok = false; - for (StringView control_file : {"CONTROL", "vcpkg.json"}) - { - auto treeish = Strings::concat(version_entry.git_tree, ':', control_file); - auto maybe_file = paths.git_show(Strings::concat(treeish), paths.root / ".git"); - if (!maybe_file) continue; - - const auto& file = maybe_file.value_or_exit(VCPKG_LINE_INFO); - auto maybe_scf = - Paragraphs::try_load_port_text(file, treeish, control_file == "vcpkg.json", stdout_sink); - auto scf = maybe_scf.get(); - if (!scf) + treeish = version_entry.git_tree + ":vcpkg.json"; + paths.git_show(treeish, paths.root / ".git") + .then([&](std::string&& file) -> ExpectedL { + auto maybe_scf = Paragraphs::try_load_port_manifest_text(file, treeish, stdout_sink); + if (!maybe_scf) { - return {msg::format_error(msgWhileParsingVersionsForPort, - msg::package_name = port_name, - msg::path = versions_file_path) - .append_raw('\n') - .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) - .append_raw('\n') - .append(msgWhileLoadingPortFromGitTree, msg::commit_sha = treeish) - .append_raw('\n') - .append(maybe_scf.error()), - expected_right_tag}; + add_parse_from_git_tree_failure_notes( + maybe_scf.error(), port_name, versions_file_path, version_entry.version, treeish); } - auto&& git_tree_version = (*scf)->to_schemed_version(); - if (version_entry.version.version != git_tree_version.version) - { - return { - msg::format_error(msgWhileParsingVersionsForPort, - msg::package_name = port_name, - msg::path = versions_file_path) - .append_raw('\n') - .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) - .append_raw('\n') - .append(msgVersionInDeclarationDoesNotMatch, msg::version = git_tree_version.version) - .append_raw('\n') - .append(msgCheckedOutGitSha, msg::commit_sha = version_entry.git_tree), - expected_right_tag}; - } - version_ok = true; - break; - } - - if (!version_ok) - { - return {msg::format_error(msgWhileParsingVersionsForPort, - msg::package_name = port_name, - msg::path = versions_file_path) - .append_raw('\n') - .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) - .append_raw('\n') - .append(msgCheckedOutObjectMissingManifest) - .append_raw('\n') - .append(msgCheckedOutGitSha, msg::commit_sha = version_entry.git_tree), - expected_right_tag}; - } + return maybe_scf; + }); + + maybe_loaded_manifest = maybe_maybe_loaded_manifest.get(); + if (!maybe_loaded_manifest) + { + success = false; + errors.append(std::move(maybe_maybe_loaded_manifest).error()).append_raw('\n'); + return; + } + + if (!maybe_loaded_manifest->source_control_file) + { + success = false; + errors.append_raw(versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgCheckedOutObjectMissingManifest) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgCheckedOutGitSha, msg::commit_sha = treeish) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) + .append_raw('\n'); + return; } } - auto maybe_scf = Paragraphs::try_load_port_required(paths.get_filesystem(), port_name, port_path); - auto scf = maybe_scf.get(); - if (!scf) + auto& scf = *maybe_loaded_manifest->source_control_file; + auto&& git_tree_version = scf.to_schemed_version(); + if (version_entry.version.version != git_tree_version.version) + { + success = false; + errors.append_raw(versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionInDeclarationDoesNotMatch, msg::version = git_tree_version.version) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgCheckedOutGitSha, msg::commit_sha = treeish) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) + .append_raw('\n'); + } + + if (version_entry.version.scheme != git_tree_version.scheme) + { + success = false; + errors.append_raw(versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionSchemeMismatch, + msg::version = version_entry.version.version, + msg::expected = get_scheme_name(version_entry.version.scheme), + msg::actual = get_scheme_name(git_tree_version.scheme), + msg::path = treeish, + msg::package_name = port_name) + .append_raw('\n'); + } + + if (success) + { + success_sink.println(LocalizedString::from_raw(versions_file_path) + .append_raw(": ") + .append(msgVersionVerifiedOK2, + msg::version_spec = VersionSpec{port_name, version_entry.version.version}, + msg::commit_sha = version_entry.git_tree)); + } + } + + void verify_all_historical_git_trees(LocalizedString& errors, + MessageSink& success_sink, + const VcpkgPaths& paths, + const std::string& port_name, + const CiVerifyVersionsDbEntry& versions) + { + for (auto&& version_entry : versions.entries) + { + verify_git_tree(errors, success_sink, paths, port_name, versions.versions_file_path, version_entry); + } + } + + void verify_local_port_matches_version_database(LocalizedString& errors, + MessageSink& success_sink, + const std::string& port_name, + const CiVerifyVersionsDbEntry& db, + const std::string& local_git_tree) + { + bool success = true; + if (db.entries.empty()) { - return {msg::format_error(msgWhileLoadingLocalPort, msg::package_name = port_name) - .append_raw('\n') - .append(maybe_scf.error()), - expected_right_tag}; + success = false; + errors.append_raw(db.versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgInvalidNoVersions) + .append_raw('\n'); } - const auto local_port_version = (*scf)->to_schemed_version(); + const auto local_port_version = db.scf.source_control_file->to_schemed_version(); - auto versions_end = versions->end(); - auto it = std::find_if(versions->begin(), versions_end, [&](const GitVersionDbEntry& entry) { + auto versions_end = db.entries.end(); + auto it = std::find_if(db.entries.begin(), versions_end, [&](const GitVersionDbEntry& entry) { return entry.version.version == local_port_version.version; }); + if (it == versions_end) { - return {msg::format_error( - msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file_path) - .append_raw('\n') - .append(msgVersionNotFoundInVersionsFile, - msg::version = local_port_version.version, - msg::package_name = port_name), - expected_right_tag}; + success = false; + errors.append_raw(db.scf.source_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionNotFoundInVersionsFile2, + msg::version_spec = VersionSpec{port_name, local_port_version.version}, + msg::package_name = port_name, + msg::path = db.versions_file_path) + .append_raw('\n'); + return; } - auto& entry = *it; - if (entry.version.scheme != local_port_version.scheme) + auto& version_entry = *it; + if (version_entry.version.scheme != local_port_version.scheme) { - return {msg::format_error( - msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file_path) - .append_raw('\n') - .append(msgVersionSchemeMismatch, - msg::version = entry.version.version, - msg::expected = get_scheme_name(entry.version.scheme), - msg::actual = get_scheme_name(local_port_version.scheme), - msg::path = port_path, - msg::package_name = port_name), - expected_right_tag}; + success = false; + // assume the port is correct, so report the error on the version database file + errors.append_raw(db.versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionSchemeMismatch, + msg::version = version_entry.version.version, + msg::expected = get_scheme_name(version_entry.version.scheme), + msg::actual = get_scheme_name(local_port_version.scheme), + msg::path = db.port_directory, + msg::package_name = port_name) + .append_raw('\n'); } - if (local_git_tree != entry.git_tree) + if (local_git_tree != version_entry.git_tree) { - return {msg::format_error( - msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file_path) - .append_raw('\n') - .append(msgVersionShaMismatch, - msg::version = entry.version.version, - msg::expected = entry.git_tree, - msg::actual = local_git_tree, - msg::package_name = port_name), - expected_right_tag}; + success = false; + errors.append_raw(db.versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionShaMismatch1, + msg::version_spec = VersionSpec{port_name, local_port_version.version}, + msg::expected = version_entry.git_tree, + msg::actual = local_git_tree, + msg::package_name = port_name, + msg::path = db.port_directory) + .append_raw('\n') + .append_indent() + .append_raw("vcpkg x-add-version " + port_name + "\n") + .append_indent() + .append_raw("git add versions\n") + .append_indent() + .append(msgGitCommitUpdateVersionDatabase) + .append_raw('\n') + .append(msgVersionShaMismatch2, msg::version_spec = VersionSpec{port_name, local_port_version.version}) + .append_raw('\n') + .append_indent() + .append_raw("vcpkg x-add-version " + port_name + " --overwrite-version\n") + .append_indent() + .append_raw("git add versions\n") + .append_indent() + .append(msgGitCommitUpdateVersionDatabase) + .append_raw('\n'); } + if (success) + { + success_sink.println(LocalizedString::from_raw(db.port_directory) + .append_raw(": ") + .append(msgVersionVerifiedOK2, + msg::version_spec = VersionSpec{port_name, local_port_version.version}, + msg::commit_sha = version_entry.git_tree)); + } + } + + void verify_local_port_matches_baseline(LocalizedString& errors, + MessageSink& success_sink, + const std::map> baseline, + const Path& baseline_path, + const std::string& port_name, + const CiVerifyVersionsDbEntry& db) + { + const auto local_port_version = db.scf.source_control_file->to_schemed_version(); auto maybe_baseline = baseline.find(port_name); if (maybe_baseline == baseline.end()) { - return {msg::format_error( - msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file_path) - .append_raw('\n') - .append(msgBaselineMissing, - msg::package_name = port_name, - msg::version = local_port_version.version), - expected_right_tag}; + errors.append_raw(db.scf.source_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgBaselineMissing, msg::package_name = port_name, msg::version = local_port_version.version) + .append_raw('\n'); + return; } auto&& baseline_version = maybe_baseline->second; - if (baseline_version != entry.version.version) + if (baseline_version == local_port_version.version) { - return {msg::format_error( - msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file_path) - .append_raw('\n') - .append(msgVersionBaselineMismatch, - msg::expected = entry.version.version, - msg::actual = baseline_version, - msg::package_name = port_name), - expected_right_tag}; + success_sink.println(LocalizedString::from_raw(baseline_path) + .append_raw(": ") + .append(msgVersionBaselineMatch, + msg::version_spec = VersionSpec{port_name, local_port_version.version})); + } + else + { + // assume the port is correct, so report the error on the baseline.json file + errors.append_raw(baseline_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionBaselineMismatch, + msg::expected = local_port_version.version, + msg::actual = baseline_version, + msg::package_name = port_name) + .append_raw('\n'); } - - return { - msg::format(msgVersionVerifiedOK, - msg::version_spec = Strings::concat(port_name, '@', entry.version.version), - msg::commit_sha = entry.git_tree), - expected_left_tag, - }; } - constexpr StringLiteral OPTION_EXCLUDE = "exclude"; constexpr StringLiteral OPTION_VERBOSE = "verbose"; constexpr StringLiteral OPTION_VERIFY_GIT_TREES = "verify-git-trees"; @@ -219,9 +325,6 @@ namespace {OPTION_VERIFY_GIT_TREES, msgCISettingsVerifyGitTree}, }; - constexpr CommandSetting VERIFY_VERSIONS_SETTINGS[] = { - {OPTION_EXCLUDE, msgCISettingsExclude}, - }; } // unnamed namespace namespace vcpkg @@ -234,7 +337,7 @@ namespace vcpkg AutocompletePriority::Internal, 0, SIZE_MAX, - {VERIFY_VERSIONS_SWITCHES, VERIFY_VERSIONS_SETTINGS}, + {VERIFY_VERSIONS_SWITCHES}, nullptr, }; @@ -245,15 +348,6 @@ namespace vcpkg bool verbose = Util::Sets::contains(parsed_args.switches, OPTION_VERBOSE); bool verify_git_trees = Util::Sets::contains(parsed_args.switches, OPTION_VERIFY_GIT_TREES); - std::set exclusion_set; - auto& settings = parsed_args.settings; - auto it_exclusions = settings.find(OPTION_EXCLUDE); - if (it_exclusions != settings.end()) - { - auto exclusions = Strings::split(it_exclusions->second, ','); - exclusion_set.insert(exclusions.begin(), exclusions.end()); - } - auto maybe_port_git_tree_map = paths.git_get_local_port_treeish_map(); if (!maybe_port_git_tree_map) { @@ -268,88 +362,82 @@ namespace vcpkg // Baseline is required. auto baseline = get_builtin_baseline(paths).value_or_exit(VCPKG_LINE_INFO); auto& fs = paths.get_filesystem(); - std::set errors; - for (const auto& port_path : fs.get_directories_non_recursive(paths.builtin_ports_directory(), VCPKG_LINE_INFO)) + LocalizedString errors; + std::map> versions_database; + for (auto&& port_path : fs.get_directories_non_recursive(paths.builtin_ports_directory(), VCPKG_LINE_INFO)) { - auto port_name = port_path.stem(); - if (Util::Sets::contains(exclusion_set, port_name.to_string())) + auto port_name = port_path.stem().to_string(); + auto maybe_loaded_port = Paragraphs::try_load_port_required(fs, port_name, port_path).maybe_scfl; + auto loaded_port = maybe_loaded_port.get(); + if (!loaded_port) { - if (verbose) - { - msg::write_unlocalized_text_to_stdout(Color::error, fmt::format("SKIP: {}\n", port_name)); - } - + errors.append(std::move(maybe_loaded_port).error()).append_raw('\n'); continue; } - auto git_tree_it = port_git_tree_map.find(port_name); - if (git_tree_it == port_git_tree_map.end()) - { - msg::write_unlocalized_text_to_stdout(Color::error, fmt::format("FAIL: {}\n", port_name)); - errors.emplace( - msg::format_error(msgVersionShaMissing, msg::package_name = port_name, msg::path = port_path)); - continue; - } - - auto& git_tree = git_tree_it->second; - auto control_path = port_path / "CONTROL"; - auto manifest_path = port_path / "vcpkg.json"; - auto manifest_exists = fs.exists(manifest_path, IgnoreErrors{}); - auto control_exists = fs.exists(control_path, IgnoreErrors{}); - if (manifest_exists && control_exists) + auto load_versions_result = load_git_versions_file(fs, paths.builtin_registry_versions, port_name); + auto maybe_versions_db = load_versions_result.entries.get(); + if (!maybe_versions_db) { - msg::write_unlocalized_text_to_stdout(Color::error, fmt::format("FAIL: {}\n", port_name)); - errors.emplace(msg::format_error(msgControlAndManifestFilesPresent, msg::path = port_path)); + errors.append(std::move(load_versions_result.entries).error()).append_raw('\n'); continue; } - if (!manifest_exists && !control_exists) + auto versions_db = maybe_versions_db->get(); + if (!versions_db) { - msg::write_unlocalized_text_to_stdout(Color::error, fmt::format("FAIL: {}\n", port_name)); - errors.emplace( - msg::format(msgPortMissingManifest, msg::package_name = port_name, msg::path = port_path)); + errors.append_raw(loaded_port->source_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionDatabaseFileMissing, + msg::package_name = port_name, + msg::path = load_versions_result.versions_file_path) + .append_raw('\n'); continue; } - const char prefix[] = {port_name[0], '-', '\0'}; - auto versions_file_path = paths.builtin_registry_versions / prefix / Strings::concat(port_name, ".json"); - if (!fs.exists(versions_file_path, IgnoreErrors{})) - { - msg::write_unlocalized_text_to_stdout(Color::error, fmt::format("FAIL: {}\n", port_name)); - errors.emplace(msg::format_error( - msgVersionDatabaseFileMissing, msg::package_name = port_name, msg::path = versions_file_path)); - continue; - } + versions_database.emplace(std::move(port_name), + CiVerifyVersionsDbEntry{std::move(*loaded_port), + std::move(port_path), + std::move(*versions_db), + std::move(load_versions_result.versions_file_path)}); + } - auto maybe_ok = verify_version_in_db( - paths, baseline, port_name, port_path, versions_file_path, git_tree, verify_git_trees); - if (auto ok = maybe_ok.get()) + auto& success_sink = verbose ? stdout_sink : null_sink; + for (const auto& port : versions_database) + { + const auto& port_name = port.first; + const auto& db = port.second; + auto git_tree_it = port_git_tree_map.find(port_name); + if (git_tree_it == port_git_tree_map.end()) { - if (verbose) - { - msg::println(*ok); - } + errors.append_raw(db.scf.source_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionShaMissing, msg::package_name = port_name, msg::path = db.port_directory) + .append_raw('\n'); } else { - msg::write_unlocalized_text_to_stdout(Color::error, fmt::format("FAIL: {}\n", port_name)); - errors.emplace(std::move(maybe_ok).error()); + verify_local_port_matches_version_database(errors, success_sink, port_name, db, git_tree_it->second); } - } - if (!errors.empty()) - { - auto message = msg::format(msgErrorsFound); - for (auto&& error : errors) + verify_local_port_matches_baseline( + errors, success_sink, baseline, paths.builtin_registry_versions / "baseline.json", port_name, db); + + if (verify_git_trees) { - message.append_raw('\n').append(error); + verify_all_historical_git_trees(errors, success_sink, paths, port_name, db); } + } - message.append_raw('\n').append( - msgSuggestResolution, msg::command_name = "x-add-version", msg::option = "all"); - msg::println_error(message); - Checks::exit_fail(VCPKG_LINE_INFO); + if (!errors.empty()) + { + errors.append_raw('\n'); + errors.append(msgSuggestResolution, msg::command_name = "x-add-version", msg::option = "all"); + Checks::msg_exit_with_message(VCPKG_LINE_INFO, errors); } + Checks::exit_success(VCPKG_LINE_INFO); } } // namespace vcpkg diff --git a/src/vcpkg/commands.format-manifest.cpp b/src/vcpkg/commands.format-manifest.cpp index be23ab175b..e74dcddfe3 100644 --- a/src/vcpkg/commands.format-manifest.cpp +++ b/src/vcpkg/commands.format-manifest.cpp @@ -2,13 +2,12 @@ #include #include -#include +#include #include +#include #include #include -#include -#include #include #include @@ -18,87 +17,17 @@ namespace { struct ToWrite { - SourceControlFile scf; - Path file_to_write; - Path original_path; std::string original_source; + SourceControlFileAndLocation scf; + Path file_to_write; }; - Optional read_manifest(const ReadOnlyFilesystem& fs, Path&& manifest_path) - { - const auto& path_string = manifest_path.native(); - Debug::println("Reading ", path_string); - auto contents = fs.read_contents(manifest_path, VCPKG_LINE_INFO); - auto parsed_json_opt = Json::parse(contents, manifest_path); - if (!parsed_json_opt) - { - msg::println(Color::error, LocalizedString::from_raw(parsed_json_opt.error()->to_string())); - return nullopt; - } - - const auto& parsed_json = parsed_json_opt.value(VCPKG_LINE_INFO).value; - if (!parsed_json.is_object()) - { - msg::println_error(msgJsonErrorMustBeAnObject, msg::path = path_string); - return nullopt; - } - - auto parsed_json_obj = parsed_json.object(VCPKG_LINE_INFO); - - auto scf = SourceControlFile::parse_project_manifest_object(path_string, parsed_json_obj, stdout_sink); - if (!scf) - { - msg::println_error(msgFailedToParseManifest, msg::path = path_string); - print_error_message(LocalizedString::from_raw(scf.error()->to_string())); - msg::println(); - return nullopt; - } - - return ToWrite{ - std::move(*scf.value(VCPKG_LINE_INFO)), - manifest_path, - manifest_path, - std::move(contents), - }; - } - - Optional read_control_file(const ReadOnlyFilesystem& fs, Path&& control_path) - { - Debug::println("Reading ", control_path); - - auto manifest_path = Path(control_path.parent_path()) / "vcpkg.json"; - auto contents = fs.read_contents(control_path, VCPKG_LINE_INFO); - auto paragraphs = Paragraphs::parse_paragraphs(contents, control_path); - - if (!paragraphs) - { - msg::println_error(msg::format(msgFailedToReadParagraph, msg::path = control_path) - .append_raw(": ") - .append_raw(paragraphs.error())); - return {}; - } - auto scf_res = - SourceControlFile::parse_control_file(control_path, std::move(paragraphs).value(VCPKG_LINE_INFO)); - if (!scf_res) - { - msg::println_error(msgFailedToParseControl, msg::path = control_path); - print_error_message(LocalizedString::from_raw(scf_res.error()->to_string())); - return {}; - } - - return ToWrite{ - std::move(*scf_res.value(VCPKG_LINE_INFO)), - manifest_path, - control_path, - std::move(contents), - }; - } - void open_for_write(const Filesystem& fs, const ToWrite& data) { - const auto& original_path_string = data.original_path.native(); + const auto& original_path_string = data.scf.source_location.native(); const auto& file_to_write_string = data.file_to_write.native(); - if (data.file_to_write == data.original_path) + bool in_place = data.file_to_write == original_path_string; + if (in_place) { Debug::println("Formatting ", file_to_write_string); } @@ -107,14 +36,15 @@ namespace Debug::println("Converting ", file_to_write_string, " -> ", original_path_string); } - auto res = serialize_manifest(data.scf); + auto res = serialize_manifest(*data.scf.source_control_file); // reparse res to ensure no semantic changes were made - auto maybe_reparsed = SourceControlFile::parse_project_manifest_object(StringView{}, res, null_sink); + auto maybe_reparsed = + SourceControlFile::parse_project_manifest_object(StringLiteral{"Researialized manifest"}, res, null_sink); bool reparse_matches; if (auto reparsed = maybe_reparsed.get()) { - reparse_matches = **reparsed == data.scf; + reparse_matches = **reparsed == *data.scf.source_control_file; } else { @@ -132,26 +62,10 @@ namespace Json::stringify(res, {})))); } - // the manifest scf is correct - std::error_code ec; - fs.write_contents(data.file_to_write, Json::stringify(res), ec); - if (ec) + fs.write_contents(data.file_to_write, Json::stringify(res), VCPKG_LINE_INFO); + if (!in_place) { - Checks::msg_exit_with_error(VCPKG_LINE_INFO, - msg::format(msgFailedToWriteManifest, msg::path = file_to_write_string) - .append_raw(": ") - .append_raw(ec.message())); - } - if (data.original_path != data.file_to_write) - { - fs.remove(data.original_path, ec); - if (ec) - { - Checks::msg_exit_with_error(VCPKG_LINE_INFO, - msg::format(msgFailedToRemoveControl, msg::path = original_path_string) - .append_raw(": ") - .append_raw(ec.message())); - } + fs.remove(original_path_string, VCPKG_LINE_INFO); } } @@ -200,18 +114,6 @@ namespace vcpkg } std::vector to_write; - - const auto add_file = [&to_write, &has_error](Optional&& opt) { - if (auto t = opt.get()) - { - to_write.push_back(std::move(*t)); - } - else - { - has_error = true; - } - }; - for (Path path : parsed_args.command_arguments) { if (path.is_relative()) @@ -219,13 +121,42 @@ namespace vcpkg path = paths.original_cwd / path; } + auto maybe_contents = fs.try_read_contents(path); + auto contents = maybe_contents.get(); + if (!contents) + { + has_error = true; + msg::println(maybe_contents.error()); + continue; + } + if (path.filename() == "CONTROL") { - add_file(read_control_file(fs, std::move(path))); + auto maybe_control = Paragraphs::try_load_control_file_text(contents->content, contents->origin); + if (auto control = maybe_control.get()) + { + to_write.push_back( + ToWrite{contents->content, std::move(*control), Path(path.parent_path()) / "vcpkg.json"}); + } + else + { + has_error = true; + msg::println(maybe_control.error()); + } } else { - add_file(read_manifest(fs, std::move(path))); + auto maybe_manifest = + Paragraphs::try_load_port_manifest_text(contents->content, contents->origin, stdout_sink); + if (auto manifest = maybe_manifest.get()) + { + to_write.push_back(ToWrite{contents->content, std::move(*manifest), path}); + } + else + { + has_error = true; + msg::println(maybe_manifest.error()); + } } } @@ -233,23 +164,17 @@ namespace vcpkg { for (const auto& dir : fs.get_directories_non_recursive(paths.builtin_ports_directory(), VCPKG_LINE_INFO)) { - auto control_path = dir / "CONTROL"; - auto manifest_path = dir / "vcpkg.json"; - auto manifest_exists = fs.exists(manifest_path, IgnoreErrors{}); - auto control_exists = fs.exists(control_path, IgnoreErrors{}); - - if (manifest_exists && control_exists) - { - Checks::msg_exit_with_error(VCPKG_LINE_INFO, msgControlAndManifestFilesPresent, msg::path = dir); - } - - if (manifest_exists) + auto maybe_manifest = Paragraphs::try_load_port_required(fs, dir.filename(), dir); + if (auto manifest = maybe_manifest.maybe_scfl.get()) { - add_file(read_manifest(fs, std::move(manifest_path))); + auto original = manifest->source_location; + to_write.push_back( + ToWrite{maybe_manifest.on_disk_contents, std::move(*manifest), std::move(original)}); } - if (convert_control && control_exists) + else { - add_file(read_control_file(fs, std::move(control_path))); + has_error = true; + msg::println(maybe_manifest.maybe_scfl.error()); } } } diff --git a/src/vcpkg/paragraphs.cpp b/src/vcpkg/paragraphs.cpp index 238846dc83..453e617aca 100644 --- a/src/vcpkg/paragraphs.cpp +++ b/src/vcpkg/paragraphs.cpp @@ -26,51 +26,77 @@ namespace vcpkg return; } - target.append(msg::format_error(msgParseControlErrorInfoWhileLoading, msg::path = name).extract_data()); + bool newline_needed = false; if (!error.empty()) { - target.push_back('\n'); target.append(error.data()); + newline_needed = true; } - if (!other_errors.empty()) + for (auto&& msg : other_errors) { - for (auto&& msg : other_errors) + if (newline_needed) { target.push_back('\n'); - target.append(msg.data()); } + + target.append(msg.data()); + newline_needed = true; } if (!extra_fields.empty()) { - target.push_back('\n'); - target.append(msg::format(msgParseControlErrorInfoInvalidFields) + if (newline_needed) + { + target.push_back('\n'); + } + + target.append(msg::format_error(msgParseControlErrorInfoWhileLoading, msg::path = name) + .append_raw(' ') + .append(msgParseControlErrorInfoInvalidFields) .append_raw(' ') .append_raw(Strings::join(", ", extra_fields)) .extract_data()); + newline_needed = true; } if (!missing_fields.empty()) { - target.push_back('\n'); - target.append(msg::format(msgParseControlErrorInfoMissingFields) + if (newline_needed) + { + target.push_back('\n'); + } + + target.append(msg::format_error(msgParseControlErrorInfoWhileLoading, msg::path = name) + .append_raw(' ') + .append(msgParseControlErrorInfoMissingFields) .append_raw(' ') .append_raw(Strings::join(", ", missing_fields)) .extract_data()); + newline_needed = true; } if (!expected_types.empty()) { - auto expected_types_component = msg::format_error(msgParseControlErrorInfoWrongTypeFields); + if (newline_needed) + { + target.push_back('\n'); + } + + target.append(msg::format_error(msgParseControlErrorInfoWhileLoading, msg::path = name) + .append_raw(' ') + .append(msgParseControlErrorInfoWrongTypeFields) + .extract_data()); for (auto&& pr : expected_types) { - expected_types_component.append_raw('\n').append_indent().append( - msgParseControlErrorInfoTypesEntry, msg::value = pr.first, msg::expected = pr.second); + target.append( + LocalizedString::from_raw("\n") + .append_indent() + .append(msgParseControlErrorInfoTypesEntry, msg::value = pr.first, msg::expected = pr.second) + .extract_data()); } - target.push_back('\n'); - target.append(expected_types_component.extract_data()); + newline_needed = true; } } @@ -375,50 +401,47 @@ namespace vcpkg::Paragraphs fs.exists(maybe_directory / "vcpkg.json", IgnoreErrors{}); } - static ExpectedL> try_load_manifest_text(const std::string& text, - StringView origin, - MessageSink& warning_sink) + ExpectedL try_load_port_manifest_text(StringView text, + StringView origin, + MessageSink& warning_sink) { - auto res = Json::parse(text, origin); - if (auto val = res.get()) + StatsTimer timer(g_load_ports_stats); + auto maybe_object = Json::parse_object(text, origin); + if (auto object = maybe_object.get()) { - if (val->value.is_object()) + auto maybe_parsed = map_parse_expected_to_localized_string( + SourceControlFile::parse_port_manifest_object(origin, *object, warning_sink)); + if (auto parsed = maybe_parsed.get()) { - return map_parse_expected_to_localized_string(SourceControlFile::parse_port_manifest_object( - origin, val->value.object(VCPKG_LINE_INFO), warning_sink)); + return SourceControlFileAndLocation{std::move(*parsed), origin.to_string()}; } - return msg::format(msgJsonValueNotObject); + return std::move(maybe_parsed).error(); } - return LocalizedString::from_raw(res.error()->to_string()); + return std::move(maybe_object).error(); } - ExpectedL> try_load_port_text(const std::string& text, - StringView origin, - bool is_manifest, - MessageSink& warning_sink) + ExpectedL try_load_control_file_text(StringView text, StringView origin) { StatsTimer timer(g_load_ports_stats); - - if (is_manifest) - { - return try_load_manifest_text(text, origin, warning_sink); - } - - ExpectedL> pghs = parse_paragraphs(StringView{text}, origin); + ExpectedL> pghs = parse_paragraphs(text, origin); if (auto vector_pghs = pghs.get()) { - return map_parse_expected_to_localized_string( + auto maybe_parsed = map_parse_expected_to_localized_string( SourceControlFile::parse_control_file(origin, std::move(*vector_pghs))); + if (auto parsed = maybe_parsed.get()) + { + return SourceControlFileAndLocation{std::move(*parsed), origin.to_string()}; + } + + return std::move(maybe_parsed).error(); } return std::move(pghs).error(); } - ExpectedL> try_load_port(const ReadOnlyFilesystem& fs, - StringView port_name, - const Path& port_directory) + PortLoadResult try_load_port(const ReadOnlyFilesystem& fs, StringView port_name, const Path& port_directory) { StatsTimer timer(g_load_ports_stats); @@ -428,73 +451,75 @@ namespace vcpkg::Paragraphs auto manifest_contents = fs.read_contents(manifest_path, ec); if (ec) { - const auto exists = ec != std::errc::no_such_file_or_directory; - if (exists) + auto manifest_exists = ec != std::errc::no_such_file_or_directory; + if (manifest_exists) { - return msg::format_error(msgFailedToParseManifest, msg::path = manifest_path) - .append_raw("\n") - .append(format_filesystem_call_error(ec, "read_contents", {manifest_path})); + return PortLoadResult{LocalizedString::from_raw(port_directory) + .append_raw(": ") + .append(format_filesystem_call_error(ec, "read_contents", {manifest_path})), + std::string{}}; } - if (fs.exists(control_path, IgnoreErrors{})) + auto control_contents = fs.read_contents(control_path, ec); + if (ec) { - ExpectedL> pghs = get_paragraphs(fs, control_path); - if (auto vector_pghs = pghs.get()) + if (ec != std::errc::no_such_file_or_directory) { - auto maybe_parsed_control = - SourceControlFile::parse_control_file(control_path, std::move(*vector_pghs)); - if (auto parsed_control = maybe_parsed_control.get()) - { - return std::move(*parsed_control); - } - - return LocalizedString::from_raw(maybe_parsed_control.error()->to_string()); + return PortLoadResult{ + LocalizedString::from_raw(port_directory) + .append_raw(": ") + .append(format_filesystem_call_error(ec, "read_contents", {control_path})), + std::string{}}; } - return std::move(pghs).error(); - } + if (fs.exists(port_directory, IgnoreErrors{})) + { + return PortLoadResult{LocalizedString::from_raw(port_directory) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgPortMissingManifest2, msg::package_name = port_name), + std::string{}}; + } - if (fs.exists(port_directory, IgnoreErrors{})) - { - return msg::format_error( - msgPortMissingManifest, msg::package_name = port_name, msg::path = port_directory); + return PortLoadResult{LocalizedString::from_raw(port_directory) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgPortDoesNotExist, msg::package_name = port_name), + std::string{}}; } - return std::unique_ptr(); + return PortLoadResult{try_load_control_file_text(control_contents, control_path), control_contents}; } if (fs.exists(control_path, IgnoreErrors{})) { - return msg::format_error(msgManifestConflict, msg::path = port_directory); - } - - auto maybe_parsed = try_load_manifest_text(manifest_contents, manifest_path, stdout_sink); - if (auto parsed = maybe_parsed.get()) - { - return std::move(*parsed); + return PortLoadResult{LocalizedString::from_raw(port_directory) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgManifestConflict2), + std::string{}}; } - return std::move(maybe_parsed).error(); + return PortLoadResult{try_load_port_manifest_text(manifest_contents, manifest_path, stdout_sink), + manifest_contents}; } - ExpectedL> try_load_port_required(const ReadOnlyFilesystem& fs, - StringView port_name, - const Path& port_directory) + PortLoadResult try_load_port_required(const ReadOnlyFilesystem& fs, + StringView port_name, + const Path& port_directory) { auto maybe_maybe_res = try_load_port(fs, port_name, port_directory); - auto maybe_res = maybe_maybe_res.get(); - if (!maybe_res) + auto maybe_res = maybe_maybe_res.maybe_scfl.get(); + if (maybe_res) { - return std::move(maybe_maybe_res).error(); - } - - auto res = maybe_res->get(); - if (!res) - { - return msg::format_error(msgPortDoesNotExist, msg::package_name = port_name); + auto res = maybe_res->source_control_file.get(); + if (!res) + { + maybe_maybe_res.maybe_scfl = msg::format_error(msgPortDoesNotExist, msg::package_name = port_name); + } } - return std::move(*maybe_res); + return maybe_maybe_res; } ExpectedL try_load_cached_package(const ReadOnlyFilesystem& fs, @@ -554,14 +579,10 @@ namespace vcpkg::Paragraphs auto maybe_port_location = (*port_entry)->get_version(*baseline_version); const auto port_location = maybe_port_location.get(); if (!port_location) continue; // baseline version was not in version db (registry consistency issue) - auto maybe_spgh = try_load_port_required(fs, port_name, port_location->path); + auto maybe_spgh = try_load_port_required(fs, port_name, port_location->path).maybe_scfl; if (const auto spgh = maybe_spgh.get()) { - ret.paragraphs.push_back({ - std::move(*spgh), - std::move(port_location->path), - std::move(port_location->location), - }); + ret.paragraphs.push_back(std::move(*spgh)); } else { @@ -620,10 +641,10 @@ namespace vcpkg::Paragraphs for (auto&& path : port_dirs) { auto port_name = path.filename(); - auto maybe_spgh = try_load_port_required(fs, port_name, path); + auto maybe_spgh = try_load_port_required(fs, port_name, path).maybe_scfl; if (const auto spgh = maybe_spgh.get()) { - ret.paragraphs.push_back({std::move(*spgh), std::move(path)}); + ret.paragraphs.push_back(std::move(*spgh)); } else { diff --git a/src/vcpkg/portfileprovider.cpp b/src/vcpkg/portfileprovider.cpp index 6830d1ef37..4380e9164f 100644 --- a/src/vcpkg/portfileprovider.cpp +++ b/src/vcpkg/portfileprovider.cpp @@ -179,8 +179,7 @@ namespace vcpkg .value_or_exit(VCPKG_LINE_INFO); } - ExpectedL> load_control_file( - const VersionSpec& version_spec) const + ExpectedL load_control_file(const VersionSpec& version_spec) const { const auto& maybe_ent = entry(version_spec.port_name); if (auto ent = maybe_ent.get()) @@ -189,17 +188,13 @@ namespace vcpkg if (auto path = maybe_path.get()) { auto maybe_control_file = - Paragraphs::try_load_port_required(m_fs, version_spec.port_name, path->path); + Paragraphs::try_load_port_required(m_fs, version_spec.port_name, path->path).maybe_scfl; if (auto scf = maybe_control_file.get()) { - auto scf_vspec = scf->get()->to_version_spec(); + auto scf_vspec = scf->source_control_file.get()->to_version_spec(); if (scf_vspec == version_spec) { - return std::make_unique(SourceControlFileAndLocation{ - std::move(*scf), - std::move(path->path), - std::move(path->location), - }); + return std::move(*scf); } else { @@ -238,7 +233,9 @@ namespace vcpkg { it = m_control_cache.emplace(version_spec, load_control_file(version_spec)).first; } - return it->second.map([](const auto& x) -> const SourceControlFileAndLocation& { return *x.get(); }); + + return it->second.map( + [](const SourceControlFileAndLocation& x) -> const SourceControlFileAndLocation& { return x; }); } virtual void load_all_control_files( @@ -249,20 +246,16 @@ namespace vcpkg { auto port_name = scfl.source_control_file->core_paragraph->name; auto version = scfl.source_control_file->core_paragraph->to_version(); - auto it = m_control_cache - .emplace(VersionSpec{port_name, version}, - std::make_unique(std::move(scfl))) - .first; - out.emplace(it->first.port_name, it->second.value_or_exit(VCPKG_LINE_INFO).get()); + auto it = m_control_cache.emplace(VersionSpec{port_name, version}, std::move(scfl)).first; + out.emplace(it->first.port_name, &it->second.value_or_exit(VCPKG_LINE_INFO)); } } private: const ReadOnlyFilesystem& m_fs; const RegistrySet& m_registry_set; - mutable std:: - unordered_map>, VersionSpecHasher> - m_control_cache; + mutable std::unordered_map, VersionSpecHasher> + m_control_cache; mutable std::map>, std::less<>> m_entry_cache; }; @@ -296,13 +289,12 @@ namespace vcpkg // Try loading individual port if (Paragraphs::is_port_directory(m_fs, ports_dir)) { - auto maybe_scf = Paragraphs::try_load_port_required(m_fs, port_name, ports_dir); + auto maybe_scf = Paragraphs::try_load_port_required(m_fs, port_name, ports_dir).maybe_scfl; if (auto scfp = maybe_scf.get()) { - auto& scf = *scfp; - if (scf->core_paragraph->name == port_name) + if (scfp->source_control_file->core_paragraph->name == port_name) { - return SourceControlFileAndLocation{std::move(scf), ports_dir}; + return std::move(*scfp); } } else @@ -320,13 +312,12 @@ namespace vcpkg auto ports_spec = ports_dir / port_name; if (Paragraphs::is_port_directory(m_fs, ports_spec)) { - auto found_scf = Paragraphs::try_load_port_required(m_fs, port_name, ports_spec); + auto found_scf = Paragraphs::try_load_port_required(m_fs, port_name, ports_spec).maybe_scfl; if (auto scfp = found_scf.get()) { - auto& scf = *scfp; - if (scf->core_paragraph->name == port_name) + if (scfp->source_control_file->core_paragraph->name == port_name) { - return SourceControlFileAndLocation{std::move(scf), std::move(ports_spec)}; + return std::move(*scfp); } Checks::msg_exit_maybe_upgrade( @@ -335,7 +326,7 @@ namespace vcpkg .append_raw('\n') .append(msgMismatchedNames, msg::package_name = port_name, - msg::actual = scf->core_paragraph->name)); + msg::actual = scfp->source_control_file->core_paragraph->name)); } else { @@ -371,12 +362,13 @@ namespace vcpkg // Try loading individual port if (Paragraphs::is_port_directory(m_fs, ports_dir)) { - auto maybe_scf = Paragraphs::try_load_port_required(m_fs, ports_dir.filename(), ports_dir); + auto maybe_scf = + Paragraphs::try_load_port_required(m_fs, ports_dir.filename(), ports_dir).maybe_scfl; if (auto scfp = maybe_scf.get()) { - SourceControlFileAndLocation scfl{std::move(*scfp), ports_dir}; - auto name = scfl.source_control_file->core_paragraph->name; - auto it = m_overlay_cache.emplace(std::move(name), std::move(scfl)).first; + // copy name before moving *scfp + auto name = scfp->source_control_file->core_paragraph->name; + auto it = m_overlay_cache.emplace(std::move(name), std::move(*scfp)).first; Checks::check_exit(VCPKG_LINE_INFO, it->second.get()); out.emplace(it->first, it->second.get()); } diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index 47b1dac589..6857ee8d3f 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -488,14 +488,15 @@ namespace DelayedInit m_baseline; private: - const ExpectedL>& get_scf(StringView port_name, const Path& path) const + const ExpectedL& get_scf(StringView port_name, const Path& path) const { - return m_scfs.get_lazy(path, [&, this]() { return Paragraphs::try_load_port(m_fs, port_name, path); }); + return m_scfs.get_lazy(path, + [&, this]() { return Paragraphs::try_load_port(m_fs, port_name, path).maybe_scfl; }); } const ReadOnlyFilesystem& m_fs; const Path m_builtin_ports_directory; - Cache>> m_scfs; + Cache> m_scfs; }; constexpr StringLiteral BuiltinFilesRegistry::s_kind; @@ -592,12 +593,6 @@ namespace }; Path relative_path_to_versions(StringView port_name); - ExpectedL>> load_git_versions_file(const ReadOnlyFilesystem& fs, - const Path& registry_versions, - StringView port_name); - - ExpectedL>> load_filesystem_versions_file( - const ReadOnlyFilesystem& fs, const Path& registry_versions, StringView port_name, const Path& registry_root); // returns nullopt if the baseline is valid, but doesn't contain the specified baseline, // or (equivalently) if the baseline does not exist. @@ -718,7 +713,7 @@ namespace return maybe_maybe_scf.error(); } - auto scf = maybe_scf->get(); + auto scf = maybe_scf->source_control_file.get(); if (!scf) { return std::unique_ptr(); @@ -746,7 +741,7 @@ namespace return maybe_maybe_scf.error(); } - auto scf = maybe_scf->get(); + auto scf = maybe_scf->source_control_file.get(); if (!scf) { return Optional(); @@ -786,7 +781,8 @@ namespace const auto& fs = m_paths.get_filesystem(); auto versions_path = m_paths.builtin_registry_versions / relative_path_to_versions(port_name); - auto maybe_maybe_version_entries = load_git_versions_file(fs, m_paths.builtin_registry_versions, port_name); + auto maybe_maybe_version_entries = + load_git_versions_file(fs, m_paths.builtin_registry_versions, port_name).entries; auto maybe_version_entries = maybe_maybe_version_entries.get(); if (!maybe_version_entries) { @@ -947,7 +943,7 @@ namespace { // try to load using "stale" version database auto maybe_maybe_version_entries = - load_git_versions_file(m_paths.get_filesystem(), stale_vtp->p, port_name); + load_git_versions_file(m_paths.get_filesystem(), stale_vtp->p, port_name).entries; auto maybe_version_entries = maybe_maybe_version_entries.get(); if (!maybe_version_entries) { @@ -976,7 +972,8 @@ namespace } { - auto maybe_maybe_version_entries = load_git_versions_file(m_paths.get_filesystem(), *live_vcb, port_name); + auto maybe_maybe_version_entries = + load_git_versions_file(m_paths.get_filesystem(), *live_vcb, port_name).entries; auto maybe_version_entries = maybe_maybe_version_entries.get(); if (!maybe_version_entries) { @@ -1203,7 +1200,7 @@ namespace } auto maybe_maybe_version_entries = - load_git_versions_file(parent.m_paths.get_filesystem(), *live_vdb, port_name); + load_git_versions_file(parent.m_paths.get_filesystem(), *live_vdb, port_name).entries; auto maybe_version_entries = maybe_maybe_version_entries.get(); if (!maybe_version_entries) { @@ -1309,114 +1306,17 @@ namespace return Path(prefix) / port_name.to_string() + ".json"; } - ExpectedL>> load_git_versions_file(const ReadOnlyFilesystem& fs, - const Path& registry_versions, - StringView port_name) - { - auto versions_file_path = registry_versions / relative_path_to_versions(port_name); - std::error_code ec; - auto contents = fs.read_contents(versions_file_path, ec); - if (ec) - { - if (ec == std::errc::no_such_file_or_directory) - { - return Optional>{}; - } - - return format_filesystem_call_error(ec, "read_contents", {versions_file_path}); - } - - auto maybe_versions_json = Json::parse_object(contents, versions_file_path); - auto versions_json = maybe_versions_json.get(); - if (!versions_json) - { - return std::move(maybe_versions_json).error(); - } - - auto maybe_versions_array = versions_json->get("versions"); - if (!maybe_versions_array || !maybe_versions_array->is_array()) - { - return msg::format_error(msgFailedToParseNoVersionsArray, msg::path = versions_file_path); - } - - std::vector db_entries; - GitVersionDbEntryArrayDeserializer deserializer{}; - Json::Reader r; - r.visit_in_key(*maybe_versions_array, "versions", db_entries, deserializer); - if (!r.errors().empty()) - { - return msg::format_error(msgFailedToParseVersionsFile, msg::path = versions_file_path) - .append_raw(Strings::join("\n", r.errors())); - } - - return db_entries; - } - - ExpectedL>> load_filesystem_versions_file( - const ReadOnlyFilesystem& fs, const Path& registry_versions, StringView port_name, const Path& registry_root) - { - if (registry_root.empty()) - { - Checks::unreachable(VCPKG_LINE_INFO, "type should never = Filesystem when registry_root is empty."); - } - - auto versions_file_path = registry_versions / relative_path_to_versions(port_name); - std::error_code ec; - auto contents = fs.read_contents(versions_file_path, ec); - if (ec) - { - if (ec == std::errc::no_such_file_or_directory) - { - return Optional>{}; - } - - return format_filesystem_call_error(ec, "read_contents", {versions_file_path}); - } - - auto maybe_versions_json = Json::parse_object(contents, versions_file_path); - auto versions_json = maybe_versions_json.get(); - if (!versions_json) - { - return std::move(maybe_versions_json).error(); - } - - auto maybe_versions_array = versions_json->get("versions"); - if (!maybe_versions_array || !maybe_versions_array->is_array()) - { - return msg::format_error(msgFailedToParseNoVersionsArray, msg::path = versions_file_path); - } - - std::vector db_entries; - FilesystemVersionDbEntryArrayDeserializer deserializer{registry_root}; - Json::Reader r; - r.visit_in_key(*maybe_versions_array, "versions", db_entries, deserializer); - if (!r.errors().empty()) - { - return msg::format_error(msgFailedToParseVersionsFile, msg::path = versions_file_path) - .append_raw(Strings::join("\n", r.errors())); - } - - return db_entries; - } - ExpectedL> parse_baseline_versions(StringView contents, StringView baseline, StringView origin) { - auto maybe_value = Json::parse(contents, origin); - if (!maybe_value) - { - return LocalizedString::from_raw(maybe_value.error()->to_string()); - } - - auto& value = *maybe_value.get(); - if (!value.value.is_object()) + auto maybe_object = Json::parse_object(contents, origin); + auto object = maybe_object.get(); + if (!object) { - return msg::format_error(msgFailedToParseNoTopLevelObj, msg::path = origin); + return std::move(maybe_object).error(); } auto real_baseline = baseline.size() == 0 ? "default" : baseline; - - const auto& obj = value.value.object(VCPKG_LINE_INFO); - auto baseline_value = obj.get(real_baseline); + auto baseline_value = object->get(real_baseline); if (!baseline_value) { return {nullopt, expected_left_tag}; @@ -1689,11 +1589,126 @@ namespace vcpkg Util::sort_unique_erase(result); return result; } +} // namespace vcpkg + +namespace +{ + ExpectedL>> load_git_versions_file_impl(const ReadOnlyFilesystem& fs, + const Path& versions_file_path) + { + std::error_code ec; + auto contents = fs.read_contents(versions_file_path, ec); + if (ec) + { + if (ec == std::errc::no_such_file_or_directory) + { + return nullopt; + } + + return format_filesystem_call_error(ec, "read_contents", {versions_file_path}); + } + + auto maybe_versions_json = Json::parse_object(contents, versions_file_path); + auto versions_json = maybe_versions_json.get(); + if (!versions_json) + { + return std::move(maybe_versions_json).error(); + } + + auto maybe_versions_array = versions_json->get("versions"); + if (!maybe_versions_array || !maybe_versions_array->is_array()) + { + return msg::format_error(msgFailedToParseNoVersionsArray, msg::path = versions_file_path); + } + + std::vector db_entries; + GitVersionDbEntryArrayDeserializer deserializer{}; + Json::Reader r; + r.visit_in_key(*maybe_versions_array, "versions", db_entries, deserializer); + if (!r.errors().empty()) + { + return msg::format_error(msgFailedToParseVersionsFile, msg::path = versions_file_path) + .append_raw(Strings::join("\n", r.errors())); + } + + return db_entries; + } + + ExpectedL>> load_filesystem_versions_file_impl( + const ReadOnlyFilesystem& fs, const Path& versions_file_path, const Path& registry_root) + { + std::error_code ec; + auto contents = fs.read_contents(versions_file_path, ec); + if (ec) + { + if (ec == std::errc::no_such_file_or_directory) + { + return Optional>{}; + } + + return format_filesystem_call_error(ec, "read_contents", {versions_file_path}); + } + + auto maybe_versions_json = Json::parse_object(contents, versions_file_path); + auto versions_json = maybe_versions_json.get(); + if (!versions_json) + { + return std::move(maybe_versions_json).error(); + } + + auto maybe_versions_array = versions_json->get("versions"); + if (!maybe_versions_array || !maybe_versions_array->is_array()) + { + return msg::format_error(msgFailedToParseNoVersionsArray, msg::path = versions_file_path); + } + + std::vector db_entries; + FilesystemVersionDbEntryArrayDeserializer deserializer{registry_root}; + Json::Reader r; + r.visit_in_key(*maybe_versions_array, "versions", db_entries, deserializer); + if (!r.errors().empty()) + { + return msg::format_error(msgFailedToParseVersionsFile, msg::path = versions_file_path) + .append_raw(Strings::join("\n", r.errors())); + } + + return db_entries; + } +} // unnamed namespace + +namespace vcpkg +{ + GitVersionsLoadResult load_git_versions_file(const ReadOnlyFilesystem& fs, + const Path& registry_versions, + StringView port_name) + { + auto versions_file_path = registry_versions / relative_path_to_versions(port_name); + auto result = load_git_versions_file_impl(fs, versions_file_path); + if (!result) + { + result.error() + .append_raw('\n') + .append(msgNoteMessage) + .append(msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file_path); + } + + return {std::move(result), std::move(versions_file_path)}; + } - ExpectedL>> get_builtin_versions(const VcpkgPaths& paths, - StringView port_name) + ExpectedL>> load_filesystem_versions_file( + const ReadOnlyFilesystem& fs, const Path& registry_versions, StringView port_name, const Path& registry_root) { - return load_git_versions_file(paths.get_filesystem(), paths.builtin_registry_versions, port_name); + auto versions_file_path = registry_versions / relative_path_to_versions(port_name); + auto result = load_filesystem_versions_file_impl(fs, versions_file_path, registry_root); + if (!result) + { + result.error() + .append_raw('\n') + .append(msgNoteMessage) + .append(msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file_path); + } + + return result; } ExpectedL get_builtin_baseline(const VcpkgPaths& paths) diff --git a/src/vcpkg/spdx.cpp b/src/vcpkg/spdx.cpp index 374e36a1f6..975f496229 100644 --- a/src/vcpkg/spdx.cpp +++ b/src/vcpkg/spdx.cpp @@ -167,7 +167,7 @@ std::string vcpkg::create_spdx_sbom(const InstallPlanAction& action, obj.insert("name", action.spec.name()); obj.insert("SPDXID", "SPDXRef-port"); obj.insert("versionInfo", cpgh.to_version().to_string()); - obj.insert("downloadLocation", scfl.registry_location.empty() ? noassert : scfl.registry_location); + obj.insert("downloadLocation", noassert); if (!cpgh.homepage.empty()) { obj.insert("homepage", cpgh.homepage); diff --git a/src/vcpkg/vcpkgpaths.cpp b/src/vcpkg/vcpkgpaths.cpp index 5289bc985d..969e684552 100644 --- a/src/vcpkg/vcpkgpaths.cpp +++ b/src/vcpkg/vcpkgpaths.cpp @@ -73,28 +73,19 @@ namespace { std::error_code ec; auto manifest_path = manifest_dir / "vcpkg.json"; - auto manifest_opt = Json::parse_file(fs, manifest_path, ec); - if (ec) - { - Checks::msg_exit_maybe_upgrade(VCPKG_LINE_INFO, - msg::format(msgFailedToLoadManifest, msg::path = manifest_dir) - .append_raw('\n') - .append_raw(ec.message())); - } + auto maybe_manifest_object = fs.try_read_contents(manifest_path).then([](FileContents&& contents) { + return Json::parse_object(contents.content, contents.origin); + }); - if (!manifest_opt) + if (auto manifest_object = maybe_manifest_object.get()) { - Checks::msg_exit_maybe_upgrade(VCPKG_LINE_INFO, - LocalizedString::from_raw(manifest_opt.error()->to_string())); + return ManifestAndPath{std::move(*manifest_object), std::move(manifest_path)}; } - auto manifest_value = std::move(manifest_opt).value(VCPKG_LINE_INFO).value; - if (!manifest_value.is_object()) - { - msg::println_error(msgFailedToParseNoTopLevelObj, msg::path = manifest_path); - Checks::exit_fail(VCPKG_LINE_INFO); - } - return {std::move(manifest_value).object(VCPKG_LINE_INFO), std::move(manifest_path)}; + Checks::msg_exit_maybe_upgrade(VCPKG_LINE_INFO, + msg::format(msgFailedToLoadManifest, msg::path = manifest_dir) + .append_raw('\n') + .append(maybe_manifest_object.error())); } static Optional config_from_manifest(const Optional& manifest_doc) diff --git a/src/vcpkg/versions.cpp b/src/vcpkg/versions.cpp index 7cfbcc400e..de10ebfd7d 100644 --- a/src/vcpkg/versions.cpp +++ b/src/vcpkg/versions.cpp @@ -341,6 +341,8 @@ namespace vcpkg return lhs.scheme == rhs.scheme && lhs.version == rhs.version; } + bool operator!=(const SchemedVersion& lhs, const SchemedVersion& rhs) { return !(lhs == rhs); } + StringLiteral to_string_literal(VersionScheme scheme) { static constexpr StringLiteral MISSING = "missing"; From a741b84c3668f56b51d2538cd19dc274e9421122 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Fri, 22 Sep 2023 22:58:18 -0700 Subject: [PATCH 05/48] Teach vcpkg to find bogus version constraints and overrides that are meaningless because they aren't in the version database. --- include/vcpkg/base/message-data.inc.h | 33 +++++- include/vcpkg/base/util.h | 6 ++ include/vcpkg/sourceparagraph.h | 4 +- locales/messages.json | 11 ++ src/vcpkg-test/dependencies.cpp | 126 +++++++++++----------- src/vcpkg-test/manifests.cpp | 28 ++--- src/vcpkg/commands.ci-verify-versions.cpp | 114 ++++++++++++++++++++ src/vcpkg/dependencies.cpp | 2 +- src/vcpkg/sourceparagraph.cpp | 17 +-- 9 files changed, 246 insertions(+), 95 deletions(-) diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 30b394297a..211064e952 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -993,6 +993,11 @@ DECLARE_MESSAGE(DeleteVcpkgConfigFromManifest, DECLARE_MESSAGE(DependencyGraphCalculation, (), "", "Dependency graph submission enabled.") DECLARE_MESSAGE(DependencyGraphFailure, (), "", "Dependency graph submission failed.") DECLARE_MESSAGE(DependencyGraphSuccess, (), "", "Dependency graph submission successful.") +DECLARE_MESSAGE(DependencyInFeature, (msg::feature), "", "the dependency is in the feature named {feature}.") +DECLARE_MESSAGE(DependencyNotInVersionDatabase, + (msg::package_name), + "", + "the dependency {package_name} does not exist in the version database; does that port exist?") DECLARE_MESSAGE(DeprecatedPrefabDebugOption, (), "", "--prefab-debug is now deprecated.") DECLARE_MESSAGE(DetectCompilerHash, (msg::triplet), "", "Detecting compiler hash for triplet {triplet}...") DECLARE_MESSAGE(DocumentedFieldsSuggestUpdate, @@ -2954,6 +2959,11 @@ DECLARE_MESSAGE(VersionBaselineMismatch, "git add versions\n" "git commit -m \"Update version database\"\n" "to update the baseline version.") +DECLARE_MESSAGE(VersionBuiltinPortTreeEntryMissing, + (msg::package_name, msg::expected, msg::actual), + "{expected} and {actual} are versions like 1.0.", + "no version database entry for {package_name} at {expected}; using the checked out ports tree " + "version ({actual}).") DECLARE_MESSAGE(VersionCommandHeader, (msg::version), "", @@ -2963,6 +2973,13 @@ DECLARE_MESSAGE( (msg::path, msg::expected_version, msg::actual_version), "", "Expected {path} version: [{expected_version}], but was [{actual_version}]. Please re-run bootstrap-vcpkg.") +DECLARE_MESSAGE(VersionConstraintNotInDatabase, + (msg::package_name, msg::version, msg::path), + "", + "the \"version>=\" constraint to {package_name} names version {version} which does not exist in the " + "version database. All versions must exist in the version database to be interpreted by vcpkg. " + "Consider removing the version constraint or choosing a value declared in {path}.") +DECLARE_MESSAGE(VersionConstraintOk, (), "", "All version constraints are consistent with the version database") DECLARE_MESSAGE(VersionConstraintPortVersionMustBePositiveInteger, (), "", @@ -2984,11 +3001,6 @@ DECLARE_MESSAGE(VersionDatabaseFileMissing, "", "missing a version database file at {path}\n" "note: run 'vcpkg x-add-version {package_name}' to create the version database file.") -DECLARE_MESSAGE(VersionBuiltinPortTreeEntryMissing, - (msg::package_name, msg::expected, msg::actual), - "{expected} and {actual} are versions like 1.0.", - "no version database entry for {package_name} at {expected}; using the checked out ports tree " - "version ({actual}).") DECLARE_MESSAGE(VersionDatabaseEntryMissing, (msg::package_name, msg::version), "", @@ -3049,6 +3061,17 @@ DECLARE_MESSAGE(VersionNotFoundInVersionsFile2, "", "{version_spec} was not found in versions database {path}.\n" "note: run 'vcpkg x-add-version {package_name}' to add the new port version.") +DECLARE_MESSAGE(VersionOverrideNotInVersionDatabase, + (msg::package_name), + "", + "the version override {package_name} does not exist in the version database; does that port exist?") +DECLARE_MESSAGE( + VersionOverrideVersionNotInVersionDatabase, + (msg::package_name, msg::version, msg::path), + "", + "the override of {package_name} names version {version} which does not exist in the " + "version database. Installing this port at the top level will fail as that version will be unresolvable. " + "Consider removing the version override or choosing a value declared in {path}.") DECLARE_MESSAGE(VersionRejectedDueToBaselineMissing, (msg::path, msg::json_field), "", diff --git a/include/vcpkg/base/util.h b/include/vcpkg/base/util.h index fcffb9aa6b..9acd5ea63a 100644 --- a/include/vcpkg/base/util.h +++ b/include/vcpkg/base/util.h @@ -414,6 +414,12 @@ namespace vcpkg::Util return std::any_of(rng.begin(), rng.end(), std::move(pred)); } + template + bool none_of(Range&& rng, Pred pred) + { + return std::none_of(rng.begin(), rng.end(), std::move(pred)); + } + template> Range&& sort_unique_erase(Range&& cont, Comp comp = Comp()) { diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index bcb134d444..37102c609f 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -78,9 +78,7 @@ namespace vcpkg struct DependencyOverride { std::string name; - std::string version; - int port_version = 0; - VersionScheme version_scheme = VersionScheme::String; + SchemedVersion version; Json::Object extra_info; diff --git a/locales/messages.json b/locales/messages.json index a5dd100192..a872ccfc29 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -582,6 +582,10 @@ "DependencyGraphCalculation": "Dependency graph submission enabled.", "DependencyGraphFailure": "Dependency graph submission failed.", "DependencyGraphSuccess": "Dependency graph submission successful.", + "DependencyInFeature": "the dependency is in the feature named {feature}.", + "_DependencyInFeature.comment": "An example of {feature} is avisynthplus.", + "DependencyNotInVersionDatabase": "the dependency {package_name} does not exist in the version database; does that port exist?", + "_DependencyNotInVersionDatabase.comment": "An example of {package_name} is zlib.", "DeprecatedPrefabDebugOption": "--prefab-debug is now deprecated.", "DetectCompilerHash": "Detecting compiler hash for triplet {triplet}...", "_DetectCompilerHash.comment": "An example of {triplet} is x64-windows.", @@ -1654,6 +1658,9 @@ "_VersionCommandHeader.comment": "An example of {version} is 1.3.8.", "VersionConflictXML": "Expected {path} version: [{expected_version}], but was [{actual_version}]. Please re-run bootstrap-vcpkg.", "_VersionConflictXML.comment": "An example of {path} is /foo/bar. An example of {expected_version} is 1.3.8. An example of {actual_version} is 1.3.8.", + "VersionConstraintNotInDatabase": "the \"version>=\" constraint to {package_name} names version {version} which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. Consider removing the version constraint or choosing a value declared in {path}.", + "_VersionConstraintNotInDatabase.comment": "An example of {package_name} is zlib. An example of {version} is 1.3.8. An example of {path} is /foo/bar.", + "VersionConstraintOk": "All version constraints are consistent with the version database", "VersionConstraintPortVersionMustBePositiveInteger": "port-version (after the '#') in \"version>=\" must be a non-negative integer", "VersionConstraintUnresolvable": "Cannot resolve a minimum constraint for dependency {package_name} from {spec}.\nThe dependency was not found in the baseline, indicating that the package did not exist at that time. This may be fixed by providing an explicit override version via the \"overrides\" field or by updating the baseline.\nSee `vcpkg help versioning` for more information.", "_VersionConstraintUnresolvable.comment": "An example of {package_name} is zlib. An example of {spec} is zlib:x64-windows.", @@ -1691,6 +1698,10 @@ "_VersionNotFound.comment": "{expected} and {actual} are versions", "VersionNotFoundInVersionsFile2": "{version_spec} was not found in versions database {path}.\nnote: run 'vcpkg x-add-version {package_name}' to add the new port version.", "_VersionNotFoundInVersionsFile2.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {package_name} is zlib. An example of {path} is /foo/bar.", + "VersionOverrideNotInVersionDatabase": "the version override {package_name} does not exist in the version database; does that port exist?", + "_VersionOverrideNotInVersionDatabase.comment": "An example of {package_name} is zlib.", + "VersionOverrideVersionNotInVersionDatabase": "the override of {package_name} names version {version} which does not exist in the version database. Installing this port at the top level will fail as that version will be unresolvable. Consider removing the version override or choosing a value declared in {path}.", + "_VersionOverrideVersionNotInVersionDatabase.comment": "An example of {package_name} is zlib. An example of {version} is 1.3.8. An example of {path} is /foo/bar.", "VersionRejectedDueToBaselineMissing": "{path} was rejected because it uses \"{json_field}\" and does not have a \"builtin-baseline\". This can be fixed by removing the uses of \"{json_field}\" or adding a \"builtin-baseline\".\nSee `vcpkg help versioning` for more information.", "_VersionRejectedDueToBaselineMissing.comment": "An example of {path} is /foo/bar. An example of {json_field} is identifer.", "VersionRejectedDueToFeatureFlagOff": "{path} was rejected because it uses \"{json_field}\" and the `versions` feature flag is disabled. This can be fixed by removing \"{json_field}\" or enabling the `versions` feature flag.\nSee `vcpkg help versioning` for more information.", diff --git a/src/vcpkg-test/dependencies.cpp b/src/vcpkg-test/dependencies.cpp index eef42ad3a7..60ce65adfc 100644 --- a/src/vcpkg-test/dependencies.cpp +++ b/src/vcpkg-test/dependencies.cpp @@ -1554,15 +1554,13 @@ TEST_CASE ("version install overrides", "[versionplan]") bp.v["b"] = {"2", 0}; bp.v["c"] = {"2", 0}; + DependencyOverride bdo{"b", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; + DependencyOverride cdo{"c", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; SECTION ("string") { - auto install_plan = create_versioned_install_plan(vp, - bp, - var_provider, - {Dependency{"c"}}, - {DependencyOverride{"b", "1"}, DependencyOverride{"c", "1"}}, - toplevel_spec()) - .value_or_exit(VCPKG_LINE_INFO); + auto install_plan = + create_versioned_install_plan(vp, bp, var_provider, {Dependency{"c"}}, {bdo, cdo}, toplevel_spec()) + .value_or_exit(VCPKG_LINE_INFO); REQUIRE(install_plan.size() == 1); check_name_and_version(install_plan.install_actions[0], "c", {"1", 0}); @@ -1570,13 +1568,9 @@ TEST_CASE ("version install overrides", "[versionplan]") SECTION ("relaxed") { - auto install_plan = create_versioned_install_plan(vp, - bp, - var_provider, - {Dependency{"b"}}, - {DependencyOverride{"b", "1"}, DependencyOverride{"c", "1"}}, - toplevel_spec()) - .value_or_exit(VCPKG_LINE_INFO); + auto install_plan = + create_versioned_install_plan(vp, bp, var_provider, {Dependency{"b"}}, {bdo, cdo}, toplevel_spec()) + .value_or_exit(VCPKG_LINE_INFO); REQUIRE(install_plan.size() == 1); check_name_and_version(install_plan.install_actions[0], "b", {"1", 0}); @@ -1600,13 +1594,10 @@ TEST_CASE ("version install transitive overrides", "[versionplan]") bp.v["b"] = {"2", 0}; bp.v["c"] = {"2", 1}; + DependencyOverride bdo{"b", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; + DependencyOverride cdo{"c", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; WITH_EXPECTED(install_plan, - create_versioned_install_plan(vp, - bp, - var_provider, - {Dependency{"b"}}, - {DependencyOverride{"b", "1"}, DependencyOverride{"c", "1"}}, - toplevel_spec())); + create_versioned_install_plan(vp, bp, var_provider, {Dependency{"b"}}, {bdo, cdo}, toplevel_spec())); REQUIRE(install_plan.size() == 2); check_name_and_version(install_plan.install_actions[0], "c", {"1", 0}); @@ -2144,36 +2135,37 @@ TEST_CASE ("version overlay ports", "[versionplan]") } SECTION ("constraint+override") { - auto install_plan = - create_versioned_install_plan(vp, - bp, - oprovider, - var_provider, - { - Dependency{"a", {}, {}, {VersionConstraintKind::Minimum, "1", 1}}, - }, - { - DependencyOverride{"a", "2", 0}, - }, - toplevel_spec()) - .value_or_exit(VCPKG_LINE_INFO); + auto install_plan = create_versioned_install_plan( + vp, + bp, + oprovider, + var_provider, + { + Dependency{"a", {}, {}, {VersionConstraintKind::Minimum, "1", 1}}, + }, + { + DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"2", 0}}}, + }, + toplevel_spec()) + .value_or_exit(VCPKG_LINE_INFO); REQUIRE(install_plan.size() == 1); check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0}); } SECTION ("override") { - auto install_plan = create_versioned_install_plan(vp, - bp, - oprovider, - var_provider, - { - Dependency{"a"}, - }, - { - DependencyOverride{"a", "2", 0}, - }, - toplevel_spec()) + auto install_plan = create_versioned_install_plan( + vp, + bp, + oprovider, + var_provider, + { + Dependency{"a"}, + }, + { + DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"2", 0}}}, + }, + toplevel_spec()) .value_or_exit(VCPKG_LINE_INFO); REQUIRE(install_plan.size() == 1); @@ -2204,12 +2196,24 @@ TEST_CASE ("respect supports expression", "[versionplan]") // override from non supported to supported version MockOverlayProvider oprovider; install_plan = create_versioned_install_plan( - vp, bp, oprovider, var_provider, {Dependency{"a"}}, {DependencyOverride{"a", "1", 1}}, toplevel_spec()); + vp, + bp, + oprovider, + var_provider, + {Dependency{"a"}}, + {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 1}}}}, + toplevel_spec()); CHECK(install_plan.has_value()); // override from supported to non supported version bp.v["a"] = {"1", 1}; install_plan = create_versioned_install_plan( - vp, bp, oprovider, var_provider, {Dependency{"a"}}, {DependencyOverride{"a", "1", 0}}, toplevel_spec()); + vp, + bp, + oprovider, + var_provider, + {Dependency{"a"}}, + {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 0}}}}, + toplevel_spec()); CHECK_FALSE(install_plan.has_value()); } } @@ -2241,23 +2245,25 @@ TEST_CASE ("respect supports expressions of features", "[versionplan]") { // override from non supported to supported version MockOverlayProvider oprovider; - install_plan = create_versioned_install_plan(vp, - bp, - oprovider, - var_provider, - {Dependency{"a", {{"x"}}}}, - {DependencyOverride{"a", "1", 1}}, - toplevel_spec()); + install_plan = create_versioned_install_plan( + vp, + bp, + oprovider, + var_provider, + {Dependency{"a", {{"x"}}}}, + {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 1}}}}, + toplevel_spec()); CHECK(install_plan.has_value()); // override from supported to non supported version bp.v["a"] = {"1", 1}; - install_plan = create_versioned_install_plan(vp, - bp, - oprovider, - var_provider, - {Dependency{"a", {{"x"}}}}, - {DependencyOverride{"a", "1", 0}}, - toplevel_spec()); + install_plan = create_versioned_install_plan( + vp, + bp, + oprovider, + var_provider, + {Dependency{"a", {{"x"}}}}, + {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 0}}}}, + toplevel_spec()); CHECK_FALSE(install_plan.has_value()); } } diff --git a/src/vcpkg-test/manifests.cpp b/src/vcpkg-test/manifests.cpp index 4ca7936de3..5b8670746f 100644 --- a/src/vcpkg-test/manifests.cpp +++ b/src/vcpkg-test/manifests.cpp @@ -390,7 +390,8 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).port_version == 1); + CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == + SchemedVersion{VersionScheme::String, Version{"abcd", 1}}); parsed = test_parse_port_manifest(R"json({ "name": "zlib", @@ -403,7 +404,8 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).port_version == 1); + CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == + SchemedVersion{VersionScheme::Date, Version{"2018-01-01", 1}}); parsed = test_parse_port_manifest(R"json({ "name": "zlib", @@ -416,7 +418,8 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).port_version == 1); + CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == + SchemedVersion{VersionScheme::Relaxed, Version{"1.2", 1}}); parsed = test_parse_port_manifest(R"json({ "name": "zlib", @@ -429,7 +432,8 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).port_version == 1); + CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == + SchemedVersion{VersionScheme::Semver, Version{"1.2.0", 1}}); } TEST_CASE ("manifest constraints", "[manifests]") @@ -565,9 +569,7 @@ TEST_CASE ("manifest builtin-baseline", "[manifests]") REQUIRE(pgh.core_paragraph->dependencies[0].constraint.port_version == 1); REQUIRE(pgh.core_paragraph->dependencies[0].constraint.type == VersionConstraintKind::Minimum); REQUIRE(pgh.core_paragraph->overrides.size() == 1); - REQUIRE(pgh.core_paragraph->overrides[0].version_scheme == VersionScheme::String); - REQUIRE(pgh.core_paragraph->overrides[0].version == "abcd"); - REQUIRE(pgh.core_paragraph->overrides[0].port_version == 0); + REQUIRE(pgh.core_paragraph->overrides[0].version == SchemedVersion{VersionScheme::String, Version{"abcd", 0}}); REQUIRE(pgh.core_paragraph->builtin_baseline.value_or("does not have a value") == "089fa4de7dca22c67dcab631f618d5cd0697c8d4"); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); @@ -602,9 +604,7 @@ TEST_CASE ("manifest builtin-baseline", "[manifests]") REQUIRE(pgh.core_paragraph->dependencies[0].constraint.port_version == 1); REQUIRE(pgh.core_paragraph->dependencies[0].constraint.type == VersionConstraintKind::Minimum); REQUIRE(pgh.core_paragraph->overrides.size() == 1); - REQUIRE(pgh.core_paragraph->overrides[0].version_scheme == VersionScheme::String); - REQUIRE(pgh.core_paragraph->overrides[0].version == "abcd"); - REQUIRE(pgh.core_paragraph->overrides[0].port_version == 0); + REQUIRE(pgh.core_paragraph->overrides[0].version == SchemedVersion{VersionScheme::String, Version{"abcd", 0}}); REQUIRE(!pgh.core_paragraph->builtin_baseline.has_value()); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning)); @@ -679,8 +679,8 @@ TEST_CASE ("manifest overrides", "[manifests]") auto& pgh = **m_pgh.get(); REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == std::get<0>(v)); REQUIRE(pgh.core_paragraph->overrides.size() == 1); - REQUIRE(pgh.core_paragraph->overrides[0].version_scheme == std::get<1>(v)); - REQUIRE(pgh.core_paragraph->overrides[0].version == std::get<2>(v)); + REQUIRE(pgh.core_paragraph->overrides[0].version == + SchemedVersion{std::get<1>(v), Version{std::get<2>(v).to_string(), 0}}); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); REQUIRE(pgh.check_against_feature_flags({}, feature_flags_with_versioning)); } @@ -733,9 +733,9 @@ TEST_CASE ("manifest overrides", "[manifests]") REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == raw); REQUIRE(pgh.core_paragraph->overrides.size() == 2); REQUIRE(pgh.core_paragraph->overrides[0].name == "abc"); - REQUIRE(pgh.core_paragraph->overrides[0].port_version == 5); + REQUIRE(pgh.core_paragraph->overrides[0].version == SchemedVersion{VersionScheme::String, Version{"hello", 5}}); REQUIRE(pgh.core_paragraph->overrides[1].name == "abcd"); - REQUIRE(pgh.core_paragraph->overrides[1].port_version == 7); + REQUIRE(pgh.core_paragraph->overrides[1].version == SchemedVersion{VersionScheme::String, Version{"hello", 7}}); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); REQUIRE(pgh.check_against_feature_flags({}, feature_flags_with_versioning)); diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index 8eccea66e4..09ddb9b638 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -317,6 +317,118 @@ namespace } } + bool verify_dependency_and_version_constraint( + const Dependency& dependency, + const std::string* feature_name, + LocalizedString& errors, + const CiVerifyVersionsDbEntry& db, + const std::map>& versions_database) + { + auto dependent_versions = versions_database.find(dependency.name); + if (dependent_versions == versions_database.end()) + { + errors.append_raw(db.scf.source_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgDependencyNotInVersionDatabase, msg::package_name = dependency.name) + .append_raw('\n'); + if (feature_name) + { + errors.append(msgNoteMessage) + .append(msgDependencyInFeature, msg::feature = *feature_name) + .append_raw('\n'); + } + + return false; + } + + auto maybe_minimum_version = dependency.constraint.try_get_minimum_version(); + auto minimum_version = maybe_minimum_version.get(); + if (minimum_version && Util::none_of(dependent_versions->second.entries, [=](const GitVersionDbEntry& entry) { + return entry.version.version == *minimum_version; + })) + { + errors.append_raw(db.scf.source_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionConstraintNotInDatabase, + msg::package_name = dependency.name, + msg::version = *minimum_version, + msg::path = dependent_versions->second.versions_file_path) + .append_raw('\n'); + if (feature_name) + { + errors.append(msgNoteMessage) + .append(msgDependencyInFeature, msg::feature = *feature_name) + .append_raw('\n'); + } + + return false; + } + + return true; + } + + void verify_all_dependencies_and_version_constraints( + LocalizedString& errors, + MessageSink& success_sink, + const CiVerifyVersionsDbEntry& db, + const std::map>& versions_database) + { + bool success = true; + + for (auto&& core_dependency : db.scf.source_control_file->core_paragraph->dependencies) + { + success &= + verify_dependency_and_version_constraint(core_dependency, nullptr, errors, db, versions_database); + } + + for (auto&& feature : db.scf.source_control_file->feature_paragraphs) + { + for (auto&& feature_dependency : feature->dependencies) + { + success &= verify_dependency_and_version_constraint( + feature_dependency, &feature->name, errors, db, versions_database); + } + } + + for (auto&& override_ : db.scf.source_control_file->core_paragraph->overrides) + { + auto override_versions = versions_database.find(override_.name); + if (override_versions == versions_database.end()) + { + success = false; + errors.append_raw(db.scf.source_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionOverrideNotInVersionDatabase, msg::package_name = override_.name) + .append_raw('\n'); + continue; + } + + if (Util::none_of(override_versions->second.entries, [&](const GitVersionDbEntry& entry) { + return entry.version.version == override_.version.version; + })) + { + success = false; + errors.append_raw(db.scf.source_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionOverrideVersionNotInVersionDatabase, + msg::package_name = override_.name, + msg::version = override_.version.version, + msg::path = override_versions->second.versions_file_path) + .append_raw('\n'); + } + } + + if (success) + { + success_sink.println( + LocalizedString::from_raw(db.scf.source_location).append_raw(": ").append(msgVersionConstraintOk)); + } + } + constexpr StringLiteral OPTION_VERBOSE = "verbose"; constexpr StringLiteral OPTION_VERIFY_GIT_TREES = "verify-git-trees"; @@ -429,6 +541,8 @@ namespace vcpkg { verify_all_historical_git_trees(errors, success_sink, paths, port_name, db); } + + verify_all_dependencies_and_version_constraints(errors, success_sink, db, versions_database); } if (!errors.empty()) diff --git a/src/vcpkg/dependencies.cpp b/src/vcpkg/dependencies.cpp index fa7fccd69c..50cc8a9fe9 100644 --- a/src/vcpkg/dependencies.cpp +++ b/src/vcpkg/dependencies.cpp @@ -2007,7 +2007,7 @@ namespace vcpkg provider, bprovider, oprovider, var_provider, options.host_triplet, options.packages_dir); for (auto&& o : overrides) { - vpg.add_override(o.name, {o.version, o.port_version}); + vpg.add_override(o.name, o.version.version); } vpg.solve_with_roots(deps, toplevel); diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 5e21d6a32e..d8254a43bf 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -71,8 +71,6 @@ namespace vcpkg bool operator==(const DependencyOverride& lhs, const DependencyOverride& rhs) { - if (lhs.version_scheme != rhs.version_scheme) return false; - if (lhs.port_version != rhs.port_version) return false; if (lhs.name != rhs.name) return false; if (lhs.version != rhs.version) return false; return lhs.extra_info == rhs.extra_info; @@ -662,16 +660,10 @@ namespace vcpkg Json::Reader& r, const Json::Object& obj, std::string& name, - std::string& version, - VersionScheme& version_scheme, - int& port_version) + SchemedVersion& version) { r.required_object_field(type_name, obj, NAME, name, Json::IdentifierDeserializer::instance); - - auto schemed_version = visit_required_schemed_deserializer(type_name, r, obj, true); - version = schemed_version.version.text(); - version_scheme = schemed_version.scheme; - port_version = schemed_version.version.port_version(); + version = visit_required_schemed_deserializer(type_name, r, obj, true); } virtual Optional visit_object(Json::Reader& r, const Json::Object& obj) const override @@ -686,7 +678,7 @@ namespace vcpkg } } - visit_impl(type_name(), r, obj, dep.name, dep.version, dep.version_scheme, dep.port_version); + visit_impl(type_name(), r, obj, dep.name, dep.version); return dep; } @@ -1718,7 +1710,8 @@ namespace vcpkg dep_obj.insert(DependencyOverrideDeserializer::NAME, Json::Value::string(dep.name)); - serialize_schemed_version(dep_obj, dep.version_scheme, dep.version, dep.port_version); + serialize_schemed_version( + dep_obj, dep.version.scheme, dep.version.version.text(), dep.version.version.port_version()); }; auto serialize_license = From d9dcaae222205a5ec9bb5bf9ccd285c068b9f69d Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 26 Sep 2023 14:28:00 -0700 Subject: [PATCH 06/48] Clarify that source_location is path to CONTROL, not port_directory. --- include/vcpkg/sourceparagraph.h | 3 ++- src/vcpkg/cmakevars.cpp | 2 +- src/vcpkg/commands.add-version.cpp | 6 +++--- src/vcpkg/commands.build.cpp | 14 +++++++------- src/vcpkg/commands.ci-verify-versions.cpp | 18 +++++++++--------- src/vcpkg/commands.format-manifest.cpp | 4 ++-- src/vcpkg/dependencies.cpp | 4 ++-- 7 files changed, 26 insertions(+), 25 deletions(-) diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index 37102c609f..562db285b5 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -204,9 +204,10 @@ namespace vcpkg Version to_version() const { return source_control_file->to_version(); } VersionScheme scheme() const { return source_control_file->core_paragraph->version_scheme; } SchemedVersion schemed_version() const { return {scheme(), to_version()}; } + Path port_directory() const { return control_location.parent_path(); } std::unique_ptr source_control_file; - Path source_location; + Path control_location; }; void print_error_message(View error_info_list); diff --git a/src/vcpkg/cmakevars.cpp b/src/vcpkg/cmakevars.cpp index 5d1c199b5e..cb9250e31a 100644 --- a/src/vcpkg/cmakevars.cpp +++ b/src/vcpkg/cmakevars.cpp @@ -367,7 +367,7 @@ endfunction() for (const auto& install_action : action_plan.install_actions) { auto& scfl = install_action.source_control_file_and_location.value_or_exit(VCPKG_LINE_INFO); - const auto override_path = scfl.source_location / "vcpkg-abi-settings.cmake"; + const auto override_path = scfl.port_directory() / "vcpkg-abi-settings.cmake"; spec_abi_settings.emplace_back(FullPackageSpec{install_action.spec, install_action.feature_list}, override_path.generic_u8string()); } diff --git a/src/vcpkg/commands.add-version.cpp b/src/vcpkg/commands.add-version.cpp index 11f1d20e5a..c2aeb4547b 100644 --- a/src/vcpkg/commands.add-version.cpp +++ b/src/vcpkg/commands.add-version.cpp @@ -413,14 +413,14 @@ namespace vcpkg { // check if manifest file is property formatted - if (Path{scf->source_location}.filename() == "vcpkg.json") + if (scf->control_location.filename() == "vcpkg.json") { - const auto current_file_content = fs.read_contents(scf->source_location, VCPKG_LINE_INFO); + const auto current_file_content = fs.read_contents(scf->control_location, VCPKG_LINE_INFO); const auto json = serialize_manifest(*scf->source_control_file); const auto formatted_content = Json::stringify(json); if (current_file_content != formatted_content) { - auto command_line = fmt::format("vcpkg format-manifest {}", scf->source_location); + auto command_line = fmt::format("vcpkg format-manifest {}", scf->control_location); msg::println_error( msg::format(msgAddVersionPortHasImproperFormat, msg::package_name = port_name) .append_raw('\n') diff --git a/src/vcpkg/commands.build.cpp b/src/vcpkg/commands.build.cpp index 9af5c20830..092a3655e8 100644 --- a/src/vcpkg/commands.build.cpp +++ b/src/vcpkg/commands.build.cpp @@ -759,7 +759,7 @@ namespace vcpkg std::vector variables{ {"ALL_FEATURES", all_features}, - {"CURRENT_PORT_DIR", scfl.source_location}, + {"CURRENT_PORT_DIR", scfl.port_directory()}, {"_HOST_TRIPLET", action.host_triplet.canonical_name()}, {"FEATURES", Strings::join(";", action.feature_list)}, {"PORT", scf.core_paragraph->name}, @@ -950,9 +950,9 @@ namespace vcpkg msg::println(msgLoadingOverlayTriplet, msg::path = triplet_file_path); } - if (!Strings::starts_with(scfl.source_location, paths.builtin_ports_directory())) + if (!Strings::starts_with(scfl.control_location, paths.builtin_ports_directory())) { - msg::println(msgInstallingFromLocation, msg::path = scfl.source_location); + msg::println(msgInstallingFromLocation, msg::path = scfl.control_location); } const ElapsedTimer timer; @@ -1029,7 +1029,7 @@ namespace vcpkg FileSink file_sink{fs, stdoutlog, Append::YES}; CombiningSink combo_sink{stdout_sink, file_sink}; error_count = perform_post_build_lint_checks( - action.spec, paths, pre_build_info, build_info, scfl.source_location, combo_sink); + action.spec, paths, pre_build_info, build_info, scfl.port_directory(), combo_sink); }; if (error_count != 0 && action.build_options.backcompat_features == BackcompatFeatures::PROHIBIT) { @@ -1173,7 +1173,8 @@ namespace vcpkg constexpr int max_port_file_count = 100; std::string portfile_cmake_contents; - auto&& port_dir = action.source_control_file_and_location.value_or_exit(VCPKG_LINE_INFO).source_location; + auto&& scfl = action.source_control_file_and_location.value_or_exit(VCPKG_LINE_INFO); + auto port_dir = scfl.port_directory(); auto raw_files = fs.get_regular_files_recursive_lexically_proximate(port_dir, VCPKG_LINE_INFO); if (raw_files.size() > max_port_file_count) { @@ -1272,8 +1273,7 @@ namespace vcpkg auto abi_file_path = current_build_tree / (triplet_canonical_name + ".vcpkg_abi_info.txt"); fs.write_contents(abi_file_path, full_abi_info, VCPKG_LINE_INFO); - auto& scf = action.source_control_file_and_location.value_or_exit(VCPKG_LINE_INFO).source_control_file; - + auto& scf = scfl.source_control_file; abi_info.package_abi = Hash::get_string_sha256(full_abi_info); abi_info.abi_tag_file.emplace(std::move(abi_file_path)); abi_info.relative_port_files = std::move(files); diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index 09ddb9b638..407a2642fc 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -207,7 +207,7 @@ namespace if (it == versions_end) { success = false; - errors.append_raw(db.scf.source_location) + errors.append_raw(db.scf.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionNotFoundInVersionsFile2, @@ -287,7 +287,7 @@ namespace auto maybe_baseline = baseline.find(port_name); if (maybe_baseline == baseline.end()) { - errors.append_raw(db.scf.source_location) + errors.append_raw(db.scf.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgBaselineMissing, msg::package_name = port_name, msg::version = local_port_version.version) @@ -327,7 +327,7 @@ namespace auto dependent_versions = versions_database.find(dependency.name); if (dependent_versions == versions_database.end()) { - errors.append_raw(db.scf.source_location) + errors.append_raw(db.scf.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgDependencyNotInVersionDatabase, msg::package_name = dependency.name) @@ -348,7 +348,7 @@ namespace return entry.version.version == *minimum_version; })) { - errors.append_raw(db.scf.source_location) + errors.append_raw(db.scf.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionConstraintNotInDatabase, @@ -398,7 +398,7 @@ namespace if (override_versions == versions_database.end()) { success = false; - errors.append_raw(db.scf.source_location) + errors.append_raw(db.scf.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionOverrideNotInVersionDatabase, msg::package_name = override_.name) @@ -411,7 +411,7 @@ namespace })) { success = false; - errors.append_raw(db.scf.source_location) + errors.append_raw(db.scf.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionOverrideVersionNotInVersionDatabase, @@ -425,7 +425,7 @@ namespace if (success) { success_sink.println( - LocalizedString::from_raw(db.scf.source_location).append_raw(": ").append(msgVersionConstraintOk)); + LocalizedString::from_raw(db.scf.control_location).append_raw(": ").append(msgVersionConstraintOk)); } } @@ -498,7 +498,7 @@ namespace vcpkg auto versions_db = maybe_versions_db->get(); if (!versions_db) { - errors.append_raw(loaded_port->source_location) + errors.append_raw(loaded_port->control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionDatabaseFileMissing, @@ -523,7 +523,7 @@ namespace vcpkg auto git_tree_it = port_git_tree_map.find(port_name); if (git_tree_it == port_git_tree_map.end()) { - errors.append_raw(db.scf.source_location) + errors.append_raw(db.scf.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionShaMissing, msg::package_name = port_name, msg::path = db.port_directory) diff --git a/src/vcpkg/commands.format-manifest.cpp b/src/vcpkg/commands.format-manifest.cpp index e74dcddfe3..4a2e7dd05f 100644 --- a/src/vcpkg/commands.format-manifest.cpp +++ b/src/vcpkg/commands.format-manifest.cpp @@ -24,7 +24,7 @@ namespace void open_for_write(const Filesystem& fs, const ToWrite& data) { - const auto& original_path_string = data.scf.source_location.native(); + const auto& original_path_string = data.scf.control_location.native(); const auto& file_to_write_string = data.file_to_write.native(); bool in_place = data.file_to_write == original_path_string; if (in_place) @@ -167,7 +167,7 @@ namespace vcpkg auto maybe_manifest = Paragraphs::try_load_port_required(fs, dir.filename(), dir); if (auto manifest = maybe_manifest.maybe_scfl.get()) { - auto original = manifest->source_location; + auto original = manifest->control_location; to_write.push_back( ToWrite{maybe_manifest.on_disk_contents, std::move(*manifest), std::move(original)}); } diff --git a/src/vcpkg/dependencies.cpp b/src/vcpkg/dependencies.cpp index 50cc8a9fe9..39a99f9cdf 100644 --- a/src/vcpkg/dependencies.cpp +++ b/src/vcpkg/dependencies.cpp @@ -445,9 +445,9 @@ namespace vcpkg if (auto scfl = action.source_control_file_and_location.get()) { if (!builtin_ports_dir.empty() && - !Strings::case_insensitive_ascii_starts_with(scfl->source_location, builtin_ports_dir)) + !Strings::case_insensitive_ascii_starts_with(scfl->control_location, builtin_ports_dir)) { - out.append_raw(" -- ").append_raw(scfl->source_location); + out.append_raw(" -- ").append_raw(scfl->control_location); } } } From 1e9673c3deeb426951ae09f29a49f0dcb8a4d860 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 26 Sep 2023 23:02:41 -0700 Subject: [PATCH 07/48] Fix e2e test failures by also making JSON parse errors print the filename first --- include/vcpkg/base/jsonreader.h | 30 ++++-- include/vcpkg/base/message-data.inc.h | 6 -- include/vcpkg/base/strings.h | 2 +- include/vcpkg/paragraphs.h | 3 + include/vcpkg/sourceparagraph.h | 12 +-- locales/messages.json | 11 --- src/vcpkg-test/configmetadata.cpp | 80 ++++++++-------- src/vcpkg-test/manifests.cpp | 21 +++-- src/vcpkg-test/registries.cpp | 124 +++++++++++++------------ src/vcpkg/base/json.cpp | 88 ++++++++++++++++-- src/vcpkg/commands.add.cpp | 7 +- src/vcpkg/commands.format-manifest.cpp | 2 +- src/vcpkg/commands.install.cpp | 7 +- src/vcpkg/configuration.cpp | 45 ++++----- src/vcpkg/paragraphs.cpp | 33 ++++++- src/vcpkg/registries.cpp | 29 +++--- src/vcpkg/sourceparagraph.cpp | 75 +++++---------- 17 files changed, 318 insertions(+), 257 deletions(-) diff --git a/include/vcpkg/base/jsonreader.h b/include/vcpkg/base/jsonreader.h index 24fda8d19e..98f49b68b9 100644 --- a/include/vcpkg/base/jsonreader.h +++ b/include/vcpkg/base/jsonreader.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -42,29 +43,43 @@ namespace vcpkg::Json IDeserializer& operator=(IDeserializer&&) = default; }; + struct ReaderMessage + { + MessageKind kind; + LocalizedString message; + + ReaderMessage(MessageKind kind, LocalizedString&& message); + ReaderMessage(const ReaderMessage&); + ReaderMessage(ReaderMessage&&); + ReaderMessage& operator=(const ReaderMessage&); + ReaderMessage& operator=(ReaderMessage&&); + }; + + LocalizedString join(const std::vector& messages); + LocalizedString flatten_reader_messages(const std::vector& messages, MessageSink& warningsSink); + struct Reader { - Reader(); + explicit Reader(StringView origin); - const std::vector& errors() const { return m_errors; } + const std::vector& messages() const { return m_messages; } + std::size_t error_count() const { return m_error_count; } void add_missing_field_error(const LocalizedString& type, StringView key, const LocalizedString& key_type); void add_expected_type_error(const LocalizedString& expected_type); void add_extra_field_error(const LocalizedString& type, StringView fields, StringView suggestion = {}); - void add_generic_error(const LocalizedString& type, LocalizedString&& message); + void add_generic_error(const LocalizedString& type, StringView message); void add_warning(LocalizedString type, StringView msg); - const std::vector& warnings() const { return m_warnings; } - std::string path() const noexcept; private: template friend struct IDeserializer; - std::vector m_errors; - std::vector m_warnings; + std::vector m_messages; + std::size_t m_error_count; struct JsonPathElement { constexpr JsonPathElement() = default; @@ -88,6 +103,7 @@ namespace vcpkg::Json std::vector& m_path; }; + StringView m_origin; std::vector m_path; public: diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 211064e952..0c1f0e64f7 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -1227,7 +1227,6 @@ DECLARE_MESSAGE(FailedToDetermineCurrentCommit, (), "", "Failed to determine the DECLARE_MESSAGE(FailedToDownloadFromMirrorSet, (), "", "Failed to download from mirror set") DECLARE_MESSAGE(FailedToExtract, (msg::path), "", "Failed to extract \"{path}\":") DECLARE_MESSAGE(FailedToFetchRepo, (msg::url), "", "Failed to fetch {url}.") -DECLARE_MESSAGE(FailedToFindBaseline, (), "", "Failed to find baseline.json") DECLARE_MESSAGE(FailedToFindPortFeature, (msg::feature, msg::package_name), "", @@ -1258,9 +1257,6 @@ DECLARE_MESSAGE(FailedToParseCMakeConsoleOut, (), "", "Failed to parse CMake console output to locate block start/end markers.") -DECLARE_MESSAGE(FailedToParseBaseline, (msg::path), "", "Failed to parse baseline: {path}") -DECLARE_MESSAGE(FailedToParseConfig, (msg::path), "", "Failed to parse configuration: {path}") -DECLARE_MESSAGE(FailedToParseControl, (msg::path), "", "Failed to parse CONTROL file: {path}") DECLARE_MESSAGE(FailedToParseNoTopLevelObj, (msg::path), "", "Failed to parse {path}, expected a top-level object.") DECLARE_MESSAGE(FailedToParseNoVersionsArray, (msg::path), "", "Failed to parse {path}, expected a 'versions' array.") DECLARE_MESSAGE(FailedToParseSerializedBinParagraph, @@ -1269,7 +1265,6 @@ DECLARE_MESSAGE(FailedToParseSerializedBinParagraph, "[sanity check] Failed to parse a serialized binary paragraph.\nPlease open an issue at " "https://github.com/microsoft/vcpkg, " "with the following output:\n{error_msg}\nSerialized Binary Paragraph:") -DECLARE_MESSAGE(FailedToParseVersionsFile, (msg::path), "", "failed to parse versions file {path}") DECLARE_MESSAGE(FailedToParseVersionXML, (msg::tool_name, msg::version), "", @@ -3150,7 +3145,6 @@ DECLARE_MESSAGE(WarningMessageMustUsePrintWarning, "The message named {value} starts with warning:, it must be changed to prepend " "WarningMessage in code instead.") DECLARE_MESSAGE(WarningsTreatedAsErrors, (), "", "previous warnings being interpreted as errors") -DECLARE_MESSAGE(WarnOnParseConfig, (msg::path), "", "Found the following warnings in configuration {path}:") DECLARE_MESSAGE(WhileCheckingOutBaseline, (msg::commit_sha), "", "while checking out baseline {commit_sha}") DECLARE_MESSAGE(WhileCheckingOutPortTreeIsh, (msg::package_name, msg::commit_sha), diff --git a/include/vcpkg/base/strings.h b/include/vcpkg/base/strings.h index 6e7177f8fd..284f6e480d 100644 --- a/include/vcpkg/base/strings.h +++ b/include/vcpkg/base/strings.h @@ -110,7 +110,7 @@ namespace vcpkg::Strings if (first != last) { Strings::append(output, transformer(*first)); - for (++first; first != last; ++first) + while (++first != last) { output.append(delimiter.data(), delimiter.size()); Strings::append(output, transformer(*first)); diff --git a/include/vcpkg/paragraphs.h b/include/vcpkg/paragraphs.h index 37d03b07ab..aeb288c279 100644 --- a/include/vcpkg/paragraphs.h +++ b/include/vcpkg/paragraphs.h @@ -40,6 +40,9 @@ namespace vcpkg::Paragraphs PortLoadResult try_load_port_required(const ReadOnlyFilesystem& fs, StringView port_name, const Path& port_directory); + ExpectedL try_load_project_manifest_text(StringView text, + StringView origin, + MessageSink& warning_sink); ExpectedL try_load_port_manifest_text(StringView text, StringView origin, MessageSink& warning_sink); diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index 562db285b5..91eb043793 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -155,13 +155,13 @@ namespace vcpkg struct SourceControlFile { SourceControlFile clone() const; - static ParseExpected parse_project_manifest_object(StringView origin, - const Json::Object& object, - MessageSink& warnings_sink); + static ExpectedL> parse_project_manifest_object(StringView origin, + const Json::Object& object, + MessageSink& warnings_sink); - static ParseExpected parse_port_manifest_object(StringView origin, - const Json::Object& object, - MessageSink& warnings_sink); + static ExpectedL> parse_port_manifest_object(StringView origin, + const Json::Object& object, + MessageSink& warnings_sink); static ParseExpected parse_control_file(StringView origin, std::vector&& control_paragraphs); diff --git a/locales/messages.json b/locales/messages.json index a872ccfc29..236faab29f 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -744,7 +744,6 @@ "_FailedToExtract.comment": "An example of {path} is /foo/bar.", "FailedToFetchRepo": "Failed to fetch {url}.", "_FailedToFetchRepo.comment": "An example of {url} is https://github.com/microsoft/vcpkg.", - "FailedToFindBaseline": "Failed to find baseline.json", "FailedToFindPortFeature": "{package_name} has no feature named {feature}.", "_FailedToFindPortFeature.comment": "An example of {feature} is avisynthplus. An example of {package_name} is zlib.", "FailedToFormatMissingFile": "No files to format.\nPlease pass either --all, or the explicit files to format or convert.", @@ -765,13 +764,7 @@ "FailedToObtainPackageVersion": "Cannot find desired package version.", "FailedToOpenAlgorithm": "failed to open {value}", "_FailedToOpenAlgorithm.comment": "{value} is a crypto algorithm like SHA-1 or SHA-512", - "FailedToParseBaseline": "Failed to parse baseline: {path}", - "_FailedToParseBaseline.comment": "An example of {path} is /foo/bar.", "FailedToParseCMakeConsoleOut": "Failed to parse CMake console output to locate block start/end markers.", - "FailedToParseConfig": "Failed to parse configuration: {path}", - "_FailedToParseConfig.comment": "An example of {path} is /foo/bar.", - "FailedToParseControl": "Failed to parse CONTROL file: {path}", - "_FailedToParseControl.comment": "An example of {path} is /foo/bar.", "FailedToParseNoTopLevelObj": "Failed to parse {path}, expected a top-level object.", "_FailedToParseNoTopLevelObj.comment": "An example of {path} is /foo/bar.", "FailedToParseNoVersionsArray": "Failed to parse {path}, expected a 'versions' array.", @@ -780,8 +773,6 @@ "_FailedToParseSerializedBinParagraph.comment": "'{error_msg}' is the error message for failing to parse the Binary Paragraph. An example of {error_msg} is File Not Found.", "FailedToParseVersionXML": "Could not parse version for tool {tool_name}. Version string was: {version}", "_FailedToParseVersionXML.comment": "An example of {tool_name} is aria2. An example of {version} is 1.3.8.", - "FailedToParseVersionsFile": "failed to parse versions file {path}", - "_FailedToParseVersionsFile.comment": "An example of {path} is /foo/bar.", "FailedToProvisionCe": "Failed to provision vcpkg-artifacts.", "FailedToReadParagraph": "Failed to read paragraphs from {path}", "_FailedToReadParagraph.comment": "An example of {path} is /foo/bar.", @@ -1724,8 +1715,6 @@ "WaitingForChildrenToExit": "Waiting for child processes to exit...", "WaitingToTakeFilesystemLock": "waiting to take filesystem lock on {path}...", "_WaitingToTakeFilesystemLock.comment": "An example of {path} is /foo/bar.", - "WarnOnParseConfig": "Found the following warnings in configuration {path}:", - "_WarnOnParseConfig.comment": "An example of {path} is /foo/bar.", "WarningMessage": "warning: ", "_WarningMessage.comment": "This identifies warnings printed on the command line; Visual Studio and other IDEs look for this so it's possible that it should remain unlocalized?", "WarningMessageMustUsePrintWarning": "The message named {value} starts with warning:, it must be changed to prepend WarningMessage in code instead.", diff --git a/src/vcpkg-test/configmetadata.cpp b/src/vcpkg-test/configmetadata.cpp index 4d1adcfab7..ce241aa083 100644 --- a/src/vcpkg-test/configmetadata.cpp +++ b/src/vcpkg-test/configmetadata.cpp @@ -41,9 +41,9 @@ static Configuration parse_test_configuration(StringView text) { auto object = Json::parse_object(text).value_or_exit(VCPKG_LINE_INFO); - Json::Reader reader; + Json::Reader reader{"test"}; auto parsed_config_opt = reader.visit(object, get_configuration_deserializer()); - REQUIRE(reader.errors().empty()); + REQUIRE(reader.messages().empty()); return std::move(parsed_config_opt).value_or_exit(VCPKG_LINE_INFO); } @@ -60,11 +60,11 @@ static void check_errors(const std::string& config_text, const std::string& expe { auto object = Json::parse_object(config_text).value_or_exit(VCPKG_LINE_INFO); - Json::Reader reader; + Json::Reader reader{"test"}; auto parsed_config_opt = reader.visit(object, get_configuration_deserializer()); - REQUIRE(!reader.errors().empty()); + REQUIRE(reader.error_count() != 0); - CHECK_LINES(Strings::join("\n", reader.errors()), expected_errors); + CHECK_LINES(Json::join(reader.messages()).data(), expected_errors); } TEST_CASE ("config registries only", "[ce-metadata]") @@ -154,7 +154,7 @@ TEST_CASE ("config registries only", "[ce-metadata]") } })json"; check_errors(raw_no_baseline, R"( -$.default-registry (a builtin registry): missing required field 'baseline' (a baseline) +test: error: $.default-registry (a builtin registry): missing required field 'baseline' (a baseline) )"); std::string raw_with_packages = R"json({ @@ -165,7 +165,7 @@ TEST_CASE ("config registries only", "[ce-metadata]") } })json"; check_errors(raw_with_packages, R"( -$.default-registry (a registry): unexpected field 'packages', did you mean 'path'? +test: error: $.default-registry (a registry): unexpected field 'packages', did you mean 'path'? )"); std::string raw_default_artifact = R"json({ @@ -176,7 +176,7 @@ TEST_CASE ("config registries only", "[ce-metadata]") } })json"; check_errors(raw_default_artifact, R"( -$ (a configuration object): The default registry cannot be an artifact registry. +test: error: $ (a configuration object): The default registry cannot be an artifact registry. )"); std::string raw_bad_kind = R"json({ "registries": [{ @@ -184,8 +184,8 @@ TEST_CASE ("config registries only", "[ce-metadata]") }] })json"; check_errors(raw_bad_kind, R"( -$.registries[0] (a registry): "kind" did not have an expected value: (expected one of: builtin, filesystem, git, artifact; found custom) -$.registries[0]: mismatched type: expected a registry +test: error: $.registries[0] (a registry): "kind" did not have an expected value: (expected one of: builtin, filesystem, git, artifact; found custom) +test: error: $.registries[0]: mismatched type: expected a registry )"); std::string raw_bad_fs_registry = R"json({ @@ -197,8 +197,8 @@ TEST_CASE ("config registries only", "[ce-metadata]") }] })json"; check_errors(raw_bad_fs_registry, R"( -$.registries[0] (a filesystem registry): unexpected field 'reference', did you mean 'baseline'? -$.registries[0] (a registry): missing required field 'packages' (a package pattern array) +test: error: $.registries[0] (a filesystem registry): unexpected field 'reference', did you mean 'baseline'? +test: error: $.registries[0] (a registry): missing required field 'packages' (a package pattern array) )"); std::string raw_bad_git_registry = R"json({ @@ -211,11 +211,11 @@ TEST_CASE ("config registries only", "[ce-metadata]") }] })json"; check_errors(raw_bad_git_registry, R"( -$.registries[0] (a registry): unexpected field 'no-repository', did you mean 'repository'? -$.registries[0] (a git registry): missing required field 'repository' (a git repository URL) -$.registries[0].reference: mismatched type: expected a git reference (for example, a branch) -$.registries[0] (a git registry): unexpected field 'no-repository', did you mean 'repository'? -$.registries[0].packages: mismatched type: expected a package pattern array +test: error: $.registries[0] (a registry): unexpected field 'no-repository', did you mean 'repository'? +test: error: $.registries[0] (a git registry): missing required field 'repository' (a git repository URL) +test: error: $.registries[0].reference: mismatched type: expected a git reference (for example, a branch) +test: error: $.registries[0] (a git registry): unexpected field 'no-repository', did you mean 'repository'? +test: error: $.registries[0].packages: mismatched type: expected a package pattern array )"); std::string raw_bad_artifact_registry = R"json({ @@ -227,12 +227,12 @@ TEST_CASE ("config registries only", "[ce-metadata]") }] })json"; check_errors(raw_bad_artifact_registry, R"( -$.registries[0] (a registry): unexpected field 'no-location', did you mean 'location'? -$.registries[0] (an artifacts registry): missing required field 'name' (an identifier) -$.registries[0] (an artifacts registry): missing required field 'location' (an artifacts git registry URL) -$.registries[0] (an artifacts registry): unexpected field 'no-location', did you mean 'location'? -$.registries[0] (an artifacts registry): unexpected field 'baseline', did you mean 'kind'? -$.registries[0] (an artifacts registry): unexpected field 'packages', did you mean 'name'? +test: error: $.registries[0] (a registry): unexpected field 'no-location', did you mean 'location'? +test: error: $.registries[0] (an artifacts registry): missing required field 'name' (an identifier) +test: error: $.registries[0] (an artifacts registry): missing required field 'location' (an artifacts git registry URL) +test: error: $.registries[0] (an artifacts registry): unexpected field 'no-location', did you mean 'location'? +test: error: $.registries[0] (an artifacts registry): unexpected field 'baseline', did you mean 'kind'? +test: error: $.registries[0] (an artifacts registry): unexpected field 'packages', did you mean 'name'? )"); } } @@ -320,9 +320,9 @@ TEST_CASE ("metadata strings", "[ce-metadata]") })json"; check_errors(invalid_raw, R"( -$.error: mismatched type: expected a string -$.warning: mismatched type: expected a string -$.message: mismatched type: expected a string +test: error: $.error: mismatched type: expected a string +test: error: $.warning: mismatched type: expected a string +test: error: $.message: mismatched type: expected a string )"); } } @@ -382,12 +382,12 @@ TEST_CASE ("metadata dictionaries", "[ce-metadata]") } })json"; check_errors(invalid_raw, R"( -$ (settings): expected an object -$.requires (a "string": "string" dictionary): value of ["fruits/a/apple"] must be a string -$.requires (a "string": "string" dictionary): value of ["fruits/a/avocado"] must be a string -$.demands (settings): expected an object -$.demands.requires (a "string": "string" dictionary): value of ["fruits/a/apple"] must be a string -$.demands.requires (a "string": "string" dictionary): value of ["fruits/a/avocado"] must be a string +test: error: $ (settings): expected an object +test: error: $.requires (a "string": "string" dictionary): value of ["fruits/a/apple"] must be a string +test: error: $.requires (a "string": "string" dictionary): value of ["fruits/a/avocado"] must be a string +test: error: $.demands (settings): expected an object +test: error: $.demands.requires (a "string": "string" dictionary): value of ["fruits/a/apple"] must be a string +test: error: $.demands.requires (a "string": "string" dictionary): value of ["fruits/a/avocado"] must be a string )"); } } @@ -455,12 +455,12 @@ TEST_CASE ("metadata demands", "[ce-metadata]") } })json"; check_errors(invalid_raw, R"( -$.demands (a demand object): value of ["a"] must be an object -$.demands (a demand object): value of ["b"] must be an object -$.demands (a demand object): value of ["c"] must be an object -$.demands (a demand object): value of ["d"] must be an object -$.demands (a demand object): value of ["e"] must be an object -$.demands (a demand object): ["f"] contains a nested `demands` object (nested `demands` have no effect) +test: error: $.demands (a demand object): value of ["a"] must be an object +test: error: $.demands (a demand object): value of ["b"] must be an object +test: error: $.demands (a demand object): value of ["c"] must be an object +test: error: $.demands (a demand object): value of ["d"] must be an object +test: error: $.demands (a demand object): value of ["e"] must be an object +test: error: $.demands (a demand object): ["f"] contains a nested `demands` object (nested `demands` have no effect) )"); } } @@ -492,7 +492,7 @@ TEST_CASE ("serialize configuration", "[ce-metadata]") ] })json"; check_errors(raw, R"( -$.overlay-ports[2]: mismatched type: expected an overlay path +test: error: $.overlay-ports[2]: mismatched type: expected an overlay path )"); } @@ -516,7 +516,7 @@ TEST_CASE ("serialize configuration", "[ce-metadata]") ] })json"; check_errors(raw, R"( -$.overlay-triplets[0]: mismatched type: expected a triplet path +test: error: $.overlay-triplets[0]: mismatched type: expected a triplet path )"); } diff --git a/src/vcpkg-test/manifests.cpp b/src/vcpkg-test/manifests.cpp index 5b8670746f..1bf6a118a5 100644 --- a/src/vcpkg-test/manifests.cpp +++ b/src/vcpkg-test/manifests.cpp @@ -39,34 +39,35 @@ enum class PrintErrors : bool Yes, }; -static ParseExpected test_parse_project_manifest(const Json::Object& obj, - PrintErrors print = PrintErrors::Yes) +static ExpectedL> test_parse_project_manifest(const Json::Object& obj, + PrintErrors print = PrintErrors::Yes) { auto res = SourceControlFile::parse_project_manifest_object("", obj, null_sink); if (!res.has_value() && print == PrintErrors::Yes) { - print_error_message(LocalizedString::from_raw(res.error()->to_string())); + msg::println(Color::error, res.error()); } return res; } -static ParseExpected test_parse_port_manifest(const Json::Object& obj, - PrintErrors print = PrintErrors::Yes) +static ExpectedL> test_parse_port_manifest(const Json::Object& obj, + PrintErrors print = PrintErrors::Yes) { auto res = SourceControlFile::parse_port_manifest_object("", obj, null_sink); if (!res.has_value() && print == PrintErrors::Yes) { - print_error_message(LocalizedString::from_raw(res.error()->to_string())); + msg::println(Color::error, res.error()); } return res; } -static ParseExpected test_parse_project_manifest(StringView obj, - PrintErrors print = PrintErrors::Yes) +static ExpectedL> test_parse_project_manifest(StringView obj, + PrintErrors print = PrintErrors::Yes) { return test_parse_project_manifest(parse_json_object(obj), print); } -static ParseExpected test_parse_port_manifest(StringView obj, PrintErrors print = PrintErrors::Yes) +static ExpectedL> test_parse_port_manifest(StringView obj, + PrintErrors print = PrintErrors::Yes) { return test_parse_port_manifest(parse_json_object(obj), print); } @@ -886,7 +887,7 @@ TEST_CASE ("manifest construct maximum", "[manifests]") auto res = SourceControlFile::parse_port_manifest_object("", object, null_sink); if (!res.has_value()) { - print_error_message(LocalizedString::from_raw(res.error()->to_string())); + msg::println(Color::error, res.error()); } REQUIRE(res.has_value()); REQUIRE(*res.get() != nullptr); diff --git a/src/vcpkg-test/registries.cpp b/src/vcpkg-test/registries.cpp index 4ebc212e7c..5f78c8d5f0 100644 --- a/src/vcpkg-test/registries.cpp +++ b/src/vcpkg-test/registries.cpp @@ -269,17 +269,17 @@ static vcpkg::Optional visit_default_registry(Json::Reader& r, Js TEST_CASE ("registry_parsing", "[registries]") { { - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( { "kind": "builtin" } )json"); visit_default_registry(r, std::move(test_json)); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } { - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( { "kind": "builtin", @@ -288,10 +288,10 @@ TEST_CASE ("registry_parsing", "[registries]") )json"); visit_default_registry(r, std::move(test_json)); // Non-SHA strings are allowed and will be diagnosed later - CHECK(r.errors().empty()); + CHECK(r.error_count() == 0); } { - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( { "kind": "builtin", @@ -300,10 +300,10 @@ TEST_CASE ("registry_parsing", "[registries]") )json"); auto registry_impl = visit_default_registry(r, std::move(test_json)); REQUIRE(registry_impl); - CHECK(r.errors().empty()); + CHECK(r.error_count() == 0); } { - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( { "kind": "builtin", @@ -312,10 +312,10 @@ TEST_CASE ("registry_parsing", "[registries]") } )json"); visit_default_registry(r, std::move(test_json)); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } { - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( { "kind": "filesystem", @@ -324,7 +324,7 @@ TEST_CASE ("registry_parsing", "[registries]") )json"); auto registry_impl = visit_default_registry(r, std::move(test_json)); REQUIRE(registry_impl); - CHECK(r.errors().empty()); + CHECK(r.error_count() == 0); test_json = parse_json(R"json( { @@ -334,7 +334,7 @@ TEST_CASE ("registry_parsing", "[registries]") )json"); registry_impl = visit_default_registry(r, std::move(test_json)); REQUIRE(registry_impl); - CHECK(r.errors().empty()); + CHECK(r.error_count() == 0); } auto test_json = parse_json(R"json( @@ -343,9 +343,9 @@ TEST_CASE ("registry_parsing", "[registries]") } )json"); { - Json::Reader r; + Json::Reader r{"test"}; visit_default_registry(r, std::move(test_json)); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } test_json = parse_json(R"json( { @@ -354,9 +354,9 @@ TEST_CASE ("registry_parsing", "[registries]") } )json"); { - Json::Reader r; + Json::Reader r{"test"}; visit_default_registry(r, std::move(test_json)); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } test_json = parse_json(R"json( @@ -366,9 +366,9 @@ TEST_CASE ("registry_parsing", "[registries]") } )json"); { - Json::Reader r; + Json::Reader r{"test"}; visit_default_registry(r, std::move(test_json)); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } test_json = parse_json(R"json( @@ -380,11 +380,11 @@ TEST_CASE ("registry_parsing", "[registries]") } )json"); { - Json::Reader r; + Json::Reader r{"test"}; auto registry_impl = visit_default_registry(r, std::move(test_json)); REQUIRE(registry_impl); - INFO(Strings::join("\n", r.errors())); - CHECK(r.errors().empty()); + INFO(Json::join(r.messages()).data()); + CHECK(r.error_count() == 0); } test_json = parse_json(R"json( @@ -394,11 +394,11 @@ TEST_CASE ("registry_parsing", "[registries]") "baseline": "123" } )json"); - Json::Reader r; + Json::Reader r{"test"}; auto registry_impl = visit_default_registry(r, std::move(test_json)); REQUIRE(registry_impl); - INFO(Strings::join("\n", r.errors())); - CHECK(r.errors().empty()); + INFO(Json::join(r.messages()).data()); + CHECK(r.error_count() == 0); } TEST_CASE ("registries report pattern errors", "[registries]") @@ -414,21 +414,23 @@ TEST_CASE ("registries report pattern errors", "[registries]") ] })json"); - Json::Reader r; + Json::Reader r{"test"}; auto maybe_conf = r.visit(test_json, get_configuration_deserializer()); - const auto& errors = r.errors(); - CHECK(!errors.empty()); - REQUIRE(errors.size() == 3); - CHECK(errors[0] == - "$.registries[0].packages[1] (a package pattern): \"\" is not a valid package pattern. Package patterns must " + const auto& messages = r.messages(); + REQUIRE(messages.size() == 3); + CHECK(messages[0].message == + "test: error: $.registries[0].packages[1] (a package pattern): \"\" is not a valid package pattern. Package " + "patterns must " "use only one wildcard character (*) and it must be the last character in the pattern (see " "https://learn.microsoft.com/vcpkg/users/registries for more information)"); - CHECK(errors[1] == - "$.registries[0].packages[2] (a package pattern): \"a*a\" is not a valid package pattern. Package patterns " + CHECK(messages[1].message == + "test: error: $.registries[0].packages[2] (a package pattern): \"a*a\" is not a valid package pattern. " + "Package patterns " "must use only one wildcard character (*) and it must be the last character in the pattern (see " "https://learn.microsoft.com/vcpkg/users/registries for more information)"); - CHECK(errors[2] == - "$.registries[0].packages[3] (a package pattern): \"*a\" is not a valid package pattern. Package patterns " + CHECK(messages[2].message == + "test: error: $.registries[0].packages[3] (a package pattern): \"*a\" is not a valid package pattern. " + "Package patterns " "must use only one wildcard character (*) and it must be the last character in the pattern (see " "https://learn.microsoft.com/vcpkg/users/registries for more information)"); } @@ -458,7 +460,7 @@ TEST_CASE ("registries ignored patterns warning", "[registries]") ] })json"); - Json::Reader r; + Json::Reader r{"test"}; auto maybe_conf = r.visit(test_json, get_configuration_deserializer()); auto conf = maybe_conf.get(); @@ -499,9 +501,9 @@ TEST_CASE ("registries ignored patterns warning", "[registries]") CHECK((*pkgs)[1] == "bei*"); CHECK((*pkgs)[2] == "zlib"); - const auto& warnings = r.warnings(); - REQUIRE(warnings.size() == 3); - CHECK(warnings[0] == R"($ (a configuration object): warning: Package "*" is duplicated. + const auto& messages = r.messages(); + REQUIRE(messages.size() == 3); + CHECK(messages[0].message == R"(test: warning: $ (a configuration object): Package "*" is duplicated. First declared in: location: $.registries[0].packages[0] registry: https://github.com/Microsoft/vcpkg @@ -510,7 +512,7 @@ TEST_CASE ("registries ignored patterns warning", "[registries]") location: $.registries[2].packages[0] registry: https://github.com/another-remote/another-vcpkg-registry )"); - CHECK(warnings[1] == R"($ (a configuration object): warning: Package "bei*" is duplicated. + CHECK(messages[1].message == R"(test: warning: $ (a configuration object): Package "bei*" is duplicated. First declared in: location: $.registries[1].packages[0] registry: https://github.com/northwindtraders/vcpkg-registry @@ -519,7 +521,7 @@ TEST_CASE ("registries ignored patterns warning", "[registries]") location: $.registries[2].packages[1] registry: https://github.com/another-remote/another-vcpkg-registry )"); - CHECK(warnings[2] == R"($ (a configuration object): warning: Package "zlib" is duplicated. + CHECK(messages[2].message == R"(test: warning: $ (a configuration object): Package "zlib" is duplicated. First declared in: location: $.registries[0].packages[2] registry: https://github.com/Microsoft/vcpkg @@ -536,7 +538,7 @@ TEST_CASE ("registries ignored patterns warning", "[registries]") TEST_CASE ("git_version_db_parsing", "[registries]") { auto filesystem_version_db = make_git_version_db_deserializer(); - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( [ { @@ -565,7 +567,7 @@ TEST_CASE ("git_version_db_parsing", "[registries]") CHECK(results[1].git_tree == "12b84a31469a78dd4b42dcf58a27d4600f6b2d48"); CHECK(results[2].version == SchemedVersion{VersionScheme::String, Version{"2020-04-12", 0}}); CHECK(results[2].git_tree == "bd4565e8ab55bc5e098a1750fa5ff0bc4406ca9b"); - CHECK(r.errors().empty()); + CHECK(r.error_count() == 0); } TEST_CASE ("filesystem_version_db_parsing", "[registries]") @@ -573,7 +575,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") auto filesystem_version_db = make_filesystem_version_db_deserializer("a/b"); { - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( [ { @@ -601,11 +603,11 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") CHECK(results[1].p == "a/b" VCPKG_PREFERRED_SEPARATOR "e/d"); CHECK(results[2].version == SchemedVersion{VersionScheme::Semver, {"1.2.3", 0}}); CHECK(results[2].p == "a/b" VCPKG_PREFERRED_SEPARATOR "semvers/here"); - CHECK(r.errors().empty()); + CHECK(r.error_count() == 0); } { // missing $/ - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( [ { @@ -616,11 +618,11 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } { // uses backslash - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( [ { @@ -631,11 +633,11 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } { // doubled slash - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( [ { @@ -646,11 +648,11 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } { // dot path (first) - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( [ { @@ -661,11 +663,11 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } { // dot path (mid) - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( [ { @@ -676,11 +678,11 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } { // dot path (last) - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( [ { @@ -691,11 +693,11 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } { // dot dot path (first) - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( [ { @@ -706,11 +708,11 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } { // dot dot path (mid) - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( [ { @@ -721,11 +723,11 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } { // dot dot path (last) - Json::Reader r; + Json::Reader r{"test"}; auto test_json = parse_json(R"json( [ { @@ -736,7 +738,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(!r.errors().empty()); + CHECK(r.error_count() != 0); } } diff --git a/src/vcpkg/base/json.cpp b/src/vcpkg/base/json.cpp index 3020f365ce..cbfed1506c 100644 --- a/src/vcpkg/base/json.cpp +++ b/src/vcpkg/base/json.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -1383,9 +1384,62 @@ namespace vcpkg::Json return res; } + ReaderMessage::ReaderMessage(MessageKind kind, LocalizedString&& message) : kind(kind), message(std::move(message)) + { + } + + ReaderMessage::ReaderMessage(const ReaderMessage&) = default; + ReaderMessage::ReaderMessage(ReaderMessage&&) = default; + ReaderMessage& ReaderMessage::operator=(const ReaderMessage&) = default; + ReaderMessage& ReaderMessage::operator=(ReaderMessage&&) = default; + + LocalizedString join(const std::vector& messages) + { + LocalizedString result; + auto first = messages.begin(); + const auto last = messages.end(); + if (first != last) + { + result.append(first->message); + while (++first != last) + { + result.append_raw('\n').append(first->message); + } + } + + return result; + } + + LocalizedString flatten_reader_messages(const std::vector& messages, MessageSink& warningsSink) + { + LocalizedString flat_errors; + for (auto&& message : messages) + { + switch (message.kind) + { + case MessageKind::Warning: warningsSink.println(Color::warning, message.message); break; + case MessageKind::Error: + if (!flat_errors.empty()) + { + flat_errors.append_raw('\n'); + } + + flat_errors.append(message.message); + + break; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + + return flat_errors; + } + static std::atomic g_json_reader_stats(0); - Reader::Reader() : m_stat_timer(g_json_reader_stats) { } + Reader::Reader(StringView origin) + : m_messages(), m_error_count(0), m_origin(origin), m_path(), m_stat_timer(g_json_reader_stats) + { + } uint64_t Reader::get_reader_stats() { return g_json_reader_stats.load(); } @@ -1395,7 +1449,13 @@ namespace vcpkg::Json } void Reader::add_expected_type_error(const LocalizedString& expected_type) { - m_errors.push_back(msg::format(msgMismatchedType, msg::json_field = path(), msg::json_type = expected_type)); + ++m_error_count; + m_messages.emplace_back( + MessageKind::Error, + LocalizedString::from_raw(m_origin) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgMismatchedType, msg::json_field = path(), msg::json_type = expected_type)); } void Reader::add_extra_field_error(const LocalizedString& type, StringView field, StringView suggestion) { @@ -1409,9 +1469,18 @@ namespace vcpkg::Json add_generic_error(type, msg::format(msgUnexpectedField, msg::json_field = field)); } } - void Reader::add_generic_error(const LocalizedString& type, LocalizedString&& message) + void Reader::add_generic_error(const LocalizedString& type, StringView message) { - m_errors.push_back(LocalizedString::from_raw(Strings::concat(path(), " (", type, "): ", message))); + ++m_error_count; + m_messages.emplace_back(MessageKind::Error, + LocalizedString::from_raw(m_origin) + .append_raw(": ") + .append(msgErrorMessage) + .append_raw(path()) + .append_raw(" (") + .append(type) + .append_raw("): ") + .append_raw(message)); } void Reader::check_for_unexpected_fields(const Object& obj, @@ -1443,8 +1512,15 @@ namespace vcpkg::Json void Reader::add_warning(LocalizedString type, StringView msg) { - m_warnings.push_back(std::move( - LocalizedString::from_raw(path()).append_raw(" (").append(type).append_raw("): ").append_raw(msg))); + m_messages.emplace_back(MessageKind::Warning, + LocalizedString::from_raw(m_origin) + .append_raw(": ") + .append(msgWarningMessage) + .append_raw(path()) + .append_raw(" (") + .append(type) + .append_raw("): ") + .append_raw(msg)); } std::string Reader::path() const noexcept diff --git a/src/vcpkg/commands.add.cpp b/src/vcpkg/commands.add.cpp index 34c413d92e..4d27585755 100644 --- a/src/vcpkg/commands.add.cpp +++ b/src/vcpkg/commands.add.cpp @@ -99,8 +99,11 @@ namespace vcpkg auto pmanifest_scf = maybe_manifest_scf.get(); if (!pmanifest_scf) { - print_error_message(LocalizedString::from_raw(maybe_manifest_scf.error()->to_string())); - msg::println(Color::error, msg::msgSeeURL, msg::url = docs::manifests_url); + msg::println(Color::error, + std::move(maybe_manifest_scf) + .error() + .append_raw('\n') + .append(msg::msgSeeURL, msg::url = docs::manifests_url)); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/commands.format-manifest.cpp b/src/vcpkg/commands.format-manifest.cpp index 4a2e7dd05f..31de5e6361 100644 --- a/src/vcpkg/commands.format-manifest.cpp +++ b/src/vcpkg/commands.format-manifest.cpp @@ -147,7 +147,7 @@ namespace vcpkg else { auto maybe_manifest = - Paragraphs::try_load_port_manifest_text(contents->content, contents->origin, stdout_sink); + Paragraphs::try_load_project_manifest_text(contents->content, contents->origin, stdout_sink); if (auto manifest = maybe_manifest.get()) { to_write.push_back(ToWrite{contents->content, std::move(*manifest), path}); diff --git a/src/vcpkg/commands.install.cpp b/src/vcpkg/commands.install.cpp index 5755636079..d21bb417b3 100644 --- a/src/vcpkg/commands.install.cpp +++ b/src/vcpkg/commands.install.cpp @@ -1104,8 +1104,11 @@ namespace vcpkg SourceControlFile::parse_project_manifest_object(manifest->path, manifest->manifest, stdout_sink); if (!maybe_manifest_scf) { - print_error_message(LocalizedString::from_raw(maybe_manifest_scf.error()->to_string())); - msg::println(msgExtendedDocumentationAtUrl, msg::url = docs::manifests_url); + msg::println(Color::error, + std::move(maybe_manifest_scf) + .error() + .append_raw('\n') + .append(msgExtendedDocumentationAtUrl, msg::url = docs::manifests_url)); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/configuration.cpp b/src/vcpkg/configuration.cpp index b81a948c7a..113b58a607 100644 --- a/src/vcpkg/configuration.cpp +++ b/src/vcpkg/configuration.cpp @@ -431,10 +431,10 @@ namespace { auto extract_string = [&](const Json::Object& obj, StringView key, Json::Object& put_into) { std::string value; - const auto errors_count = r.errors(); + const auto errors_count = r.error_count(); if (r.optional_object_field(obj, key, value, Json::UntypedStringDeserializer::instance)) { - if (errors_count != r.errors()) return; + if (errors_count != r.error_count()) return; put_into.insert_or_replace(key, std::move(value)); } }; @@ -453,10 +453,10 @@ namespace }; auto extract_dictionary = [&](const Json::Object& obj, StringView key, Json::Object& put_into) { Json::Object value; - const auto errors_count = r.errors(); + const auto errors_count = r.error_count(); if (r.optional_object_field(obj, key, value, DictionaryDeserializer::instance)) { - if (errors_count != r.errors()) return; + if (errors_count != r.error_count()) return; put_into.insert_or_replace(key, value); } }; @@ -560,7 +560,7 @@ namespace { auto first = locations.begin(); const auto last = locations.end(); - auto warning = msg::format_warning(msgDuplicatePackagePattern, msg::package_name = pattern) + auto warning = msg::format(msgDuplicatePackagePattern, msg::package_name = pattern) .append_raw('\n') .append_indent() .append(msgDuplicatePackagePatternFirstOcurrence) @@ -901,34 +901,25 @@ namespace vcpkg Optional parse_configuration(const Json::Object& obj, StringView origin, MessageSink& messageSink) { - Json::Reader reader; + Json::Reader reader{origin}; auto maybe_configuration = reader.visit(obj, get_configuration_deserializer()); - bool has_warnings = !reader.warnings().empty(); - bool has_errors = !reader.errors().empty(); - if (has_warnings || has_errors) + bool has_messages = !reader.messages().empty(); + if (has_messages) { - if (has_errors) + for (auto&& msg : reader.messages()) { - messageSink.println(Color::error, msgFailedToParseConfig, msg::path = origin); - } - else - { - messageSink.println(Color::warning, msgWarnOnParseConfig, msg::path = origin); - } - - for (auto&& msg : reader.errors()) - { - messageSink.println(Color::error, LocalizedString().append_indent().append_raw(msg)); - } + Color c; + switch (msg.kind) + { + case MessageKind::Error: c = Color::error; break; + case MessageKind::Warning: c = Color::warning; break; + default: Checks::unreachable(VCPKG_LINE_INFO); break; + } - for (auto&& msg : reader.warnings()) - { - messageSink.println(Color::warning, LocalizedString().append_indent().append(msg)); + messageSink.println(c, msg.message); } - msg::println(msgExtendedDocumentationAtUrl, msg::url = docs::registries_url); - - if (has_errors) return nullopt; + if (reader.error_count() != 0) return nullopt; } return maybe_configuration; } diff --git a/src/vcpkg/paragraphs.cpp b/src/vcpkg/paragraphs.cpp index 453e617aca..7053b7f8c3 100644 --- a/src/vcpkg/paragraphs.cpp +++ b/src/vcpkg/paragraphs.cpp @@ -15,6 +15,8 @@ #include +using namespace vcpkg; + static std::atomic g_load_ports_stats(0); namespace vcpkg @@ -400,17 +402,21 @@ namespace vcpkg::Paragraphs return fs.exists(maybe_directory / "CONTROL", IgnoreErrors{}) || fs.exists(maybe_directory / "vcpkg.json", IgnoreErrors{}); } +} // namespace vcpkg::Paragraphs - ExpectedL try_load_port_manifest_text(StringView text, - StringView origin, - MessageSink& warning_sink) +namespace +{ + ExpectedL try_load_any_manifest_text( + StringView text, + StringView origin, + MessageSink& warning_sink, + ExpectedL> (*do_parse)(StringView, const Json::Object&, MessageSink&)) { StatsTimer timer(g_load_ports_stats); auto maybe_object = Json::parse_object(text, origin); if (auto object = maybe_object.get()) { - auto maybe_parsed = map_parse_expected_to_localized_string( - SourceControlFile::parse_port_manifest_object(origin, *object, warning_sink)); + auto maybe_parsed = do_parse(origin, *object, warning_sink); if (auto parsed = maybe_parsed.get()) { return SourceControlFileAndLocation{std::move(*parsed), origin.to_string()}; @@ -421,6 +427,23 @@ namespace vcpkg::Paragraphs return std::move(maybe_object).error(); } +} + +namespace vcpkg::Paragraphs +{ + ExpectedL try_load_project_manifest_text(StringView text, + StringView origin, + MessageSink& warning_sink) + { + return try_load_any_manifest_text(text, origin, warning_sink, SourceControlFile::parse_project_manifest_object); + } + + ExpectedL try_load_port_manifest_text(StringView text, + StringView origin, + MessageSink& warning_sink) + { + return try_load_any_manifest_text(text, origin, warning_sink, SourceControlFile::parse_port_manifest_object); + } ExpectedL try_load_control_file_text(StringView text, StringView origin) { diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index 6857ee8d3f..f5af13a819 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -1322,19 +1322,15 @@ namespace return {nullopt, expected_left_tag}; } - Json::Reader r; + Json::Reader r{origin}; std::map> result; r.visit_in_key(*baseline_value, real_baseline, result, BaselineDeserializer::instance); - if (r.errors().empty()) + if (r.error_count() == 0) { - return {std::move(result), expected_left_tag}; - } - else - { - return msg::format_error(msgFailedToParseBaseline, msg::path = origin) - .append_raw('\n') - .append_raw(Strings::join("\n", r.errors())); + return Optional{std::move(result)}; } + + return join(r.messages()); } ExpectedL> load_baseline_versions(const ReadOnlyFilesystem& fs, @@ -1347,7 +1343,6 @@ namespace { if (ec == std::errc::no_such_file_or_directory) { - msg::println(msgFailedToFindBaseline); return {nullopt, expected_left_tag}; } @@ -1623,12 +1618,11 @@ namespace std::vector db_entries; GitVersionDbEntryArrayDeserializer deserializer{}; - Json::Reader r; + Json::Reader r{versions_file_path}; r.visit_in_key(*maybe_versions_array, "versions", db_entries, deserializer); - if (!r.errors().empty()) + if (r.error_count() != 0) { - return msg::format_error(msgFailedToParseVersionsFile, msg::path = versions_file_path) - .append_raw(Strings::join("\n", r.errors())); + return join(r.messages()); } return db_entries; @@ -1664,12 +1658,11 @@ namespace std::vector db_entries; FilesystemVersionDbEntryArrayDeserializer deserializer{registry_root}; - Json::Reader r; + Json::Reader r{versions_file_path}; r.visit_in_key(*maybe_versions_array, "versions", db_entries, deserializer); - if (!r.errors().empty()) + if (r.error_count() != 0) { - return msg::format_error(msgFailedToParseVersionsFile, msg::path = versions_file_path) - .append_raw(Strings::join("\n", r.errors())); + return join(r.messages()); } return db_entries; diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index d8254a43bf..fc58ee0660 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -1299,37 +1299,16 @@ namespace vcpkg StringView origin, MessageSink& warningsSink) { - Json::Reader reader; + Json::Reader reader{origin}; auto res = reader.visit(manifest, ManifestConfigurationDeserializer::instance); - if (!reader.warnings().empty()) + LocalizedString flat_errors = flatten_reader_messages(reader.messages(), warningsSink); + if (flat_errors.empty()) { - warningsSink.println(Color::warning, msgWarnOnParseConfig, msg::path = origin); - for (auto&& warning : reader.warnings()) - { - warningsSink.println(Color::warning, LocalizedString::from_raw(warning)); - } - warningsSink.println(Color::warning, msgExtendedDocumentationAtUrl, msg::url = docs::registries_url); - warningsSink.println(Color::warning, msgExtendedDocumentationAtUrl, msg::url = docs::manifests_url); - } - - if (!reader.errors().empty()) - { - LocalizedString ret; - ret.append(msgFailedToParseConfig, msg::path = origin); - ret.append_raw('\n'); - for (auto&& err : reader.errors()) - { - ret.append_indent().append(err).append_raw("\n"); - } - ret.append(msgExtendedDocumentationAtUrl, msg::url = docs::registries_url); - ret.append_raw('\n'); - ret.append(msgExtendedDocumentationAtUrl, msg::url = docs::manifests_url); - ret.append_raw('\n'); - return std::move(ret); + return std::move(res).value_or_exit(VCPKG_LINE_INFO); } - return std::move(res).value_or_exit(VCPKG_LINE_INFO); + return flat_errors; } SourceControlFile SourceControlFile::clone() const @@ -1344,46 +1323,34 @@ namespace vcpkg } template - static ParseExpected parse_manifest_object_impl(StringView origin, - const Json::Object& manifest, - MessageSink& warnings_sink) + static ExpectedL> parse_manifest_object_impl(StringView origin, + const Json::Object& manifest, + MessageSink& warnings_sink) { - Json::Reader reader; - + Json::Reader reader{origin}; auto res = reader.visit(manifest, ManifestDeserializerType::instance); - - for (auto&& w : reader.warnings()) + LocalizedString flat_errors = flatten_reader_messages(reader.messages(), warnings_sink); + if (flat_errors.empty()) { - warnings_sink.print(Color::warning, LocalizedString::from_raw(Strings::concat(origin, ": ", w, '\n'))); - } + if (auto p = res.get()) + { + return std::move(*p); + } - if (!reader.errors().empty()) - { - auto err = std::make_unique(); - err->name = origin.to_string(); - err->other_errors = std::move(reader.errors()); - return err; - } - else if (auto p = res.get()) - { - return std::move(*p); - } - else - { Checks::unreachable(VCPKG_LINE_INFO); } + + return flat_errors; } - ParseExpected SourceControlFile::parse_project_manifest_object(StringView origin, - const Json::Object& manifest, - MessageSink& warnings_sink) + ExpectedL> SourceControlFile::parse_project_manifest_object( + StringView origin, const Json::Object& manifest, MessageSink& warnings_sink) { return parse_manifest_object_impl(origin, manifest, warnings_sink); } - ParseExpected SourceControlFile::parse_port_manifest_object(StringView origin, - const Json::Object& manifest, - MessageSink& warnings_sink) + ExpectedL> SourceControlFile::parse_port_manifest_object( + StringView origin, const Json::Object& manifest, MessageSink& warnings_sink) { return parse_manifest_object_impl(origin, manifest, warnings_sink); } From 40bdcebeffb319f7b6391ccf1c43171a62fe1b78 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 27 Sep 2023 00:46:57 -0700 Subject: [PATCH 08/48] Fix output claiming that a port isn't in the versions database when it is really that the local port is toast or vice versa. Make validating git trees of removed-from-baseline ports possible. --- include/vcpkg/base/message-data.inc.h | 5 - include/vcpkg/registries.h | 35 ++- locales/messages.json | 3 - src/vcpkg/commands.ci-verify-versions.cpp | 248 ++++++++++++---------- src/vcpkg/registries.cpp | 77 +++++++ 5 files changed, 237 insertions(+), 131 deletions(-) diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 0c1f0e64f7..e983c5c03e 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -1247,7 +1247,6 @@ DECLARE_MESSAGE(FailedToLoadPortFrom, (msg::path), "", "Failed to load port from DECLARE_MESSAGE(FailedToLoadUnnamedPortFromPath, (msg::path), "", "Failed to load port from {path}") DECLARE_MESSAGE(FailedToLocateSpec, (msg::spec), "", "Failed to locate spec in graph: {spec}") DECLARE_MESSAGE(FailedToObtainDependencyVersion, (), "", "Cannot find desired dependency version.") -DECLARE_MESSAGE(FailedToObtainLocalPortGitSha, (), "", "Failed to obtain git SHAs for local ports.") DECLARE_MESSAGE(FailedToObtainPackageVersion, (), "", "Cannot find desired package version.") DECLARE_MESSAGE(FailedToOpenAlgorithm, (msg::value), @@ -2622,10 +2621,6 @@ DECLARE_MESSAGE(StoredBinariesToDestinations, DECLARE_MESSAGE(StoreOptionMissingSha, (), "", "--store option is invalid without a sha512") DECLARE_MESSAGE(SuccessfulyExported, (msg::package_name, msg::path), "", "Exported {package_name} to {path}") DECLARE_MESSAGE(SuggestGitPull, (), "", "The result may be outdated. Run `git pull` to get the latest results.") -DECLARE_MESSAGE(SuggestResolution, - (msg::command_name, msg::option), - "", - "To attempt to resolve all errors at once, run:\nvcpkg {command_name} --{option}") DECLARE_MESSAGE(SuggestStartingBashShell, (), "", diff --git a/include/vcpkg/registries.h b/include/vcpkg/registries.h index f618a5840a..edba2d39c9 100644 --- a/include/vcpkg/registries.h +++ b/include/vcpkg/registries.h @@ -18,7 +18,6 @@ #include #include #include -#include #include namespace vcpkg @@ -177,20 +176,46 @@ namespace vcpkg struct GitVersionsLoadResult { + // If the versions database file does not exist, a disengaged Optional + // Otherwise, if a file I/O error occurred or the file is malformed, that error + // Otherwise, the loaded version database records ExpectedL>> entries; Path versions_file_path; }; + GitVersionsLoadResult load_git_versions_file(const ReadOnlyFilesystem& fs, + const Path& registry_versions, + StringView port_name); + + struct FullGitVersionsDatabase + { + explicit FullGitVersionsDatabase(const ReadOnlyFilesystem& fs, + const Path& registry_versions, + std::map>&& initial); + FullGitVersionsDatabase(const FullGitVersionsDatabase&); + FullGitVersionsDatabase(FullGitVersionsDatabase&&); + FullGitVersionsDatabase& operator=(const FullGitVersionsDatabase&); + FullGitVersionsDatabase& operator=(FullGitVersionsDatabase&&); + + const GitVersionsLoadResult& lookup(StringView port_name); + const std::map>& cache() const; + + private: + const ReadOnlyFilesystem* m_fs; + Path m_registry_versions; + std::map> m_cache; + }; + + // The outer expected only contains directory enumeration errors; individual parse errors are within + ExpectedL load_all_git_versions_files(const ReadOnlyFilesystem& fs, + const Path& registry_versions); + struct FilesystemVersionDbEntry { SchemedVersion version; Path p; }; - GitVersionsLoadResult load_git_versions_file(const ReadOnlyFilesystem& fs, - const Path& registry_versions, - StringView port_name); - ExpectedL>> load_filesystem_versions_file( const ReadOnlyFilesystem& fs, const Path& registry_versions, StringView port_name, const Path& registry_root); diff --git a/locales/messages.json b/locales/messages.json index 236faab29f..6404774c4a 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -760,7 +760,6 @@ "FailedToLocateSpec": "Failed to locate spec in graph: {spec}", "_FailedToLocateSpec.comment": "An example of {spec} is zlib:x64-windows.", "FailedToObtainDependencyVersion": "Cannot find desired dependency version.", - "FailedToObtainLocalPortGitSha": "Failed to obtain git SHAs for local ports.", "FailedToObtainPackageVersion": "Cannot find desired package version.", "FailedToOpenAlgorithm": "failed to open {value}", "_FailedToOpenAlgorithm.comment": "{value} is a crypto algorithm like SHA-1 or SHA-512", @@ -1453,8 +1452,6 @@ "SuccessfulyExported": "Exported {package_name} to {path}", "_SuccessfulyExported.comment": "An example of {package_name} is zlib. An example of {path} is /foo/bar.", "SuggestGitPull": "The result may be outdated. Run `git pull` to get the latest results.", - "SuggestResolution": "To attempt to resolve all errors at once, run:\nvcpkg {command_name} --{option}", - "_SuggestResolution.comment": "An example of {command_name} is install. An example of {option} is editable.", "SuggestStartingBashShell": "Please make sure you have started a new bash shell for the change to take effect.", "SuggestUpdateVcpkg": "You may need to update the vcpkg binary; try running {command_line} to update.", "_SuggestUpdateVcpkg.comment": "An example of {command_line} is vcpkg install zlib.", diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index 407a2642fc..39ed76f6e3 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -29,14 +29,6 @@ namespace } } - struct CiVerifyVersionsDbEntry - { - SourceControlFileAndLocation scf; - Path port_directory; - std::vector entries; - Path versions_file_path; - }; - void add_parse_from_git_tree_failure_notes(LocalizedString& target, const std::string& port_name, const Path& versions_file_path, @@ -168,52 +160,63 @@ namespace } } - void verify_all_historical_git_trees(LocalizedString& errors, - MessageSink& success_sink, - const VcpkgPaths& paths, - const std::string& port_name, - const CiVerifyVersionsDbEntry& versions) - { - for (auto&& version_entry : versions.entries) - { - verify_git_tree(errors, success_sink, paths, port_name, versions.versions_file_path, version_entry); - } - } - void verify_local_port_matches_version_database(LocalizedString& errors, MessageSink& success_sink, const std::string& port_name, - const CiVerifyVersionsDbEntry& db, + const SourceControlFileAndLocation& scfl, + FullGitVersionsDatabase& versions_database, const std::string& local_git_tree) { bool success = true; - if (db.entries.empty()) + const auto& versions_database_entry = versions_database.lookup(port_name); + auto maybe_entries = versions_database_entry.entries.get(); + if (!maybe_entries) + { + // exists, but parse or file I/O error happened + return; + } + + auto entries = maybe_entries->get(); + if (!entries) + { + success = false; + errors.append_raw(scfl.control_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionDatabaseFileMissing, + msg::package_name = port_name, + msg::path = versions_database_entry.versions_file_path) + .append_raw('\n'); + return; + } + + if (entries->empty()) { success = false; - errors.append_raw(db.versions_file_path) + errors.append_raw(versions_database_entry.versions_file_path) .append_raw(": ") .append(msgErrorMessage) .append(msgInvalidNoVersions) .append_raw('\n'); } - const auto local_port_version = db.scf.source_control_file->to_schemed_version(); + const auto local_port_version = scfl.source_control_file->to_schemed_version(); - auto versions_end = db.entries.end(); - auto it = std::find_if(db.entries.begin(), versions_end, [&](const GitVersionDbEntry& entry) { + auto versions_end = entries->end(); + auto it = std::find_if(entries->begin(), versions_end, [&](const GitVersionDbEntry& entry) { return entry.version.version == local_port_version.version; }); if (it == versions_end) { success = false; - errors.append_raw(db.scf.control_location) + errors.append_raw(scfl.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionNotFoundInVersionsFile2, msg::version_spec = VersionSpec{port_name, local_port_version.version}, msg::package_name = port_name, - msg::path = db.versions_file_path) + msg::path = versions_database_entry.versions_file_path) .append_raw('\n'); return; } @@ -223,14 +226,14 @@ namespace { success = false; // assume the port is correct, so report the error on the version database file - errors.append_raw(db.versions_file_path) + errors.append_raw(versions_database_entry.versions_file_path) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionSchemeMismatch, msg::version = version_entry.version.version, msg::expected = get_scheme_name(version_entry.version.scheme), msg::actual = get_scheme_name(local_port_version.scheme), - msg::path = db.port_directory, + msg::path = scfl.port_directory(), msg::package_name = port_name) .append_raw('\n'); } @@ -238,7 +241,7 @@ namespace if (local_git_tree != version_entry.git_tree) { success = false; - errors.append_raw(db.versions_file_path) + errors.append_raw(versions_database_entry.versions_file_path) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionShaMismatch1, @@ -246,7 +249,7 @@ namespace msg::expected = version_entry.git_tree, msg::actual = local_git_tree, msg::package_name = port_name, - msg::path = db.port_directory) + msg::path = scfl.port_directory()) .append_raw('\n') .append_indent() .append_raw("vcpkg x-add-version " + port_name + "\n") @@ -268,7 +271,7 @@ namespace if (success) { - success_sink.println(LocalizedString::from_raw(db.port_directory) + success_sink.println(LocalizedString::from_raw(scfl.port_directory()) .append_raw(": ") .append(msgVersionVerifiedOK2, msg::version_spec = VersionSpec{port_name, local_port_version.version}, @@ -281,13 +284,13 @@ namespace const std::map> baseline, const Path& baseline_path, const std::string& port_name, - const CiVerifyVersionsDbEntry& db) + const SourceControlFileAndLocation& scfl) { - const auto local_port_version = db.scf.source_control_file->to_schemed_version(); + const auto local_port_version = scfl.source_control_file->to_schemed_version(); auto maybe_baseline = baseline.find(port_name); if (maybe_baseline == baseline.end()) { - errors.append_raw(db.scf.control_location) + errors.append_raw(scfl.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgBaselineMissing, msg::package_name = port_name, msg::version = local_port_version.version) @@ -317,17 +320,24 @@ namespace } } - bool verify_dependency_and_version_constraint( - const Dependency& dependency, - const std::string* feature_name, - LocalizedString& errors, - const CiVerifyVersionsDbEntry& db, - const std::map>& versions_database) + bool verify_dependency_and_version_constraint(const Dependency& dependency, + const std::string* feature_name, + LocalizedString& errors, + const SourceControlFileAndLocation& scfl, + FullGitVersionsDatabase& versions_database) { - auto dependent_versions = versions_database.find(dependency.name); - if (dependent_versions == versions_database.end()) + auto dependent_versions_db_entry = versions_database.lookup(dependency.name); + auto maybe_dependent_entries = dependent_versions_db_entry.entries.get(); + if (!maybe_dependent_entries) { - errors.append_raw(db.scf.control_location) + // versions database parse or I/O error + return false; + } + + auto dependent_entries = maybe_dependent_entries->get(); + if (!dependent_entries) + { + errors.append_raw(scfl.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgDependencyNotInVersionDatabase, msg::package_name = dependency.name) @@ -344,17 +354,17 @@ namespace auto maybe_minimum_version = dependency.constraint.try_get_minimum_version(); auto minimum_version = maybe_minimum_version.get(); - if (minimum_version && Util::none_of(dependent_versions->second.entries, [=](const GitVersionDbEntry& entry) { + if (minimum_version && Util::none_of(*dependent_entries, [=](const GitVersionDbEntry& entry) { return entry.version.version == *minimum_version; })) { - errors.append_raw(db.scf.control_location) + errors.append_raw(scfl.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionConstraintNotInDatabase, msg::package_name = dependency.name, msg::version = *minimum_version, - msg::path = dependent_versions->second.versions_file_path) + msg::path = dependent_versions_db_entry.versions_file_path) .append_raw('\n'); if (feature_name) { @@ -369,36 +379,43 @@ namespace return true; } - void verify_all_dependencies_and_version_constraints( - LocalizedString& errors, - MessageSink& success_sink, - const CiVerifyVersionsDbEntry& db, - const std::map>& versions_database) + void verify_all_dependencies_and_version_constraints(LocalizedString& errors, + MessageSink& success_sink, + const SourceControlFileAndLocation& scfl, + FullGitVersionsDatabase& versions_database) { bool success = true; - for (auto&& core_dependency : db.scf.source_control_file->core_paragraph->dependencies) + for (auto&& core_dependency : scfl.source_control_file->core_paragraph->dependencies) { success &= - verify_dependency_and_version_constraint(core_dependency, nullptr, errors, db, versions_database); + verify_dependency_and_version_constraint(core_dependency, nullptr, errors, scfl, versions_database); } - for (auto&& feature : db.scf.source_control_file->feature_paragraphs) + for (auto&& feature : scfl.source_control_file->feature_paragraphs) { for (auto&& feature_dependency : feature->dependencies) { success &= verify_dependency_and_version_constraint( - feature_dependency, &feature->name, errors, db, versions_database); + feature_dependency, &feature->name, errors, scfl, versions_database); } } - for (auto&& override_ : db.scf.source_control_file->core_paragraph->overrides) + for (auto&& override_ : scfl.source_control_file->core_paragraph->overrides) { - auto override_versions = versions_database.find(override_.name); - if (override_versions == versions_database.end()) + auto override_versions_db_entry = versions_database.lookup(override_.name); + auto maybe_override_entries = override_versions_db_entry.entries.get(); + if (!maybe_override_entries) + { + success = false; + continue; + } + + auto override_entries = maybe_override_entries->get(); + if (!override_entries) { success = false; - errors.append_raw(db.scf.control_location) + errors.append_raw(scfl.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionOverrideNotInVersionDatabase, msg::package_name = override_.name) @@ -406,18 +423,18 @@ namespace continue; } - if (Util::none_of(override_versions->second.entries, [&](const GitVersionDbEntry& entry) { + if (Util::none_of(*override_entries, [&](const GitVersionDbEntry& entry) { return entry.version.version == override_.version.version; })) { success = false; - errors.append_raw(db.scf.control_location) + errors.append_raw(scfl.control_location) .append_raw(": ") .append(msgErrorMessage) .append(msgVersionOverrideVersionNotInVersionDatabase, msg::package_name = override_.name, msg::version = override_.version.version, - msg::path = override_versions->second.versions_file_path) + msg::path = override_versions_db_entry.versions_file_path) .append_raw('\n'); } } @@ -425,7 +442,7 @@ namespace if (success) { success_sink.println( - LocalizedString::from_raw(db.scf.control_location).append_raw(": ").append(msgVersionConstraintOk)); + LocalizedString::from_raw(scfl.control_location).append_raw(": ").append(msgVersionConstraintOk)); } } @@ -460,95 +477,90 @@ namespace vcpkg bool verbose = Util::Sets::contains(parsed_args.switches, OPTION_VERBOSE); bool verify_git_trees = Util::Sets::contains(parsed_args.switches, OPTION_VERIFY_GIT_TREES); - auto maybe_port_git_tree_map = paths.git_get_local_port_treeish_map(); - if (!maybe_port_git_tree_map) - { - Checks::msg_exit_with_error(VCPKG_LINE_INFO, - msg::format(msgFailedToObtainLocalPortGitSha) - .append_raw('\n') - .append_raw(maybe_port_git_tree_map.error())); - } + auto port_git_tree_map = paths.git_get_local_port_treeish_map().value_or_exit(VCPKG_LINE_INFO); + auto& fs = paths.get_filesystem(); + auto versions_database = + load_all_git_versions_files(fs, paths.builtin_registry_versions).value_or_exit(VCPKG_LINE_INFO); + auto baseline = get_builtin_baseline(paths).value_or_exit(VCPKG_LINE_INFO); - auto& port_git_tree_map = maybe_port_git_tree_map.value_or_exit(VCPKG_LINE_INFO); + std::map> local_ports; - // Baseline is required. - auto baseline = get_builtin_baseline(paths).value_or_exit(VCPKG_LINE_INFO); - auto& fs = paths.get_filesystem(); LocalizedString errors; - std::map> versions_database; for (auto&& port_path : fs.get_directories_non_recursive(paths.builtin_ports_directory(), VCPKG_LINE_INFO)) { auto port_name = port_path.stem().to_string(); auto maybe_loaded_port = Paragraphs::try_load_port_required(fs, port_name, port_path).maybe_scfl; auto loaded_port = maybe_loaded_port.get(); - if (!loaded_port) + if (loaded_port) { - errors.append(std::move(maybe_loaded_port).error()).append_raw('\n'); - continue; - } - - auto load_versions_result = load_git_versions_file(fs, paths.builtin_registry_versions, port_name); - auto maybe_versions_db = load_versions_result.entries.get(); - if (!maybe_versions_db) - { - errors.append(std::move(load_versions_result.entries).error()).append_raw('\n'); - continue; - } - - auto versions_db = maybe_versions_db->get(); - if (!versions_db) - { - errors.append_raw(loaded_port->control_location) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionDatabaseFileMissing, - msg::package_name = port_name, - msg::path = load_versions_result.versions_file_path) - .append_raw('\n'); - continue; + local_ports.emplace(port_name, std::move(*loaded_port)); } - versions_database.emplace(std::move(port_name), - CiVerifyVersionsDbEntry{std::move(*loaded_port), - std::move(port_path), - std::move(*versions_db), - std::move(load_versions_result.versions_file_path)}); + errors.append(std::move(maybe_loaded_port).error()).append_raw('\n'); } auto& success_sink = verbose ? stdout_sink : null_sink; - for (const auto& port : versions_database) + for (const auto& local_port : local_ports) { - const auto& port_name = port.first; - const auto& db = port.second; + const auto& port_name = local_port.first; + const auto& scfl = local_port.second; auto git_tree_it = port_git_tree_map.find(port_name); if (git_tree_it == port_git_tree_map.end()) { - errors.append_raw(db.scf.control_location) + errors.append_raw(scfl.control_location) .append_raw(": ") .append(msgErrorMessage) - .append(msgVersionShaMissing, msg::package_name = port_name, msg::path = db.port_directory) + .append(msgVersionShaMissing, msg::package_name = port_name, msg::path = scfl.port_directory()) .append_raw('\n'); } else { - verify_local_port_matches_version_database(errors, success_sink, port_name, db, git_tree_it->second); + verify_local_port_matches_version_database( + errors, success_sink, port_name, scfl, versions_database, git_tree_it->second); } verify_local_port_matches_baseline( - errors, success_sink, baseline, paths.builtin_registry_versions / "baseline.json", port_name, db); + errors, success_sink, baseline, paths.builtin_registry_versions / "baseline.json", port_name, scfl); - if (verify_git_trees) + verify_all_dependencies_and_version_constraints(errors, success_sink, scfl, versions_database); + } + + // We run version database checks at the end in case any of the above created new cache entries + for (auto&& versions_cache_entry : versions_database.cache()) + { + auto&& port_name = versions_cache_entry.first; + auto maybe_entries = versions_cache_entry.second.entries.get(); + if (!maybe_entries) { - verify_all_historical_git_trees(errors, success_sink, paths, port_name, db); + errors.append(versions_cache_entry.second.entries.error()).append_raw('\n'); + continue; } - verify_all_dependencies_and_version_constraints(errors, success_sink, db, versions_database); + auto entries = maybe_entries->get(); + if (!entries) + { + // missing version database entry is OK; should have been reported as one of the other error categories + // by one of the other checks + continue; + } + + if (verify_git_trees) + { + for (auto&& version_entry : *entries) + { + verify_git_tree(errors, + success_sink, + paths, + port_name, + versions_cache_entry.second.versions_file_path, + version_entry); + } + } } if (!errors.empty()) { errors.append_raw('\n'); - errors.append(msgSuggestResolution, msg::command_name = "x-add-version", msg::option = "all"); Checks::msg_exit_with_message(VCPKG_LINE_INFO, errors); } diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index f5af13a819..e122e7a836 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -1688,6 +1688,83 @@ namespace vcpkg return {std::move(result), std::move(versions_file_path)}; } + FullGitVersionsDatabase::FullGitVersionsDatabase( + const ReadOnlyFilesystem& fs, + const Path& registry_versions, + std::map>&& initial) + : m_fs(&fs), m_registry_versions(registry_versions), m_cache(std::move(initial)) + { + } + + FullGitVersionsDatabase::FullGitVersionsDatabase(const FullGitVersionsDatabase&) = default; + FullGitVersionsDatabase::FullGitVersionsDatabase(FullGitVersionsDatabase&&) = default; + FullGitVersionsDatabase& FullGitVersionsDatabase::operator=(const FullGitVersionsDatabase&) = default; + FullGitVersionsDatabase& FullGitVersionsDatabase::operator=(FullGitVersionsDatabase&&) = default; + + const GitVersionsLoadResult& FullGitVersionsDatabase::lookup(StringView port_name) + { + auto it = m_cache.lower_bound(port_name); + if (it != m_cache.end() && port_name >= it->first) + { + return it->second; + } + + return m_cache.emplace_hint(it, port_name, load_git_versions_file(*m_fs, m_registry_versions, port_name)) + ->second; + } + + const std::map>& FullGitVersionsDatabase::cache() const + { + return m_cache; + } + + ExpectedL load_all_git_versions_files(const ReadOnlyFilesystem& fs, + const Path& registry_versions) + { + auto maybe_letter_directories = fs.try_get_directories_non_recursive(registry_versions); + auto letter_directories = maybe_letter_directories.get(); + if (!letter_directories) + { + return std::move(maybe_letter_directories).error(); + } + + std::map> initial_result; + for (auto&& letter_directory : *letter_directories) + { + auto maybe_versions_files = fs.try_get_files_non_recursive(letter_directory); + auto versions_files = maybe_versions_files.get(); + if (!versions_files) + { + return std::move(maybe_versions_files).error(); + } + + for (auto&& versions_file : *versions_files) + { + auto port_name_json = versions_file.filename(); + static constexpr StringLiteral dot_json = ".json"; + if (!Strings::ends_with(port_name_json, dot_json)) + { + continue; + } + + StringView port_name{port_name_json.data(), port_name_json.size() - dot_json.size()}; + auto maybe_port_versions = load_git_versions_file_impl(fs, versions_file); + if (!maybe_port_versions) + { + maybe_port_versions.error() + .append_raw('\n') + .append(msgNoteMessage) + .append( + msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file); + } + + initial_result.emplace(port_name, GitVersionsLoadResult{std::move(maybe_port_versions), versions_file}); + } + } + + return FullGitVersionsDatabase{fs, registry_versions, std::move(initial_result)}; + } + ExpectedL>> load_filesystem_versions_file( const ReadOnlyFilesystem& fs, const Path& registry_versions, StringView port_name, const Path& registry_root) { From 7b3682fc65d1cb98b04fdb0eb4c9afca5e8141e2 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 27 Sep 2023 00:52:11 -0700 Subject: [PATCH 09/48] oops --- src/vcpkg/commands.ci-verify-versions.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index 39ed76f6e3..4e3f51bed4 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -494,6 +494,7 @@ namespace vcpkg if (loaded_port) { local_ports.emplace(port_name, std::move(*loaded_port)); + continue; } errors.append(std::move(maybe_loaded_port).error()).append_raw('\n'); From 13a30de90730417186c93504efa84d813aefc308 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 27 Sep 2023 00:53:16 -0700 Subject: [PATCH 10/48] oops2 --- src/vcpkg/commands.ci-verify-versions.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index 4e3f51bed4..57ead0a887 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -561,7 +561,6 @@ namespace vcpkg if (!errors.empty()) { - errors.append_raw('\n'); Checks::msg_exit_with_message(VCPKG_LINE_INFO, errors); } From 8dd6ad8a3e9ec7a38784ecef6c974b4642ad679e Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 27 Sep 2023 10:42:25 -0700 Subject: [PATCH 11/48] Try to workaround macos compile failure by just not providing copy ops not used anyway --- include/vcpkg/registries.h | 2 -- src/vcpkg/registries.cpp | 2 -- 2 files changed, 4 deletions(-) diff --git a/include/vcpkg/registries.h b/include/vcpkg/registries.h index edba2d39c9..5f1d2ae948 100644 --- a/include/vcpkg/registries.h +++ b/include/vcpkg/registries.h @@ -192,9 +192,7 @@ namespace vcpkg explicit FullGitVersionsDatabase(const ReadOnlyFilesystem& fs, const Path& registry_versions, std::map>&& initial); - FullGitVersionsDatabase(const FullGitVersionsDatabase&); FullGitVersionsDatabase(FullGitVersionsDatabase&&); - FullGitVersionsDatabase& operator=(const FullGitVersionsDatabase&); FullGitVersionsDatabase& operator=(FullGitVersionsDatabase&&); const GitVersionsLoadResult& lookup(StringView port_name); diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index e122e7a836..7dd93672c9 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -1696,9 +1696,7 @@ namespace vcpkg { } - FullGitVersionsDatabase::FullGitVersionsDatabase(const FullGitVersionsDatabase&) = default; FullGitVersionsDatabase::FullGitVersionsDatabase(FullGitVersionsDatabase&&) = default; - FullGitVersionsDatabase& FullGitVersionsDatabase::operator=(const FullGitVersionsDatabase&) = default; FullGitVersionsDatabase& FullGitVersionsDatabase::operator=(FullGitVersionsDatabase&&) = default; const GitVersionsLoadResult& FullGitVersionsDatabase::lookup(StringView port_name) From b094ab1d856add2f4c29762b46f9dbad0eb00d40 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 27 Sep 2023 14:54:59 -0700 Subject: [PATCH 12/48] Get rid of one more CONTROL/vcpkg.json tester by using git_checkout_port instead of git_show. (This also makes repeatedly running much faster) --- include/vcpkg/base/message-data.inc.h | 4 -- src/vcpkg/commands.ci-verify-versions.cpp | 82 +++++++---------------- 2 files changed, 23 insertions(+), 63 deletions(-) diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index e983c5c03e..6e8a0992f1 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -416,10 +416,6 @@ DECLARE_MESSAGE(BuildTroubleshootingMessage4, DECLARE_MESSAGE(BuiltInTriplets, (), "", "Built-in Triplets:") DECLARE_MESSAGE(BuiltWithIncorrectArchitecture, (), "", "The following files were built for an incorrect architecture:") DECLARE_MESSAGE(CheckedOutGitSha, (msg::commit_sha), "", "Checked out Git SHA: {commit_sha}") -DECLARE_MESSAGE(CheckedOutObjectMissingManifest, - (), - "", - "The checked-out object does not contain a CONTROL file or vcpkg.json file.") DECLARE_MESSAGE(ChecksFailedCheck, (), "", "vcpkg has crashed; no additional details are available.") DECLARE_MESSAGE(ChecksUnreachableCode, (), "", "unreachable code was reached") DECLARE_MESSAGE(ChecksUpdateVcpkg, (), "", "updating vcpkg by rerunning bootstrap-vcpkg may resolve this failure.") diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index 57ead0a887..b165c3ffc0 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -54,71 +54,35 @@ namespace const GitVersionDbEntry& version_entry) { bool success = true; - auto treeish = version_entry.git_tree + ":CONTROL"; - auto maybe_maybe_loaded_manifest = - paths.git_show(treeish, paths.root / ".git") - .then([&](std::string&& file) -> ExpectedL { - auto maybe_scf = Paragraphs::try_load_control_file_text(file, treeish); - if (!maybe_scf) - { - add_parse_from_git_tree_failure_notes( - maybe_scf.error(), port_name, versions_file_path, version_entry.version, treeish); - } - - return maybe_scf; - }); - - auto maybe_loaded_manifest = maybe_maybe_loaded_manifest.get(); - if (!maybe_loaded_manifest) + auto maybe_extracted_tree = paths.git_checkout_port(port_name, version_entry.git_tree, paths.root / ".git"); + auto extracted_tree = maybe_extracted_tree.get(); + if (!extracted_tree) { success = false; - errors.append(std::move(maybe_maybe_loaded_manifest).error()).append_raw('\n'); + add_parse_from_git_tree_failure_notes(maybe_extracted_tree.error(), + port_name, + versions_file_path, + version_entry.version, + version_entry.git_tree); + errors.append(std::move(maybe_extracted_tree).error()).append_raw('\n'); return; } - if (!maybe_loaded_manifest->source_control_file) + auto load_result = Paragraphs::try_load_port(paths.get_filesystem(), port_name, *extracted_tree); + auto scfl = load_result.maybe_scfl.get(); + if (!scfl) { - treeish = version_entry.git_tree + ":vcpkg.json"; - paths.git_show(treeish, paths.root / ".git") - .then([&](std::string&& file) -> ExpectedL { - auto maybe_scf = Paragraphs::try_load_port_manifest_text(file, treeish, stdout_sink); - if (!maybe_scf) - { - add_parse_from_git_tree_failure_notes( - maybe_scf.error(), port_name, versions_file_path, version_entry.version, treeish); - } - - return maybe_scf; - }); - - maybe_loaded_manifest = maybe_maybe_loaded_manifest.get(); - if (!maybe_loaded_manifest) - { - success = false; - errors.append(std::move(maybe_maybe_loaded_manifest).error()).append_raw('\n'); - return; - } - - if (!maybe_loaded_manifest->source_control_file) - { - success = false; - errors.append_raw(versions_file_path) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgCheckedOutObjectMissingManifest) - .append_raw('\n') - .append(msgNoteMessage) - .append(msgCheckedOutGitSha, msg::commit_sha = treeish) - .append_raw('\n') - .append(msgNoteMessage) - .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) - .append_raw('\n'); - return; - } + success = false; + add_parse_from_git_tree_failure_notes(load_result.maybe_scfl.error(), + port_name, + versions_file_path, + version_entry.version, + version_entry.git_tree); + errors.append(std::move(load_result.maybe_scfl).error()).append_raw('\n'); + return; } - auto& scf = *maybe_loaded_manifest->source_control_file; - auto&& git_tree_version = scf.to_schemed_version(); + auto&& git_tree_version = scfl->source_control_file->to_schemed_version(); if (version_entry.version.version != git_tree_version.version) { success = false; @@ -128,7 +92,7 @@ namespace .append(msgVersionInDeclarationDoesNotMatch, msg::version = git_tree_version.version) .append_raw('\n') .append(msgNoteMessage) - .append(msgCheckedOutGitSha, msg::commit_sha = treeish) + .append(msgCheckedOutGitSha, msg::commit_sha = version_entry.git_tree) .append_raw('\n') .append(msgNoteMessage) .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) @@ -145,7 +109,7 @@ namespace msg::version = version_entry.version.version, msg::expected = get_scheme_name(version_entry.version.scheme), msg::actual = get_scheme_name(git_tree_version.scheme), - msg::path = treeish, + msg::path = version_entry.git_tree, msg::package_name = port_name) .append_raw('\n'); } From 58452c10af538aa678a04e94b6038d72842ebc66 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 27 Sep 2023 15:45:52 -0700 Subject: [PATCH 13/48] Print success and failure messages at the same time and deduplicate git checkout failure output. --- include/vcpkg/base/message-data.inc.h | 1 - locales/messages.json | 3 - src/vcpkg/commands.ci-verify-versions.cpp | 428 ++++++++++++---------- 3 files changed, 226 insertions(+), 206 deletions(-) diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 6e8a0992f1..9582846fa0 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -3142,7 +3142,6 @@ DECLARE_MESSAGE(WhileCheckingOutPortTreeIsh, "", "while checking out port {package_name} with git tree {commit_sha}") DECLARE_MESSAGE(WhileGettingLocalTreeIshObjectsForPorts, (), "", "while getting local treeish objects for ports") -DECLARE_MESSAGE(WhileLoadingPortFromGitTree, (msg::commit_sha), "", "while trying to load port from: {commit_sha}") DECLARE_MESSAGE(WhileLookingForSpec, (msg::spec), "", "while looking for {spec}:") DECLARE_MESSAGE(WhileParsingVersionsForPort, (msg::package_name, msg::path), diff --git a/locales/messages.json b/locales/messages.json index 6404774c4a..da0db24a82 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -276,7 +276,6 @@ "_CMakeUsingExportedLibs.comment": "{value} is a CMake command line switch of the form -DFOO=BAR", "CheckedOutGitSha": "Checked out Git SHA: {commit_sha}", "_CheckedOutGitSha.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", - "CheckedOutObjectMissingManifest": "The checked-out object does not contain a CONTROL file or vcpkg.json file.", "ChecksFailedCheck": "vcpkg has crashed; no additional details are available.", "ChecksUnreachableCode": "unreachable code was reached", "ChecksUpdateVcpkg": "updating vcpkg by rerunning bootstrap-vcpkg may resolve this failure.", @@ -1722,8 +1721,6 @@ "WhileCheckingOutPortTreeIsh": "while checking out port {package_name} with git tree {commit_sha}", "_WhileCheckingOutPortTreeIsh.comment": "An example of {package_name} is zlib. An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "WhileGettingLocalTreeIshObjectsForPorts": "while getting local treeish objects for ports", - "WhileLoadingPortFromGitTree": "while trying to load port from: {commit_sha}", - "_WhileLoadingPortFromGitTree.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "WhileLookingForSpec": "while looking for {spec}:", "_WhileLookingForSpec.comment": "An example of {spec} is zlib:x64-windows.", "WhileParsingVersionsForPort": "while parsing versions for {package_name} from {path}", diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index b165c3ffc0..d308947600 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -29,24 +29,7 @@ namespace } } - void add_parse_from_git_tree_failure_notes(LocalizedString& target, - const std::string& port_name, - const Path& versions_file_path, - const SchemedVersion& version, - StringView treeish) - { - target.append_raw('\n') - .append(msgNoteMessage) - .append(msgWhileLoadingPortFromGitTree, msg::commit_sha = treeish) - .append_raw('\n') - .append(msgNoteMessage) - .append(msgWhileValidatingVersion, msg::version = version.version) - .append_raw('\n') - .append(msgNoteMessage) - .append(msgWhileParsingVersionsForPort, msg::package_name = port_name, msg::path = versions_file_path); - } - - void verify_git_tree(LocalizedString& errors, + bool verify_git_tree(MessageSink& errors_sink, MessageSink& success_sink, const VcpkgPaths& paths, const std::string& port_name, @@ -59,13 +42,15 @@ namespace if (!extracted_tree) { success = false; - add_parse_from_git_tree_failure_notes(maybe_extracted_tree.error(), - port_name, - versions_file_path, - version_entry.version, - version_entry.git_tree); - errors.append(std::move(maybe_extracted_tree).error()).append_raw('\n'); - return; + errors_sink.print(Color::error, + LocalizedString::from_raw(versions_file_path) + .append_raw(": ") + .append(maybe_extracted_tree.error()) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) + .append_raw('\n')); + return success; } auto load_result = Paragraphs::try_load_port(paths.get_filesystem(), port_name, *extracted_tree); @@ -73,58 +58,65 @@ namespace if (!scfl) { success = false; - add_parse_from_git_tree_failure_notes(load_result.maybe_scfl.error(), - port_name, - versions_file_path, - version_entry.version, - version_entry.git_tree); - errors.append(std::move(load_result.maybe_scfl).error()).append_raw('\n'); - return; + errors_sink.print(Color::error, + LocalizedString::from_raw(versions_file_path) + .append_raw(": ") + .append(load_result.maybe_scfl.error()) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) + .append_raw('\n')); + return success; } auto&& git_tree_version = scfl->source_control_file->to_schemed_version(); if (version_entry.version.version != git_tree_version.version) { success = false; - errors.append_raw(versions_file_path) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionInDeclarationDoesNotMatch, msg::version = git_tree_version.version) - .append_raw('\n') - .append(msgNoteMessage) - .append(msgCheckedOutGitSha, msg::commit_sha = version_entry.git_tree) - .append_raw('\n') - .append(msgNoteMessage) - .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) - .append_raw('\n'); + errors_sink.print(Color::error, + LocalizedString::from_raw(versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionInDeclarationDoesNotMatch, msg::version = git_tree_version.version) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgCheckedOutGitSha, msg::commit_sha = version_entry.git_tree) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) + .append_raw('\n')); } if (version_entry.version.scheme != git_tree_version.scheme) { success = false; - errors.append_raw(versions_file_path) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionSchemeMismatch, - msg::version = version_entry.version.version, - msg::expected = get_scheme_name(version_entry.version.scheme), - msg::actual = get_scheme_name(git_tree_version.scheme), - msg::path = version_entry.git_tree, - msg::package_name = port_name) - .append_raw('\n'); + errors_sink.print(Color::error, + LocalizedString::from_raw(versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionSchemeMismatch, + msg::version = version_entry.version.version, + msg::expected = get_scheme_name(version_entry.version.scheme), + msg::actual = get_scheme_name(git_tree_version.scheme), + msg::path = version_entry.git_tree, + msg::package_name = port_name) + .append_raw('\n')); } if (success) { - success_sink.println(LocalizedString::from_raw(versions_file_path) - .append_raw(": ") - .append(msgVersionVerifiedOK2, - msg::version_spec = VersionSpec{port_name, version_entry.version.version}, - msg::commit_sha = version_entry.git_tree)); + success_sink.print(LocalizedString::from_raw(versions_file_path) + .append_raw(": ") + .append(msgVersionVerifiedOK2, + msg::version_spec = VersionSpec{port_name, version_entry.version.version}, + msg::commit_sha = version_entry.git_tree) + .append_raw('\n')); } + + return success; } - void verify_local_port_matches_version_database(LocalizedString& errors, + bool verify_local_port_matches_version_database(MessageSink& errors_sink, MessageSink& success_sink, const std::string& port_name, const SourceControlFileAndLocation& scfl, @@ -137,31 +129,33 @@ namespace if (!maybe_entries) { // exists, but parse or file I/O error happened - return; + return success; } auto entries = maybe_entries->get(); if (!entries) { success = false; - errors.append_raw(scfl.control_location) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionDatabaseFileMissing, - msg::package_name = port_name, - msg::path = versions_database_entry.versions_file_path) - .append_raw('\n'); - return; + errors_sink.print(Color::error, + LocalizedString::from_raw(scfl.control_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionDatabaseFileMissing, + msg::package_name = port_name, + msg::path = versions_database_entry.versions_file_path) + .append_raw('\n')); + return success; } if (entries->empty()) { success = false; - errors.append_raw(versions_database_entry.versions_file_path) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgInvalidNoVersions) - .append_raw('\n'); + errors_sink.print(Color::error, + LocalizedString::from_raw(versions_database_entry.versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgInvalidNoVersions) + .append_raw('\n')); } const auto local_port_version = scfl.source_control_file->to_schemed_version(); @@ -174,15 +168,16 @@ namespace if (it == versions_end) { success = false; - errors.append_raw(scfl.control_location) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionNotFoundInVersionsFile2, - msg::version_spec = VersionSpec{port_name, local_port_version.version}, - msg::package_name = port_name, - msg::path = versions_database_entry.versions_file_path) - .append_raw('\n'); - return; + errors_sink.print(Color::error, + LocalizedString::from_raw(scfl.control_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionNotFoundInVersionsFile2, + msg::version_spec = VersionSpec{port_name, local_port_version.version}, + msg::package_name = port_name, + msg::path = versions_database_entry.versions_file_path) + .append_raw('\n')); + return success; } auto& version_entry = *it; @@ -190,60 +185,66 @@ namespace { success = false; // assume the port is correct, so report the error on the version database file - errors.append_raw(versions_database_entry.versions_file_path) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionSchemeMismatch, - msg::version = version_entry.version.version, - msg::expected = get_scheme_name(version_entry.version.scheme), - msg::actual = get_scheme_name(local_port_version.scheme), - msg::path = scfl.port_directory(), - msg::package_name = port_name) - .append_raw('\n'); + errors_sink.print(Color::error, + LocalizedString::from_raw(versions_database_entry.versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionSchemeMismatch, + msg::version = version_entry.version.version, + msg::expected = get_scheme_name(version_entry.version.scheme), + msg::actual = get_scheme_name(local_port_version.scheme), + msg::path = scfl.port_directory(), + msg::package_name = port_name) + .append_raw('\n')); } if (local_git_tree != version_entry.git_tree) { success = false; - errors.append_raw(versions_database_entry.versions_file_path) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionShaMismatch1, - msg::version_spec = VersionSpec{port_name, local_port_version.version}, - msg::expected = version_entry.git_tree, - msg::actual = local_git_tree, - msg::package_name = port_name, - msg::path = scfl.port_directory()) - .append_raw('\n') - .append_indent() - .append_raw("vcpkg x-add-version " + port_name + "\n") - .append_indent() - .append_raw("git add versions\n") - .append_indent() - .append(msgGitCommitUpdateVersionDatabase) - .append_raw('\n') - .append(msgVersionShaMismatch2, msg::version_spec = VersionSpec{port_name, local_port_version.version}) - .append_raw('\n') - .append_indent() - .append_raw("vcpkg x-add-version " + port_name + " --overwrite-version\n") - .append_indent() - .append_raw("git add versions\n") - .append_indent() - .append(msgGitCommitUpdateVersionDatabase) - .append_raw('\n'); + errors_sink.print(Color::error, + LocalizedString::from_raw(versions_database_entry.versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionShaMismatch1, + msg::version_spec = VersionSpec{port_name, local_port_version.version}, + msg::expected = version_entry.git_tree, + msg::actual = local_git_tree, + msg::package_name = port_name, + msg::path = scfl.port_directory()) + .append_raw('\n') + .append_indent() + .append_raw("vcpkg x-add-version " + port_name + "\n") + .append_indent() + .append_raw("git add versions\n") + .append_indent() + .append(msgGitCommitUpdateVersionDatabase) + .append_raw('\n') + .append(msgVersionShaMismatch2, + msg::version_spec = VersionSpec{port_name, local_port_version.version}) + .append_raw('\n') + .append_indent() + .append_raw("vcpkg x-add-version " + port_name + " --overwrite-version\n") + .append_indent() + .append_raw("git add versions\n") + .append_indent() + .append(msgGitCommitUpdateVersionDatabase) + .append_raw('\n')); } if (success) { - success_sink.println(LocalizedString::from_raw(scfl.port_directory()) - .append_raw(": ") - .append(msgVersionVerifiedOK2, - msg::version_spec = VersionSpec{port_name, local_port_version.version}, - msg::commit_sha = version_entry.git_tree)); + success_sink.print(LocalizedString::from_raw(scfl.port_directory()) + .append_raw(": ") + .append(msgVersionVerifiedOK2, + msg::version_spec = VersionSpec{port_name, local_port_version.version}, + msg::commit_sha = version_entry.git_tree) + .append_raw('\n')); } + + return success; } - void verify_local_port_matches_baseline(LocalizedString& errors, + bool verify_local_port_matches_baseline(MessageSink& errors_sink, MessageSink& success_sink, const std::map> baseline, const Path& baseline_path, @@ -254,39 +255,44 @@ namespace auto maybe_baseline = baseline.find(port_name); if (maybe_baseline == baseline.end()) { - errors.append_raw(scfl.control_location) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgBaselineMissing, msg::package_name = port_name, msg::version = local_port_version.version) - .append_raw('\n'); - return; + errors_sink.print(Color::error, + LocalizedString::from_raw(scfl.control_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgBaselineMissing, + msg::package_name = port_name, + msg::version = local_port_version.version) + .append_raw('\n')); + return false; } auto&& baseline_version = maybe_baseline->second; if (baseline_version == local_port_version.version) { - success_sink.println(LocalizedString::from_raw(baseline_path) - .append_raw(": ") - .append(msgVersionBaselineMatch, - msg::version_spec = VersionSpec{port_name, local_port_version.version})); - } - else - { - // assume the port is correct, so report the error on the baseline.json file - errors.append_raw(baseline_path) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionBaselineMismatch, - msg::expected = local_port_version.version, - msg::actual = baseline_version, - msg::package_name = port_name) - .append_raw('\n'); + success_sink.print(LocalizedString::from_raw(baseline_path) + .append_raw(": ") + .append(msgVersionBaselineMatch, + msg::version_spec = VersionSpec{port_name, local_port_version.version}) + .append_raw('\n')); + return true; } + + // assume the port is correct, so report the error on the baseline.json file + errors_sink.print(Color::error, + LocalizedString::from_raw(baseline_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionBaselineMismatch, + msg::expected = local_port_version.version, + msg::actual = baseline_version, + msg::package_name = port_name) + .append_raw('\n')); + return false; } bool verify_dependency_and_version_constraint(const Dependency& dependency, const std::string* feature_name, - LocalizedString& errors, + MessageSink& errors_sink, const SourceControlFileAndLocation& scfl, FullGitVersionsDatabase& versions_database) { @@ -301,18 +307,19 @@ namespace auto dependent_entries = maybe_dependent_entries->get(); if (!dependent_entries) { - errors.append_raw(scfl.control_location) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgDependencyNotInVersionDatabase, msg::package_name = dependency.name) - .append_raw('\n'); + auto this_error = LocalizedString::from_raw(scfl.control_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgDependencyNotInVersionDatabase, msg::package_name = dependency.name) + .append_raw('\n'); if (feature_name) { - errors.append(msgNoteMessage) + this_error.append(msgNoteMessage) .append(msgDependencyInFeature, msg::feature = *feature_name) .append_raw('\n'); } + errors_sink.print(Color::error, std::move(this_error)); return false; } @@ -322,28 +329,29 @@ namespace return entry.version.version == *minimum_version; })) { - errors.append_raw(scfl.control_location) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionConstraintNotInDatabase, - msg::package_name = dependency.name, - msg::version = *minimum_version, - msg::path = dependent_versions_db_entry.versions_file_path) - .append_raw('\n'); + auto this_error = LocalizedString::from_raw(scfl.control_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionConstraintNotInDatabase, + msg::package_name = dependency.name, + msg::version = *minimum_version, + msg::path = dependent_versions_db_entry.versions_file_path) + .append_raw('\n'); if (feature_name) { - errors.append(msgNoteMessage) + this_error.append(msgNoteMessage) .append(msgDependencyInFeature, msg::feature = *feature_name) .append_raw('\n'); } + errors_sink.print(Color::error, std::move(this_error)); return false; } return true; } - void verify_all_dependencies_and_version_constraints(LocalizedString& errors, + bool verify_all_dependencies_and_version_constraints(MessageSink& errors_sink, MessageSink& success_sink, const SourceControlFileAndLocation& scfl, FullGitVersionsDatabase& versions_database) @@ -352,8 +360,8 @@ namespace for (auto&& core_dependency : scfl.source_control_file->core_paragraph->dependencies) { - success &= - verify_dependency_and_version_constraint(core_dependency, nullptr, errors, scfl, versions_database); + success &= verify_dependency_and_version_constraint( + core_dependency, nullptr, errors_sink, scfl, versions_database); } for (auto&& feature : scfl.source_control_file->feature_paragraphs) @@ -361,7 +369,7 @@ namespace for (auto&& feature_dependency : feature->dependencies) { success &= verify_dependency_and_version_constraint( - feature_dependency, &feature->name, errors, scfl, versions_database); + feature_dependency, &feature->name, errors_sink, scfl, versions_database); } } @@ -379,11 +387,13 @@ namespace if (!override_entries) { success = false; - errors.append_raw(scfl.control_location) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionOverrideNotInVersionDatabase, msg::package_name = override_.name) - .append_raw('\n'); + errors_sink.print( + Color::error, + LocalizedString::from_raw(scfl.control_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionOverrideNotInVersionDatabase, msg::package_name = override_.name) + .append_raw('\n')); continue; } @@ -392,22 +402,27 @@ namespace })) { success = false; - errors.append_raw(scfl.control_location) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionOverrideVersionNotInVersionDatabase, - msg::package_name = override_.name, - msg::version = override_.version.version, - msg::path = override_versions_db_entry.versions_file_path) - .append_raw('\n'); + errors_sink.print(Color::error, + LocalizedString::from_raw(scfl.control_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionOverrideVersionNotInVersionDatabase, + msg::package_name = override_.name, + msg::version = override_.version.version, + msg::path = override_versions_db_entry.versions_file_path) + .append_raw('\n')); } } if (success) { - success_sink.println( - LocalizedString::from_raw(scfl.control_location).append_raw(": ").append(msgVersionConstraintOk)); + success_sink.print(LocalizedString::from_raw(scfl.control_location) + .append_raw(": ") + .append(msgVersionConstraintOk) + .append_raw('\n')); } + + return success; } constexpr StringLiteral OPTION_VERBOSE = "verbose"; @@ -449,7 +464,7 @@ namespace vcpkg std::map> local_ports; - LocalizedString errors; + MessageSink& errors_sink = stdout_sink; for (auto&& port_path : fs.get_directories_non_recursive(paths.builtin_ports_directory(), VCPKG_LINE_INFO)) { auto port_name = port_path.stem().to_string(); @@ -461,9 +476,11 @@ namespace vcpkg continue; } - errors.append(std::move(maybe_loaded_port).error()).append_raw('\n'); + errors_sink.println(Color::error, std::move(maybe_loaded_port).error()); } + bool success = true; + auto& success_sink = verbose ? stdout_sink : null_sink; for (const auto& local_port : local_ports) { @@ -472,22 +489,29 @@ namespace vcpkg auto git_tree_it = port_git_tree_map.find(port_name); if (git_tree_it == port_git_tree_map.end()) { - errors.append_raw(scfl.control_location) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionShaMissing, msg::package_name = port_name, msg::path = scfl.port_directory()) - .append_raw('\n'); + errors_sink.print( + Color::error, + LocalizedString::from_raw(scfl.control_location) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionShaMissing, msg::package_name = port_name, msg::path = scfl.port_directory()) + .append_raw('\n')); } else { - verify_local_port_matches_version_database( - errors, success_sink, port_name, scfl, versions_database, git_tree_it->second); + success &= verify_local_port_matches_version_database( + errors_sink, success_sink, port_name, scfl, versions_database, git_tree_it->second); } - verify_local_port_matches_baseline( - errors, success_sink, baseline, paths.builtin_registry_versions / "baseline.json", port_name, scfl); + success &= verify_local_port_matches_baseline(errors_sink, + success_sink, + baseline, + paths.builtin_registry_versions / "baseline.json", + port_name, + scfl); - verify_all_dependencies_and_version_constraints(errors, success_sink, scfl, versions_database); + success &= + verify_all_dependencies_and_version_constraints(errors_sink, success_sink, scfl, versions_database); } // We run version database checks at the end in case any of the above created new cache entries @@ -497,7 +521,7 @@ namespace vcpkg auto maybe_entries = versions_cache_entry.second.entries.get(); if (!maybe_entries) { - errors.append(versions_cache_entry.second.entries.error()).append_raw('\n'); + errors_sink.println(Color::error, versions_cache_entry.second.entries.error()); continue; } @@ -513,19 +537,19 @@ namespace vcpkg { for (auto&& version_entry : *entries) { - verify_git_tree(errors, - success_sink, - paths, - port_name, - versions_cache_entry.second.versions_file_path, - version_entry); + success &= verify_git_tree(errors_sink, + success_sink, + paths, + port_name, + versions_cache_entry.second.versions_file_path, + version_entry); } } } - if (!errors.empty()) + if (!success) { - Checks::msg_exit_with_message(VCPKG_LINE_INFO, errors); + Checks::exit_fail(VCPKG_LINE_INFO); } Checks::exit_success(VCPKG_LINE_INFO); From dac383c3c38dd4f7c1fccad7797ebce2526c9096 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 27 Sep 2023 16:40:52 -0700 Subject: [PATCH 14/48] Add comment explaining funny output. --- src/vcpkg/commands.ci-verify-versions.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index d308947600..084f4703bd 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -53,11 +53,21 @@ namespace return success; } - auto load_result = Paragraphs::try_load_port(paths.get_filesystem(), port_name, *extracted_tree); + auto load_result = Paragraphs::try_load_port_required(paths.get_filesystem(), port_name, *extracted_tree); auto scfl = load_result.maybe_scfl.get(); if (!scfl) { success = false; + // This output is technically wrong as it prints both the versions file path and the temporary extracted + // path, like this: + // + // C:\Dev\vcpkg\versions\a-\abseil.json: + // C:\Dev\vcpkg\buildtrees\versioning_\versions\abseil\28fa609b06eec70bb06e61891e94b94f35f7d06e\vcpkg.json: + // error: $.features: mismatched type: expected a set of features note: while validating version: + // 2020-03-03#7 + // + // However including both paths likely helps investigation and there isn't an easy way to replace only that + // file path right now errors_sink.print(Color::error, LocalizedString::from_raw(versions_file_path) .append_raw(": ") From 8786bab77fd50970dbcef7e55b3b3dacb3c3b75b Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 27 Sep 2023 17:00:41 -0700 Subject: [PATCH 15/48] Deduplicate 'failed to load port' message. Before: ``` PS C:\Dev\test> ..\vcpkg\vcpkg.exe install warning: In the September 2023 release, the default triplet for vcpkg libraries changed from x86-windows to the detected host triplet (x64-windows). For the old behavior, add --triplet x86-windows . To suppress this message, add --triplet x64-windows . error: while loading C:\Dev\vcpkg\buildtrees\versioning_\versions\libwebp\a05e0de81085231df86f6902aba1e0a364e2ca7b\CONTROL: C:\Dev\vcpkg\buildtrees\versioning_\versions\libwebp\a05e0de81085231df86f6902aba1e0a364e2ca7b\CONTROL:1:94: error: invalid character in feature name (must be lowercase, digits, '-', or '*') on expression: libwebp[anim, gif2webp, img2webp, info, mux, nearlossless, simd, cwebp, dwebp], libwebp[vwebp_sdl] (!osx), libwebp[extras] (!osx) ^Failed to load port libwebp from C:\Dev\vcpkg\buildtrees\versioning_\versions\libwebp\a05e0de81085231df86f6902aba1e0a364e2ca7b note: updating vcpkg by rerunning bootstrap-vcpkg may resolve this failure. ``` After: ``` PS C:\Dev\test> C:\Dev\vcpkg-tool\out\build\Win-x64-Release-Official\vcpkg.exe install --vcpkg-root=C:\Dev\vcpkg warning: In the September 2023 release, the default triplet for vcpkg libraries changed from x86-windows to the detected host triplet (x64-windows). For the old behavior, add --triplet x86-windows . To suppress this message, add --triplet x64-windows . C:\Dev\vcpkg\buildtrees\versioning_\versions\libwebp\a05e0de81085231df86f6902aba1e0a364e2ca7b\CONTROL:1:94: error: invalid character in feature name (must be lowercase, digits, '-', or '*') on expression: libwebp[anim, gif2webp, img2webp, info, mux, nearlossless, simd, cwebp, dwebp], libwebp[vwebp_sdl] (!osx), libwebp[extras] (!osx) ^ note: updating vcpkg by rerunning bootstrap-vcpkg may resolve this failure. PS C:\Dev\test> ``` --- include/vcpkg/base/message-data.inc.h | 3 --- src/vcpkg/portfileprovider.cpp | 27 +++++++++++---------------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 9582846fa0..5388f102bd 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -1238,9 +1238,6 @@ DECLARE_MESSAGE( "The control or manifest file for {package_name} could not be loaded due to the following error. Please " "remove {package_name} and try again.") DECLARE_MESSAGE(FailedToLoadManifest, (msg::path), "", "Failed to load manifest from directory {path}") -DECLARE_MESSAGE(FailedToLoadPort, (msg::package_name, msg::path), "", "Failed to load port {package_name} from {path}") -DECLARE_MESSAGE(FailedToLoadPortFrom, (msg::path), "", "Failed to load port from {path}") -DECLARE_MESSAGE(FailedToLoadUnnamedPortFromPath, (msg::path), "", "Failed to load port from {path}") DECLARE_MESSAGE(FailedToLocateSpec, (msg::spec), "", "Failed to locate spec in graph: {spec}") DECLARE_MESSAGE(FailedToObtainDependencyVersion, (), "", "Cannot find desired dependency version.") DECLARE_MESSAGE(FailedToObtainPackageVersion, (), "", "Cannot find desired package version.") diff --git a/src/vcpkg/portfileprovider.cpp b/src/vcpkg/portfileprovider.cpp index 4380e9164f..cabc1dcc65 100644 --- a/src/vcpkg/portfileprovider.cpp +++ b/src/vcpkg/portfileprovider.cpp @@ -209,10 +209,8 @@ namespace vcpkg { // This should change to a soft error when ParseExpected is eliminated. print_error_message(maybe_control_file.error()); - Checks::msg_exit_maybe_upgrade(VCPKG_LINE_INFO, - msgFailedToLoadPort, - msg::package_name = version_spec.port_name, - msg::path = path->path); + msg::println(); + Checks::exit_maybe_upgrade(VCPKG_LINE_INFO); } } else @@ -300,10 +298,8 @@ namespace vcpkg else { print_error_message(maybe_scf.error()); - Checks::msg_exit_maybe_upgrade(VCPKG_LINE_INFO, - msgFailedToLoadPort, - msg::package_name = port_name, - msg::path = ports_dir); + msg::println(); + Checks::exit_maybe_upgrade(VCPKG_LINE_INFO); } continue; @@ -322,8 +318,9 @@ namespace vcpkg Checks::msg_exit_maybe_upgrade( VCPKG_LINE_INFO, - msg::format(msgFailedToLoadPort, msg::package_name = port_name, msg::path = ports_spec) - .append_raw('\n') + LocalizedString::from_raw(ports_spec) + .append_raw(": ") + .append(msgErrorMessage) .append(msgMismatchedNames, msg::package_name = port_name, msg::actual = scfp->source_control_file->core_paragraph->name)); @@ -331,10 +328,8 @@ namespace vcpkg else { print_error_message(found_scf.error()); - Checks::msg_exit_maybe_upgrade(VCPKG_LINE_INFO, - msgFailedToLoadPort, - msg::package_name = port_name, - msg::path = ports_dir); + msg::println(); + Checks::exit_maybe_upgrade(VCPKG_LINE_INFO); } } } @@ -375,8 +370,8 @@ namespace vcpkg else { print_error_message(maybe_scf.error()); - Checks::msg_exit_maybe_upgrade( - VCPKG_LINE_INFO, msgFailedToLoadUnnamedPortFromPath, msg::path = ports_dir); + msg::println(); + Checks::exit_maybe_upgrade(VCPKG_LINE_INFO); } continue; From de7428c18b4bd8a58c1516d7d7252226279c5aa3 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 27 Sep 2023 17:08:26 -0700 Subject: [PATCH 16/48] Add a notice of which version we are loading back. --- include/vcpkg/base/message-data.inc.h | 1 + locales/messages.json | 8 ++------ src/vcpkg/portfileprovider.cpp | 8 ++++++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 5388f102bd..48f1ed7602 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -3140,6 +3140,7 @@ DECLARE_MESSAGE(WhileCheckingOutPortTreeIsh, "while checking out port {package_name} with git tree {commit_sha}") DECLARE_MESSAGE(WhileGettingLocalTreeIshObjectsForPorts, (), "", "while getting local treeish objects for ports") DECLARE_MESSAGE(WhileLookingForSpec, (msg::spec), "", "while looking for {spec}:") +DECLARE_MESSAGE(WhileLoadingPortVersion, (msg::version_spec), "", "while loading {version_spec}") DECLARE_MESSAGE(WhileParsingVersionsForPort, (msg::package_name, msg::path), "", diff --git a/locales/messages.json b/locales/messages.json index da0db24a82..b4762ae1ab 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -750,12 +750,6 @@ "_FailedToLoadInstalledManifest.comment": "An example of {package_name} is zlib.", "FailedToLoadManifest": "Failed to load manifest from directory {path}", "_FailedToLoadManifest.comment": "An example of {path} is /foo/bar.", - "FailedToLoadPort": "Failed to load port {package_name} from {path}", - "_FailedToLoadPort.comment": "An example of {package_name} is zlib. An example of {path} is /foo/bar.", - "FailedToLoadPortFrom": "Failed to load port from {path}", - "_FailedToLoadPortFrom.comment": "An example of {path} is /foo/bar.", - "FailedToLoadUnnamedPortFromPath": "Failed to load port from {path}", - "_FailedToLoadUnnamedPortFromPath.comment": "An example of {path} is /foo/bar.", "FailedToLocateSpec": "Failed to locate spec in graph: {spec}", "_FailedToLocateSpec.comment": "An example of {spec} is zlib:x64-windows.", "FailedToObtainDependencyVersion": "Cannot find desired dependency version.", @@ -1721,6 +1715,8 @@ "WhileCheckingOutPortTreeIsh": "while checking out port {package_name} with git tree {commit_sha}", "_WhileCheckingOutPortTreeIsh.comment": "An example of {package_name} is zlib. An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "WhileGettingLocalTreeIshObjectsForPorts": "while getting local treeish objects for ports", + "WhileLoadingPortVersion": "while loading {version_spec}", + "_WhileLoadingPortVersion.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0.", "WhileLookingForSpec": "while looking for {spec}:", "_WhileLookingForSpec.comment": "An example of {spec} is zlib:x64-windows.", "WhileParsingVersionsForPort": "while parsing versions for {package_name} from {path}", diff --git a/src/vcpkg/portfileprovider.cpp b/src/vcpkg/portfileprovider.cpp index cabc1dcc65..7e0ce78f1c 100644 --- a/src/vcpkg/portfileprovider.cpp +++ b/src/vcpkg/portfileprovider.cpp @@ -208,8 +208,12 @@ namespace vcpkg else { // This should change to a soft error when ParseExpected is eliminated. - print_error_message(maybe_control_file.error()); - msg::println(); + print_error_message( + maybe_control_file.error() + .append_raw('\n') + .append(msgNoteMessage) + .append(msgWhileLoadingPortVersion, msg::version_spec = version_spec) + .append_raw('\n')); Checks::exit_maybe_upgrade(VCPKG_LINE_INFO); } } From 68122ce93325edf6be6760e3c6a6eebb641c6711 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 28 Sep 2023 00:04:57 -0700 Subject: [PATCH 17/48] Fix crash while parsing malformed manifest files. Alternative to https://github.com/microsoft/vcpkg-tool/pull/1211 Fixes microsoft/vcpkg#33973 I'm not entirely happy with this because it emits extra 'mismatched type' warnings like $.dependencies[0].features[0]: mismatched type: expected a feature in a dependency . --- .../dependency-core-feature-name.json | 8 ++++ .../dependency-default-feature-name.json | 8 ++++ .../dependency-empty-feature-name.json | 8 ++++ .../dependency-empty-name.json | 3 ++ .../dependency-empty-object-name.json | 7 ++++ .../end-to-end-tests-dir/format-manifest.ps1 | 21 ++++++++++ include/vcpkg/base/message-data.inc.h | 14 +++++++ include/vcpkg/sourceparagraph.h | 8 ++-- locales/messages.json | 6 +++ src/vcpkg-test/plan.cpp | 2 +- src/vcpkg/commands.add.cpp | 2 +- src/vcpkg/commands.install.cpp | 1 + src/vcpkg/sourceparagraph.cpp | 39 ++++++++++++++----- 13 files changed, 112 insertions(+), 15 deletions(-) create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-core-feature-name.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-default-feature-name.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-feature-name.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-name.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-object-name.json diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-core-feature-name.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-core-feature-name.json new file mode 100644 index 0000000000..2e62e0c4ed --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-core-feature-name.json @@ -0,0 +1,8 @@ +{ + "dependencies": [ + { + "name": "icu", + "features": ["core"] + } + ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-default-feature-name.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-default-feature-name.json new file mode 100644 index 0000000000..9cd5f8a3f9 --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-default-feature-name.json @@ -0,0 +1,8 @@ +{ + "dependencies": [ + { + "name": "icu", + "features": ["default"] + } + ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-feature-name.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-feature-name.json new file mode 100644 index 0000000000..95601a0394 --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-feature-name.json @@ -0,0 +1,8 @@ +{ + "dependencies": [ + { + "name": "icu", + "features": [""] + } + ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-name.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-name.json new file mode 100644 index 0000000000..1d3b0858d5 --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-name.json @@ -0,0 +1,3 @@ +{ + "dependencies": [""] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-object-name.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-object-name.json new file mode 100644 index 0000000000..b97ebc46e8 --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-object-name.json @@ -0,0 +1,7 @@ +{ + "dependencies": [ + { + "name": "" + } + ] +} diff --git a/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 b/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 index 76d59e0540..35b5aa4db9 100644 --- a/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 @@ -1,5 +1,6 @@ . "$PSScriptRoot/../end-to-end-tests-prelude.ps1" +Write-Trace "test successfully parsing good inputs" $formatManifestAssets = (Get-Item "$PSScriptRoot/../e2e-assets/format-manifest").FullName $testProjects = Get-ChildItem "$formatManifestAssets/*.json" -File $testProjects | % { @@ -18,6 +19,26 @@ $testProjects | % { } } +Write-Trace "test not crashing parsing malformed inputs" +$formatManifestEvilAssets = (Get-Item "$PSScriptRoot/../e2e-assets/format-manifest-bad").FullName +$testEvilProjects = Get-ChildItem "$formatManifestEvilAssets/*.json" -File +$testEvilProjects | % { + $asItem = Get-Item $_ + $full = $asItem.FullName + Write-Trace "test that format-manifest on $full produces an error" + $output = Run-VcpkgAndCaptureOutput format-manifest $full + Throw-IfNotFailed + if ($output -match 'vcpkg has crashed') { + throw "vcpkg crashed parsing $full" + } + + $fullEscaped = [System.Text.RegularExpressions.Regex]::Escape($full) + if ($output -notmatch 'error: while loading ' + $fullEscaped ` + -or $output -notmatch 'error: Failed to parse manifest file: ' + $fullEscaped) { + throw "error not detected in $full" + } +} + Write-Trace "test re-serializing every manifest" $manifestDir = "$TestingRoot/manifest-dir" Copy-Item -Path "$env:VCPKG_ROOT/ports" -Destination $manifestDir -recurse -Force -Filter vcpkg.json diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 168d21f128..1da3723176 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -5,6 +5,7 @@ DECLARE_MESSAGE(ABuiltinRegistry, (), "", "a builtin registry") DECLARE_MESSAGE(AConfigurationObject, (), "", "a configuration object") DECLARE_MESSAGE(ADependency, (), "", "a dependency") DECLARE_MESSAGE(ADependencyFeature, (), "", "a feature in a dependency") +DECLARE_MESSAGE(ADependencyFeatureName, (), "", "the name of a feature of a dependency") DECLARE_MESSAGE(ADemandObject, (), "'demands' are a concept in the schema of a JSON file the user can edit", @@ -994,6 +995,19 @@ DECLARE_MESSAGE(DeleteVcpkgConfigFromManifest, (msg::path), "", "-- Or remove \"vcpkg-configuration\" from the manifest file {path}.") +DECLARE_MESSAGE(DependencyCoreFeature, + (), + "The word 'core' is an on-disk name that must not be localized. The 'default-features' part is JSON " + "syntax that must be copied verbatim into the user's file.", + "The feature 'core' cannot be in a dependency's feature list. To turn off default features, add " + "\"default-features\": false instead.") +DECLARE_MESSAGE(DependencyDefaultFeature, + (), + "The word 'default' is an on-disk name that must not be localized. The 'default-features' part is JSON " + "syntax that must be copied verbatim into the user's file.", + "The feature 'default' cannot be in a dependency's feature list. To turn on default features, add " + "\"default-features\": true instead.") +DECLARE_MESSAGE(DependencyEmptyFeature, (), "", "the name of a dependent feature can't be empty.") DECLARE_MESSAGE(DependencyGraphCalculation, (), "", "Dependency graph submission enabled.") DECLARE_MESSAGE(DependencyGraphFailure, (), "", "Dependency graph submission failed.") DECLARE_MESSAGE(DependencyGraphSuccess, (), "", "Dependency graph submission successful.") diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index fd2d0c3eae..fbbd9bf43f 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -41,12 +41,12 @@ namespace vcpkg { std::string name; PlatformExpression::Expr platform; - DependencyRequestedFeature(std::string name) - : DependencyRequestedFeature(std::move(name), PlatformExpression::Expr::Empty()) + DependencyRequestedFeature(const std::string& name) + : DependencyRequestedFeature(name, PlatformExpression::Expr::Empty()) { } - DependencyRequestedFeature(std::string name, PlatformExpression::Expr platform) - : name(std::move(name)), platform(std::move(platform)) + DependencyRequestedFeature(const std::string& name, PlatformExpression::Expr&& platform) + : name(name), platform(std::move(platform)) { Checks::check_exit(VCPKG_LINE_INFO, !this->name.empty() && this->name != "core" && this->name != "default"); } diff --git a/locales/messages.json b/locales/messages.json index a5d60e5f45..77dd57c32f 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -9,6 +9,7 @@ "_ADemandObject.comment": "'demands' are a concept in the schema of a JSON file the user can edit", "ADependency": "a dependency", "ADependencyFeature": "a feature in a dependency", + "ADependencyFeatureName": "the name of a feature of a dependency", "ADictionaryOfContacts": "a dictionary of contacts", "AFeature": "a feature", "AFilesystemRegistry": "a filesystem registry", @@ -581,6 +582,11 @@ "_DefaultTripletChanged.comment": "The parts naming --triplet are command line switches that should be unlocalized. The space after the last 'triplet' and the period is intended to avoid the period looking like it's part of the command line switch An example of {triplet} is x64-windows.", "DeleteVcpkgConfigFromManifest": "-- Or remove \"vcpkg-configuration\" from the manifest file {path}.", "_DeleteVcpkgConfigFromManifest.comment": "An example of {path} is /foo/bar.", + "DependencyCoreFeature": "The feature 'core' cannot be in a dependency's feature list. To turn off default features, add \"default-features\": false instead.", + "_DependencyCoreFeature.comment": "The word 'core' is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", + "DependencyDefaultFeature": "The feature 'default' cannot be in a dependency's feature list. To turn on default features, add \"default-features\": true instead.", + "_DependencyDefaultFeature.comment": "The word 'default' is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", + "DependencyEmptyFeature": "the name of a dependent feature can't be empty.", "DependencyGraphCalculation": "Dependency graph submission enabled.", "DependencyGraphFailure": "Dependency graph submission failed.", "DependencyGraphSuccess": "Dependency graph submission successful.", diff --git a/src/vcpkg-test/plan.cpp b/src/vcpkg-test/plan.cpp index 2666931345..f5e9759d1f 100644 --- a/src/vcpkg-test/plan.cpp +++ b/src/vcpkg-test/plan.cpp @@ -459,7 +459,7 @@ TEST_CASE ("install platform dependent default features", "[plan]") using MBO = PlatformExpression::MultipleBinaryOperators; auto linux_expr = PlatformExpression::parse_platform_expression("linux", MBO::Deny).value_or_exit(VCPKG_LINE_INFO); spec_map.map["a"].source_control_file->core_paragraph->default_features = { - DependencyRequestedFeature{"1", linux_expr}}; + DependencyRequestedFeature{"1", std::move(linux_expr)}}; MapPortFileProvider map_port{spec_map.map}; MockCMakeVarProvider var_provider; diff --git a/src/vcpkg/commands.add.cpp b/src/vcpkg/commands.add.cpp index c3244a2d1e..e860bba668 100644 --- a/src/vcpkg/commands.add.cpp +++ b/src/vcpkg/commands.add.cpp @@ -110,7 +110,7 @@ namespace vcpkg return dep.name == spec.name && !dep.host && structurally_equal(spec.platform.value_or(PlatformExpression::Expr()), dep.platform); }); - const auto features = Util::fmap(spec.features.value_or({}), [](auto& feature) { + const auto features = Util::fmap(spec.features.value_or({}), [](const std::string& feature) { return DependencyRequestedFeature{feature, PlatformExpression::Expr::Empty()}; }); if (dep == manifest_scf.core_paragraph->dependencies.end()) diff --git a/src/vcpkg/commands.install.cpp b/src/vcpkg/commands.install.cpp index 6c333d2c1f..62f213a52a 100644 --- a/src/vcpkg/commands.install.cpp +++ b/src/vcpkg/commands.install.cpp @@ -1105,6 +1105,7 @@ namespace vcpkg if (!maybe_manifest_scf) { print_error_message(maybe_manifest_scf.error()); + msg::println(); msg::println(msgExtendedDocumentationAtUrl, msg::url = docs::manifests_url); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 3cab387036..655dd1e95c 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -81,10 +81,7 @@ namespace vcpkg bool operator==(const DependencyRequestedFeature& lhs, const DependencyRequestedFeature& rhs) { - if (lhs.name != rhs.name) return false; - if (!structurally_equal(lhs.platform, rhs.platform)) return false; - - return true; + return lhs.name == rhs.name && structurally_equal(lhs.platform, rhs.platform); } bool operator!=(const DependencyRequestedFeature& lhs, const DependencyRequestedFeature& rhs) @@ -374,8 +371,8 @@ namespace vcpkg auto maybe_default_features = parse_default_features_list(buf, origin, textrowcol); if (const auto default_features = maybe_default_features.get()) { - spgh->default_features = - Util::fmap(*default_features, [](const auto& name) { return DependencyRequestedFeature{name}; }); + spgh->default_features = Util::fmap( + *default_features, [](const std::string& feature) { return DependencyRequestedFeature{feature}; }); } else { @@ -494,6 +491,30 @@ namespace vcpkg }; const PlatformExprDeserializer PlatformExprDeserializer::instance; + struct DependencyFeatureNameDeserializer : Json::IDeserializer + { + virtual LocalizedString type_name() const override { return msg::format(msgADependencyFeatureName); } + virtual Optional visit_string(Json::Reader& r, StringView sv) const override + { + if (sv == "core") + { + r.add_generic_error(type_name(), msg::format(msgDependencyCoreFeature)); + return nullopt; + } + + if (sv == "default") + { + r.add_generic_error(type_name(), msg::format(msgDependencyDefaultFeature)); + return nullopt; + } + + return Json::IdentifierDeserializer::instance.visit_string(r, sv); + } + static const DependencyFeatureNameDeserializer instance; + }; + + const DependencyFeatureNameDeserializer DependencyFeatureNameDeserializer::instance; + struct DependencyFeatureDeserializer : Json::IDeserializer { LocalizedString type_name() const override { return msg::format(msgADependencyFeature); } @@ -512,15 +533,15 @@ namespace vcpkg Optional visit_string(Json::Reader& r, StringView sv) const override { - return Json::IdentifierDeserializer::instance.visit_string(r, sv).map( - [](std::string&& name) { return std::move(name); }); + return DependencyFeatureNameDeserializer::instance.visit_string(r, sv).map( + [](std::string&& name) -> DependencyRequestedFeature { return std::move(name); }); } Optional visit_object(Json::Reader& r, const Json::Object& obj) const override { std::string name; PlatformExpression::Expr platform; - r.required_object_field(type_name(), obj, NAME, name, Json::IdentifierDeserializer::instance); + r.required_object_field(type_name(), obj, NAME, name, DependencyFeatureNameDeserializer::instance); r.optional_object_field(obj, PLATFORM, platform, PlatformExprDeserializer::instance); if (name.empty()) return nullopt; return DependencyRequestedFeature{std::move(name), std::move(platform)}; From b04a5b2146171a766ad0c41986874da22c04bfe9 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 28 Sep 2023 17:19:13 -0700 Subject: [PATCH 18/48] Remove semantic constraints on the deserialized type and add specific errors. --- .../default-feature-core-object.json | 3 + .../default-feature-core.json | 3 + .../default-feature-default-object.json | 3 + .../default-feature-default.json | 3 + .../default-feature-empty-object.json | 3 + .../default-feature-empty.json | 3 + .../dependency-core-feature-name.json | 8 -- .../dependency-default-feature-name.json | 8 -- .../dependency-empty-feature-name.json | 8 -- .../dependency-empty-name.json | 3 - .../dependency-empty-object-name.json | 7 -- .../dependency-feature-name-core-object.json | 12 ++ .../dependency-feature-name-core.json | 8 ++ ...ependency-feature-name-default-object.json | 8 ++ .../dependency-feature-name-default.json | 8 ++ .../dependency-feature-name-empty-object.json | 8 ++ .../dependency-feature-name-empty.json | 8 ++ .../dependency-name-empty-object.json | 7 ++ .../dependency-name-empty.json | 3 + .../end-to-end-tests-dir/format-manifest.ps1 | 4 + include/vcpkg/base/message-data.inc.h | 17 ++- include/vcpkg/base/messages.h | 29 +++-- include/vcpkg/sourceparagraph.h | 1 - locales/messages.json | 14 ++- src/vcpkg/base/messages.cpp | 23 +++- src/vcpkg/commands.add.cpp | 1 + src/vcpkg/sourceparagraph.cpp | 105 ++++++++++++++++-- 27 files changed, 245 insertions(+), 63 deletions(-) create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core-object.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default-object.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty-object.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-core-feature-name.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-default-feature-name.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-feature-name.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-name.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-object-name.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core-object.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default-object.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty-object.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty-object.json create mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty.json diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core-object.json new file mode 100644 index 0000000000..c03140f6d1 --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core-object.json @@ -0,0 +1,3 @@ +{ + "default-features": [ { "name": "core" } ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core.json new file mode 100644 index 0000000000..f282a980da --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core.json @@ -0,0 +1,3 @@ +{ + "default-features": ["core"] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default-object.json new file mode 100644 index 0000000000..2ab3418fb9 --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default-object.json @@ -0,0 +1,3 @@ +{ + "default-features": [ { "name": "default" } ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default.json new file mode 100644 index 0000000000..dff94b4653 --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default.json @@ -0,0 +1,3 @@ +{ + "default-features": [ "default" ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty-object.json new file mode 100644 index 0000000000..1be2afc05a --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty-object.json @@ -0,0 +1,3 @@ +{ + "default-features": [ { "name": "" } ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty.json new file mode 100644 index 0000000000..039729c4e3 --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty.json @@ -0,0 +1,3 @@ +{ + "default-features": [ "" ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-core-feature-name.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-core-feature-name.json deleted file mode 100644 index 2e62e0c4ed..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-core-feature-name.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": [ - { - "name": "icu", - "features": ["core"] - } - ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-default-feature-name.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-default-feature-name.json deleted file mode 100644 index 9cd5f8a3f9..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-default-feature-name.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": [ - { - "name": "icu", - "features": ["default"] - } - ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-feature-name.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-feature-name.json deleted file mode 100644 index 95601a0394..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-feature-name.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": [ - { - "name": "icu", - "features": [""] - } - ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-name.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-name.json deleted file mode 100644 index 1d3b0858d5..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-name.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "dependencies": [""] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-object-name.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-object-name.json deleted file mode 100644 index b97ebc46e8..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-empty-object-name.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "dependencies": [ - { - "name": "" - } - ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core-object.json new file mode 100644 index 0000000000..1053f4142d --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core-object.json @@ -0,0 +1,12 @@ +{ + "dependencies": [ + { + "name": "icu", + "features": [ + { + "name": "core" + } + ] + } + ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core.json new file mode 100644 index 0000000000..4bcfa72295 --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core.json @@ -0,0 +1,8 @@ +{ + "dependencies": [ + { + "name": "icu", + "features": [ "core" ] + } + ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default-object.json new file mode 100644 index 0000000000..4bc6ef701e --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default-object.json @@ -0,0 +1,8 @@ +{ + "dependencies": [ + { + "name": "icu", + "features": [ { "name": "default" } ] + } + ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default.json new file mode 100644 index 0000000000..2b11a8e76a --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default.json @@ -0,0 +1,8 @@ +{ + "dependencies": [ + { + "name": "icu", + "features": [ "default" ] + } + ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty-object.json new file mode 100644 index 0000000000..2df194319e --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty-object.json @@ -0,0 +1,8 @@ +{ + "dependencies": [ + { + "name": "icu", + "features": [ { "name": "" } ] + } + ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty.json new file mode 100644 index 0000000000..633075ddd0 --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty.json @@ -0,0 +1,8 @@ +{ + "dependencies": [ + { + "name": "icu", + "features": [ "" ] + } + ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty-object.json new file mode 100644 index 0000000000..ad60fea9be --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty-object.json @@ -0,0 +1,7 @@ +{ + "dependencies": [ + { + "name": "" + } + ] +} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty.json new file mode 100644 index 0000000000..c55282c391 --- /dev/null +++ b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty.json @@ -0,0 +1,3 @@ +{ + "dependencies": [ "" ] +} diff --git a/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 b/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 index 35b5aa4db9..67e6d71c1c 100644 --- a/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 @@ -37,6 +37,10 @@ $testEvilProjects | % { -or $output -notmatch 'error: Failed to parse manifest file: ' + $fullEscaped) { throw "error not detected in $full" } + + if ($output -match 'mismatched type:') { + throw "duplicate mismatched type error" + } } Write-Trace "test re-serializing every manifest" diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 1da3723176..61c9b9463e 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -1,5 +1,6 @@ DECLARE_MESSAGE(ABaseline, (), "", "a baseline") DECLARE_MESSAGE(ABaselineObject, (), "", "a baseline object") +DECLARE_MESSAGE(ADefaultFeature, (), "", "a default feature") DECLARE_MESSAGE(ABoolean, (), "", "a boolean") DECLARE_MESSAGE(ABuiltinRegistry, (), "", "a builtin registry") DECLARE_MESSAGE(AConfigurationObject, (), "", "a configuration object") @@ -124,6 +125,7 @@ DECLARE_MESSAGE(AmbiguousConfigDeleteConfigFile, "configuration file {path}") DECLARE_MESSAGE(AnArtifactsGitRegistryUrl, (), "", "an artifacts git registry URL") DECLARE_MESSAGE(AnArtifactsRegistry, (), "", "an artifacts registry") +DECLARE_MESSAGE(AnArrayOfDefaultFeatures, (), "", "an array of default features") DECLARE_MESSAGE(AnArrayOfDependencies, (), "", "an array of dependencies") DECLARE_MESSAGE(AnArrayOfDependencyOverrides, (), "", "an array of dependency overrides") DECLARE_MESSAGE(AnArrayOfFeatures, (), "", "an array of features") @@ -981,6 +983,16 @@ DECLARE_MESSAGE(DefaultBinaryCacheRequiresDirectory, (msg::path), "", "Environment variable VCPKG_DEFAULT_BINARY_CACHE must be a directory (was: {path})") +DECLARE_MESSAGE(DefaultFeatureCore, + (), + "The word 'core' is an on-disk name that must not be localized.", + "the feature 'core' turns off default features and thus can't be in the default features list") +DECLARE_MESSAGE( + DefaultFeatureDefault, + (), + "The word 'default' is an on-disk name that must not be localized.", + "the feature 'default' refers to the set of default features and thus can't be in the default features list") +DECLARE_MESSAGE(DefaultFeatureIdentifier, (), "", "the names of default features must be identifiers") DECLARE_MESSAGE(DefaultFlag, (msg::option), "", "Defaulting to --{option} being on.") DECLARE_MESSAGE(DefaultRegistryIsArtifact, (), "", "The default registry cannot be an artifact registry.") DECLARE_MESSAGE( @@ -995,19 +1007,18 @@ DECLARE_MESSAGE(DeleteVcpkgConfigFromManifest, (msg::path), "", "-- Or remove \"vcpkg-configuration\" from the manifest file {path}.") -DECLARE_MESSAGE(DependencyCoreFeature, +DECLARE_MESSAGE(DependencyFeatureCore, (), "The word 'core' is an on-disk name that must not be localized. The 'default-features' part is JSON " "syntax that must be copied verbatim into the user's file.", "The feature 'core' cannot be in a dependency's feature list. To turn off default features, add " "\"default-features\": false instead.") -DECLARE_MESSAGE(DependencyDefaultFeature, +DECLARE_MESSAGE(DependencyFeatureDefault, (), "The word 'default' is an on-disk name that must not be localized. The 'default-features' part is JSON " "syntax that must be copied verbatim into the user's file.", "The feature 'default' cannot be in a dependency's feature list. To turn on default features, add " "\"default-features\": true instead.") -DECLARE_MESSAGE(DependencyEmptyFeature, (), "", "the name of a dependent feature can't be empty.") DECLARE_MESSAGE(DependencyGraphCalculation, (), "", "Dependency graph submission enabled.") DECLARE_MESSAGE(DependencyGraphFailure, (), "", "Dependency graph submission failed.") DECLARE_MESSAGE(DependencyGraphSuccess, (), "", "Dependency graph submission successful.") diff --git a/include/vcpkg/base/messages.h b/include/vcpkg/base/messages.h index 5260b09dbc..980df1b6d7 100644 --- a/include/vcpkg/base/messages.h +++ b/include/vcpkg/base/messages.h @@ -84,27 +84,42 @@ namespace vcpkg static LocalizedString from_raw(std::basic_string&& s) noexcept; static LocalizedString from_raw(StringView s); - LocalizedString& append_raw(char c); - LocalizedString& append_raw(StringView s); + LocalizedString& append_raw(char c) &; + LocalizedString&& append_raw(char c) &&; + LocalizedString& append_raw(StringView s) &; + LocalizedString&& append_raw(StringView s) &&; template().to_string(std::declval()))> - LocalizedString& append_raw(const T& s) + LocalizedString& append_raw(const T& s) & { s.to_string(m_data); return *this; } - LocalizedString& append(const LocalizedString& s); + template().to_string(std::declval()))> + LocalizedString&& append_raw(const T& s) && + { + return std::move(append_raw(s)); + } + LocalizedString& append(const LocalizedString& s) &; + LocalizedString&& append(const LocalizedString& s) &&; template - LocalizedString& append(VCPKG_DECL_MSG_ARGS) + LocalizedString& append(VCPKG_DECL_MSG_ARGS) & { msg::format_to(*this, VCPKG_EXPAND_MSG_ARGS); return *this; } - LocalizedString& append_indent(size_t indent = 1); + template + LocalizedString&& append(VCPKG_DECL_MSG_ARGS) && + { + return std::move(append(VCPKG_EXPAND_MSG_ARGS)); + } + LocalizedString& append_indent(size_t indent = 1) &; + LocalizedString&& append_indent(size_t indent = 1) &&; // 0 items - Does nothing // 1 item - .append_raw(' ').append(item) // 2+ items - foreach: .append_raw('\n').append_indent(indent).append(item) - LocalizedString& append_floating_list(int indent, View items); + LocalizedString& append_floating_list(int indent, View items) &; + LocalizedString&& append_floating_list(int indent, View items) &&; friend bool operator==(const LocalizedString& lhs, const LocalizedString& rhs) noexcept; friend bool operator!=(const LocalizedString& lhs, const LocalizedString& rhs) noexcept; friend bool operator<(const LocalizedString& lhs, const LocalizedString& rhs) noexcept; diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index fbbd9bf43f..2f6524c751 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -48,7 +48,6 @@ namespace vcpkg DependencyRequestedFeature(const std::string& name, PlatformExpression::Expr&& platform) : name(name), platform(std::move(platform)) { - Checks::check_exit(VCPKG_LINE_INFO, !this->name.empty() && this->name != "core" && this->name != "default"); } friend bool operator==(const DependencyRequestedFeature& lhs, const DependencyRequestedFeature& rhs); friend bool operator!=(const DependencyRequestedFeature& lhs, const DependencyRequestedFeature& rhs); diff --git a/locales/messages.json b/locales/messages.json index 77dd57c32f..2039451fb8 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -575,6 +575,11 @@ "_DefaultBinaryCacheRequiresAbsolutePath.comment": "An example of {path} is /foo/bar.", "DefaultBinaryCacheRequiresDirectory": "Environment variable VCPKG_DEFAULT_BINARY_CACHE must be a directory (was: {path})", "_DefaultBinaryCacheRequiresDirectory.comment": "An example of {path} is /foo/bar.", + "DefaultFeatureCore": "the feature 'core' turns off default features and thus can't be in the default features list", + "_DefaultFeatureCore.comment": "The word 'core' is an on-disk name that must not be localized.", + "DefaultFeatureDefault": "the feature 'default' refers to the set of default features and thus can't be in the default features list", + "_DefaultFeatureDefault.comment": "The word 'default' is an on-disk name that must not be localized.", + "DefaultFeatureIdentifier": "the names of default features must be identifiers", "DefaultFlag": "Defaulting to --{option} being on.", "_DefaultFlag.comment": "An example of {option} is editable.", "DefaultRegistryIsArtifact": "The default registry cannot be an artifact registry.", @@ -582,11 +587,10 @@ "_DefaultTripletChanged.comment": "The parts naming --triplet are command line switches that should be unlocalized. The space after the last 'triplet' and the period is intended to avoid the period looking like it's part of the command line switch An example of {triplet} is x64-windows.", "DeleteVcpkgConfigFromManifest": "-- Or remove \"vcpkg-configuration\" from the manifest file {path}.", "_DeleteVcpkgConfigFromManifest.comment": "An example of {path} is /foo/bar.", - "DependencyCoreFeature": "The feature 'core' cannot be in a dependency's feature list. To turn off default features, add \"default-features\": false instead.", - "_DependencyCoreFeature.comment": "The word 'core' is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", - "DependencyDefaultFeature": "The feature 'default' cannot be in a dependency's feature list. To turn on default features, add \"default-features\": true instead.", - "_DependencyDefaultFeature.comment": "The word 'default' is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", - "DependencyEmptyFeature": "the name of a dependent feature can't be empty.", + "DependencyFeatureCore": "The feature 'core' cannot be in a dependency's feature list. To turn off default features, add \"default-features\": false instead.", + "_DependencyFeatureCore.comment": "The word 'core' is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", + "DependencyFeatureDefault": "The feature 'default' cannot be in a dependency's feature list. To turn on default features, add \"default-features\": true instead.", + "_DependencyFeatureDefault.comment": "The word 'default' is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", "DependencyGraphCalculation": "Dependency graph submission enabled.", "DependencyGraphFailure": "Dependency graph submission failed.", "DependencyGraphSuccess": "Dependency graph submission successful.", diff --git a/src/vcpkg/base/messages.cpp b/src/vcpkg/base/messages.cpp index f7fba88f65..c2ca00e5d3 100644 --- a/src/vcpkg/base/messages.cpp +++ b/src/vcpkg/base/messages.cpp @@ -28,31 +28,39 @@ namespace vcpkg template LocalizedString LocalizedString::from_raw(std::basic_string&& s) noexcept; LocalizedString LocalizedString::from_raw(StringView s) { return LocalizedString(s); } - LocalizedString& LocalizedString::append_raw(char c) + LocalizedString& LocalizedString::append_raw(char c) & { m_data.push_back(c); return *this; } - LocalizedString& LocalizedString::append_raw(StringView s) + LocalizedString&& LocalizedString::append_raw(char c) && { return std::move(append_raw(c)); } + + LocalizedString& LocalizedString::append_raw(StringView s) & { m_data.append(s.begin(), s.size()); return *this; } - LocalizedString& LocalizedString::append(const LocalizedString& s) + LocalizedString&& LocalizedString::append_raw(StringView s) && { return std::move(append_raw(s)); } + + LocalizedString& LocalizedString::append(const LocalizedString& s) & { m_data.append(s.m_data); return *this; } - LocalizedString& LocalizedString::append_indent(size_t indent) + LocalizedString&& LocalizedString::append(const LocalizedString& s) && { return std::move(append(s)); } + + LocalizedString& LocalizedString::append_indent(size_t indent) & { m_data.append(indent * 2, ' '); return *this; } - LocalizedString& LocalizedString::append_floating_list(int indent, View items) + LocalizedString&& LocalizedString::append_indent(size_t indent) && { return std::move(append_indent(indent)); } + + LocalizedString& LocalizedString::append_floating_list(int indent, View items) & { switch (items.size()) { @@ -70,6 +78,11 @@ namespace vcpkg return *this; } + LocalizedString&& LocalizedString::append_floating_list(int indent, View items) && + { + return std::move(append_floating_list(indent, items)); + } + bool operator==(const LocalizedString& lhs, const LocalizedString& rhs) noexcept { return lhs.data() == rhs.data(); diff --git a/src/vcpkg/commands.add.cpp b/src/vcpkg/commands.add.cpp index e860bba668..62d0c5a109 100644 --- a/src/vcpkg/commands.add.cpp +++ b/src/vcpkg/commands.add.cpp @@ -111,6 +111,7 @@ namespace vcpkg structurally_equal(spec.platform.value_or(PlatformExpression::Expr()), dep.platform); }); const auto features = Util::fmap(spec.features.value_or({}), [](const std::string& feature) { + Checks::check_exit(VCPKG_LINE_INFO, !feature.empty() && feature != "core" && feature != "default"); return DependencyRequestedFeature{feature, PlatformExpression::Expr::Empty()}; }); if (dep == manifest_scf.core_paragraph->dependencies.end()) diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 655dd1e95c..07e810939c 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -371,8 +371,31 @@ namespace vcpkg auto maybe_default_features = parse_default_features_list(buf, origin, textrowcol); if (const auto default_features = maybe_default_features.get()) { - spgh->default_features = Util::fmap( - *default_features, [](const std::string& feature) { return DependencyRequestedFeature{feature}; }); + for (auto&& default_feature : *default_features) + { + if (default_feature == "core") + { + return ParseControlErrorInfo::from_error(origin, msg::format_error(msgDefaultFeatureCore)); + } + + if (default_feature == "default") + { + return ParseControlErrorInfo::from_error(origin, msg::format_error(msgDefaultFeatureDefault)); + } + + if (!Json::IdentifierDeserializer::is_ident(default_feature)) + { + return ParseControlErrorInfo::from_error(origin, + msg::format_error(msgDefaultFeatureIdentifier) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgParseIdentifierError, + msg::value = default_feature, + msg::url = docs::manifests_url)); + } + + spgh->default_features.emplace_back(std::move(default_feature)); + } } else { @@ -491,6 +514,73 @@ namespace vcpkg }; const PlatformExprDeserializer PlatformExprDeserializer::instance; + struct DefaultFeatureNameDeserializer : Json::IDeserializer + { + virtual LocalizedString type_name() const override { return msg::format(msgADefaultFeature); } + virtual Optional visit_string(Json::Reader& r, StringView sv) const override + { + if (sv == "core") + { + r.add_generic_error(type_name(), msg::format(msgDefaultFeatureCore)); + return sv.to_string(); + } + + if (sv == "default") + { + r.add_generic_error(type_name(), msg::format(msgDefaultFeatureDefault)); + return sv.to_string(); + } + + return Json::IdentifierDeserializer::instance.visit_string(r, sv); + } + static const DefaultFeatureNameDeserializer instance; + }; + + const DefaultFeatureNameDeserializer DefaultFeatureNameDeserializer::instance; + + struct DefaultFeatureDeserializer : Json::IDeserializer + { + LocalizedString type_name() const override { return msg::format(msgADefaultFeature); } + + constexpr static StringLiteral NAME = "name"; + constexpr static StringLiteral PLATFORM = "platform"; + + Span valid_fields() const override + { + static const StringView t[] = { + NAME, + PLATFORM, + }; + return t; + } + + Optional visit_string(Json::Reader& r, StringView sv) const override + { + return DefaultFeatureNameDeserializer::instance.visit_string(r, sv).map( + [](std::string&& name) -> DependencyRequestedFeature { return std::move(name); }); + } + + Optional visit_object(Json::Reader& r, const Json::Object& obj) const override + { + std::string name; + PlatformExpression::Expr platform; + r.required_object_field(type_name(), obj, NAME, name, DefaultFeatureNameDeserializer::instance); + r.optional_object_field(obj, PLATFORM, platform, PlatformExprDeserializer::instance); + return DependencyRequestedFeature{std::move(name), std::move(platform)}; + } + + const static DefaultFeatureDeserializer instance; + }; + const DefaultFeatureDeserializer DefaultFeatureDeserializer::instance; + + struct DefaultFeatureArrayDeserializer : Json::ArrayDeserializer + { + LocalizedString type_name() const override { return msg::format(msgAnArrayOfDefaultFeatures); } + + static const DefaultFeatureArrayDeserializer instance; + }; + const DefaultFeatureArrayDeserializer DefaultFeatureArrayDeserializer::instance; + struct DependencyFeatureNameDeserializer : Json::IDeserializer { virtual LocalizedString type_name() const override { return msg::format(msgADependencyFeatureName); } @@ -498,14 +588,14 @@ namespace vcpkg { if (sv == "core") { - r.add_generic_error(type_name(), msg::format(msgDependencyCoreFeature)); - return nullopt; + r.add_generic_error(type_name(), msg::format(msgDependencyFeatureCore)); + return sv.to_string(); } if (sv == "default") { - r.add_generic_error(type_name(), msg::format(msgDependencyDefaultFeature)); - return nullopt; + r.add_generic_error(type_name(), msg::format(msgDependencyFeatureDefault)); + return sv.to_string(); } return Json::IdentifierDeserializer::instance.visit_string(r, sv); @@ -543,7 +633,6 @@ namespace vcpkg PlatformExpression::Expr platform; r.required_object_field(type_name(), obj, NAME, name, DependencyFeatureNameDeserializer::instance); r.optional_object_field(obj, PLATFORM, platform, PlatformExprDeserializer::instance); - if (name.empty()) return nullopt; return DependencyRequestedFeature{std::move(name), std::move(platform)}; } @@ -1196,7 +1285,7 @@ namespace vcpkg r.optional_object_field(obj, SUPPORTS, spgh.supports_expression, PlatformExprDeserializer::instance); r.optional_object_field( - obj, DEFAULT_FEATURES, spgh.default_features, DependencyFeatureArrayDeserializer::instance); + obj, DEFAULT_FEATURES, spgh.default_features, DefaultFeatureArrayDeserializer::instance); FeaturesObject features_tmp; r.optional_object_field(obj, FEATURES, features_tmp, FeaturesFieldDeserializer::instance); From 38f738d8100a9119d08bf640fca4d5dceaef15ee Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 28 Sep 2023 17:44:45 -0700 Subject: [PATCH 19/48] Code review feedback --- include/vcpkg/paragraphs.h | 4 ++-- include/vcpkg/registries.h | 2 +- include/vcpkg/sourceparagraph.h | 7 ++----- src/vcpkg-test/manifests.cpp | 6 +++--- src/vcpkg/binaryparagraph.cpp | 2 +- src/vcpkg/commands.add.cpp | 2 +- src/vcpkg/commands.build.cpp | 2 +- src/vcpkg/commands.format-manifest.cpp | 5 ++--- src/vcpkg/commands.install.cpp | 2 +- src/vcpkg/sourceparagraph.cpp | 21 ++++++++++++--------- 10 files changed, 26 insertions(+), 27 deletions(-) diff --git a/include/vcpkg/paragraphs.h b/include/vcpkg/paragraphs.h index 00c93261d0..8e12aa80c4 100644 --- a/include/vcpkg/paragraphs.h +++ b/include/vcpkg/paragraphs.h @@ -27,8 +27,8 @@ namespace vcpkg::Paragraphs bool is_port_directory(const ReadOnlyFilesystem& fs, const Path& maybe_directory); // If an error occurs, the Expected will be in the error state. - // Otherwise, if the port is known, the Optional contains the loaded port information. - // Otherwise, the Optional is disengaged. + // Otherwise, if the port is known, the unique_ptr contains the loaded port information. + // Otherwise, the unique_ptr is nullptr. ExpectedL> try_load_port(const ReadOnlyFilesystem& fs, StringView port_name, const Path& port_directory); diff --git a/include/vcpkg/registries.h b/include/vcpkg/registries.h index de08cb421a..00c4996d90 100644 --- a/include/vcpkg/registries.h +++ b/include/vcpkg/registries.h @@ -87,7 +87,7 @@ namespace vcpkg // Appends the names of the ports to the out parameter if this can be known without // network access. - // Returns true iff names were appended. + // Returns true iff names were checked without network access. virtual ExpectedL try_append_all_port_names_no_network(std::vector& port_names) const = 0; // If an error occurs, the ExpectedL will be in an error state. diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index 77a02aa64a..bc849e0e95 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -214,11 +214,8 @@ namespace vcpkg std::string registry_location; }; - void print_error_message(View error_info_list); - inline void print_error_message(const LocalizedString& error_info_list) - { - return print_error_message({&error_info_list, 1}); - } + void print_error_message(const LocalizedString& message); + void print_error_message(const std::unique_ptr& error_info_list); std::string parse_spdx_license_expression(StringView sv, ParseMessages& messages); diff --git a/src/vcpkg-test/manifests.cpp b/src/vcpkg-test/manifests.cpp index 4ca7936de3..696a9fc88e 100644 --- a/src/vcpkg-test/manifests.cpp +++ b/src/vcpkg-test/manifests.cpp @@ -45,7 +45,7 @@ static ParseExpected test_parse_project_manifest(const Json:: auto res = SourceControlFile::parse_project_manifest_object("", obj, null_sink); if (!res.has_value() && print == PrintErrors::Yes) { - print_error_message(LocalizedString::from_raw(res.error()->to_string())); + print_error_message(res.error()); } return res; } @@ -56,7 +56,7 @@ static ParseExpected test_parse_port_manifest(const Json::Obj auto res = SourceControlFile::parse_port_manifest_object("", obj, null_sink); if (!res.has_value() && print == PrintErrors::Yes) { - print_error_message(LocalizedString::from_raw(res.error()->to_string())); + print_error_message(res.error()); } return res; } @@ -886,7 +886,7 @@ TEST_CASE ("manifest construct maximum", "[manifests]") auto res = SourceControlFile::parse_port_manifest_object("", object, null_sink); if (!res.has_value()) { - print_error_message(LocalizedString::from_raw(res.error()->to_string())); + print_error_message(res.error()); } REQUIRE(res.has_value()); REQUIRE(*res.get() != nullptr); diff --git a/src/vcpkg/binaryparagraph.cpp b/src/vcpkg/binaryparagraph.cpp index 212e13e9b3..b412fa9154 100644 --- a/src/vcpkg/binaryparagraph.cpp +++ b/src/vcpkg/binaryparagraph.cpp @@ -90,7 +90,7 @@ namespace vcpkg if (const auto err = parser.error_info(this->spec.to_string())) { msg::println_error(msgErrorParsingBinaryParagraph, msg::spec = this->spec); - print_error_message(LocalizedString::from_raw(err->to_string())); + print_error_message(err); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/commands.add.cpp b/src/vcpkg/commands.add.cpp index 34c413d92e..0f20db198f 100644 --- a/src/vcpkg/commands.add.cpp +++ b/src/vcpkg/commands.add.cpp @@ -99,7 +99,7 @@ namespace vcpkg auto pmanifest_scf = maybe_manifest_scf.get(); if (!pmanifest_scf) { - print_error_message(LocalizedString::from_raw(maybe_manifest_scf.error()->to_string())); + print_error_message(maybe_manifest_scf.error()); msg::println(Color::error, msg::msgSeeURL, msg::url = docs::manifests_url); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/commands.build.cpp b/src/vcpkg/commands.build.cpp index 284c688521..ab44210f65 100644 --- a/src/vcpkg/commands.build.cpp +++ b/src/vcpkg/commands.build.cpp @@ -1685,7 +1685,7 @@ namespace vcpkg if (const auto err = parser.error_info("PostBuildInformation")) { - print_error_message(LocalizedString::from_raw(err->to_string())); + print_error_message(err); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/commands.format-manifest.cpp b/src/vcpkg/commands.format-manifest.cpp index be23ab175b..f4d04a031a 100644 --- a/src/vcpkg/commands.format-manifest.cpp +++ b/src/vcpkg/commands.format-manifest.cpp @@ -49,8 +49,7 @@ namespace if (!scf) { msg::println_error(msgFailedToParseManifest, msg::path = path_string); - print_error_message(LocalizedString::from_raw(scf.error()->to_string())); - msg::println(); + print_error_message(scf.error()); return nullopt; } @@ -82,7 +81,7 @@ namespace if (!scf_res) { msg::println_error(msgFailedToParseControl, msg::path = control_path); - print_error_message(LocalizedString::from_raw(scf_res.error()->to_string())); + print_error_message(scf_res.error()); return {}; } diff --git a/src/vcpkg/commands.install.cpp b/src/vcpkg/commands.install.cpp index 5755636079..6c333d2c1f 100644 --- a/src/vcpkg/commands.install.cpp +++ b/src/vcpkg/commands.install.cpp @@ -1104,7 +1104,7 @@ namespace vcpkg SourceControlFile::parse_project_manifest_object(manifest->path, manifest->manifest, stdout_sink); if (!maybe_manifest_scf) { - print_error_message(LocalizedString::from_raw(maybe_manifest_scf.error()->to_string())); + print_error_message(maybe_manifest_scf.error()); msg::println(msgExtendedDocumentationAtUrl, msg::url = docs::manifests_url); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 5e21d6a32e..3ecf6c4a88 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -185,8 +185,6 @@ namespace vcpkg return valid_fields; } - void print_error_message(Span> error_info_list); - static void trim_all(std::vector& arr) { for (auto& el : arr) @@ -1521,19 +1519,16 @@ namespace vcpkg return Strings::starts_with(sv, "Error") || Strings::starts_with(sv, "error: "); } - void print_error_message(View error_info_list) + void print_error_message(const LocalizedString& message) { - auto msg = Strings::join("\n", error_info_list, [](const LocalizedString& ls) { return ls.data(); }); - msg.push_back('\n'); - // To preserve previous behavior, each line starting with "Error" should be error-colored. All other lines // should be neutral color. // To minimize the number of print calls on Windows (which is a significant performance bottleneck), this // algorithm chunks groups of similarly-colored lines. - const char* start_of_chunk = msg.data(); - const char* end_of_chunk = msg.data(); - const char* const last = msg.data() + msg.size(); + const char* start_of_chunk = message.data().data(); + const char* end_of_chunk = start_of_chunk; + const char* const last = start_of_chunk + message.data().size(); while (end_of_chunk != last) { while (end_of_chunk != last && starts_with_error({end_of_chunk, last})) @@ -1556,6 +1551,14 @@ namespace vcpkg start_of_chunk = end_of_chunk; } } + + msg::println(); + } + + void print_error_message(const std::unique_ptr& error_info_list) + { + print_error_message(LocalizedString::from_raw( + ParseControlErrorInfo::format_errors(View>{&error_info_list, 1}))); } Optional SourceControlFile::find_feature(StringView featurename) const From 80fa91380acc966bbc8aaea4b2f1748073250889 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 28 Sep 2023 19:45:33 -0700 Subject: [PATCH 20/48] Make the e2e tests into unit tests and make the errors a bit prettier. --- .../default-feature-core-object.json | 3 - .../default-feature-core.json | 3 - .../default-feature-default-object.json | 3 - .../default-feature-default.json | 3 - .../default-feature-empty-object.json | 3 - .../default-feature-empty.json | 3 - .../dependency-feature-name-core-object.json | 12 - .../dependency-feature-name-core.json | 8 - ...ependency-feature-name-default-object.json | 8 - .../dependency-feature-name-default.json | 8 - .../dependency-feature-name-empty-object.json | 8 - .../dependency-feature-name-empty.json | 8 - .../dependency-name-empty-object.json | 7 - .../dependency-name-empty.json | 3 - .../end-to-end-tests-dir/format-manifest.ps1 | 25 -- include/vcpkg/base/jsonreader.h | 7 + include/vcpkg/base/message-data.inc.h | 54 +++-- include/vcpkg/sourceparagraph.h | 9 +- locales/messages.json | 31 +-- src/vcpkg-test/dependencies.cpp | 18 +- src/vcpkg-test/manifests.cpp | 213 ++++++++++++++++++ src/vcpkg-test/registries.cpp | 6 +- src/vcpkg/base/json.cpp | 15 ++ src/vcpkg/paragraphs.cpp | 2 +- src/vcpkg/sourceparagraph.cpp | 46 ++-- 25 files changed, 314 insertions(+), 192 deletions(-) delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core-object.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default-object.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty-object.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core-object.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default-object.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty-object.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty-object.json delete mode 100644 azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty.json diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core-object.json deleted file mode 100644 index c03140f6d1..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core-object.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "default-features": [ { "name": "core" } ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core.json deleted file mode 100644 index f282a980da..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-core.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "default-features": ["core"] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default-object.json deleted file mode 100644 index 2ab3418fb9..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default-object.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "default-features": [ { "name": "default" } ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default.json deleted file mode 100644 index dff94b4653..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-default.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "default-features": [ "default" ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty-object.json deleted file mode 100644 index 1be2afc05a..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty-object.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "default-features": [ { "name": "" } ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty.json b/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty.json deleted file mode 100644 index 039729c4e3..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/default-feature-empty.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "default-features": [ "" ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core-object.json deleted file mode 100644 index 1053f4142d..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core-object.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dependencies": [ - { - "name": "icu", - "features": [ - { - "name": "core" - } - ] - } - ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core.json deleted file mode 100644 index 4bcfa72295..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-core.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": [ - { - "name": "icu", - "features": [ "core" ] - } - ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default-object.json deleted file mode 100644 index 4bc6ef701e..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default-object.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": [ - { - "name": "icu", - "features": [ { "name": "default" } ] - } - ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default.json deleted file mode 100644 index 2b11a8e76a..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-default.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": [ - { - "name": "icu", - "features": [ "default" ] - } - ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty-object.json deleted file mode 100644 index 2df194319e..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty-object.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": [ - { - "name": "icu", - "features": [ { "name": "" } ] - } - ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty.json deleted file mode 100644 index 633075ddd0..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-feature-name-empty.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": [ - { - "name": "icu", - "features": [ "" ] - } - ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty-object.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty-object.json deleted file mode 100644 index ad60fea9be..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty-object.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "dependencies": [ - { - "name": "" - } - ] -} diff --git a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty.json b/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty.json deleted file mode 100644 index c55282c391..0000000000 --- a/azure-pipelines/e2e-assets/format-manifest-bad/dependency-name-empty.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "dependencies": [ "" ] -} diff --git a/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 b/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 index 67e6d71c1c..76d59e0540 100644 --- a/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/format-manifest.ps1 @@ -1,6 +1,5 @@ . "$PSScriptRoot/../end-to-end-tests-prelude.ps1" -Write-Trace "test successfully parsing good inputs" $formatManifestAssets = (Get-Item "$PSScriptRoot/../e2e-assets/format-manifest").FullName $testProjects = Get-ChildItem "$formatManifestAssets/*.json" -File $testProjects | % { @@ -19,30 +18,6 @@ $testProjects | % { } } -Write-Trace "test not crashing parsing malformed inputs" -$formatManifestEvilAssets = (Get-Item "$PSScriptRoot/../e2e-assets/format-manifest-bad").FullName -$testEvilProjects = Get-ChildItem "$formatManifestEvilAssets/*.json" -File -$testEvilProjects | % { - $asItem = Get-Item $_ - $full = $asItem.FullName - Write-Trace "test that format-manifest on $full produces an error" - $output = Run-VcpkgAndCaptureOutput format-manifest $full - Throw-IfNotFailed - if ($output -match 'vcpkg has crashed') { - throw "vcpkg crashed parsing $full" - } - - $fullEscaped = [System.Text.RegularExpressions.Regex]::Escape($full) - if ($output -notmatch 'error: while loading ' + $fullEscaped ` - -or $output -notmatch 'error: Failed to parse manifest file: ' + $fullEscaped) { - throw "error not detected in $full" - } - - if ($output -match 'mismatched type:') { - throw "duplicate mismatched type error" - } -} - Write-Trace "test re-serializing every manifest" $manifestDir = "$TestingRoot/manifest-dir" Copy-Item -Path "$env:VCPKG_ROOT/ports" -Destination $manifestDir -recurse -Force -Filter vcpkg.json diff --git a/include/vcpkg/base/jsonreader.h b/include/vcpkg/base/jsonreader.h index 24fda8d19e..e948ff3961 100644 --- a/include/vcpkg/base/jsonreader.h +++ b/include/vcpkg/base/jsonreader.h @@ -350,4 +350,11 @@ namespace vcpkg::Json virtual Optional visit_string(Json::Reader&, StringView sv) const override; static const PackageNameDeserializer instance; }; + + struct FeatureNameDeserializer final : Json::IDeserializer + { + virtual LocalizedString type_name() const override; + virtual Optional visit_string(Json::Reader&, StringView sv) const override; + static const FeatureNameDeserializer instance; + }; } diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 61c9b9463e..07e7499832 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -5,8 +5,7 @@ DECLARE_MESSAGE(ABoolean, (), "", "a boolean") DECLARE_MESSAGE(ABuiltinRegistry, (), "", "a builtin registry") DECLARE_MESSAGE(AConfigurationObject, (), "", "a configuration object") DECLARE_MESSAGE(ADependency, (), "", "a dependency") -DECLARE_MESSAGE(ADependencyFeature, (), "", "a feature in a dependency") -DECLARE_MESSAGE(ADependencyFeatureName, (), "", "the name of a feature of a dependency") +DECLARE_MESSAGE(ADependencyFeature, (), "", "a feature of a dependency") DECLARE_MESSAGE(ADemandObject, (), "'demands' are a concept in the schema of a JSON file the user can edit", @@ -96,6 +95,7 @@ DECLARE_MESSAGE(AddVersionVersionAlreadyInFile, (msg::version, msg::path), "", " DECLARE_MESSAGE(AddVersionVersionIs, (msg::version), "", "version: {version}") DECLARE_MESSAGE(ADictionaryOfContacts, (), "", "a dictionary of contacts") DECLARE_MESSAGE(AFeature, (), "", "a feature") +DECLARE_MESSAGE(AFeatureName, (), "", "a feature name") DECLARE_MESSAGE(AFilesystemRegistry, (), "", "a filesystem registry") DECLARE_MESSAGE(AGitObjectSha, (), "", "a git object SHA") DECLARE_MESSAGE(AGitReference, (), "", "a git reference (for example, a branch)") @@ -985,13 +985,13 @@ DECLARE_MESSAGE(DefaultBinaryCacheRequiresDirectory, "Environment variable VCPKG_DEFAULT_BINARY_CACHE must be a directory (was: {path})") DECLARE_MESSAGE(DefaultFeatureCore, (), - "The word 'core' is an on-disk name that must not be localized.", - "the feature 'core' turns off default features and thus can't be in the default features list") + "The word \"core\" is an on-disk name that must not be localized.", + "the feature \"core\" turns off default features and thus can't be in the default features list") DECLARE_MESSAGE( DefaultFeatureDefault, (), - "The word 'default' is an on-disk name that must not be localized.", - "the feature 'default' refers to the set of default features and thus can't be in the default features list") + "The word \"default\" is an on-disk name that must not be localized.", + "the feature \"default\" refers to the set of default features and thus can't be in the default features list") DECLARE_MESSAGE(DefaultFeatureIdentifier, (), "", "the names of default features must be identifiers") DECLARE_MESSAGE(DefaultFlag, (msg::option), "", "Defaulting to --{option} being on.") DECLARE_MESSAGE(DefaultRegistryIsArtifact, (), "", "The default registry cannot be an artifact registry.") @@ -1009,16 +1009,17 @@ DECLARE_MESSAGE(DeleteVcpkgConfigFromManifest, "-- Or remove \"vcpkg-configuration\" from the manifest file {path}.") DECLARE_MESSAGE(DependencyFeatureCore, (), - "The word 'core' is an on-disk name that must not be localized. The 'default-features' part is JSON " + "The word \"core\" is an on-disk name that must not be localized. The 'default-features' part is JSON " "syntax that must be copied verbatim into the user's file.", - "The feature 'core' cannot be in a dependency's feature list. To turn off default features, add " + "the feature \"core\" cannot be in a dependency's feature list. To turn off default features, add " "\"default-features\": false instead.") -DECLARE_MESSAGE(DependencyFeatureDefault, - (), - "The word 'default' is an on-disk name that must not be localized. The 'default-features' part is JSON " - "syntax that must be copied verbatim into the user's file.", - "The feature 'default' cannot be in a dependency's feature list. To turn on default features, add " - "\"default-features\": true instead.") +DECLARE_MESSAGE( + DependencyFeatureDefault, + (), + "The word \"default\" is an on-disk name that must not be localized. The 'default-features' part is JSON " + "syntax that must be copied verbatim into the user's file.", + "the feature \"default\" cannot be in a dependency's feature list. To turn on default features, add " + "\"default-features\": true instead.") DECLARE_MESSAGE(DependencyGraphCalculation, (), "", "Dependency graph submission enabled.") DECLARE_MESSAGE(DependencyGraphFailure, (), "", "Dependency graph submission failed.") DECLARE_MESSAGE(DependencyGraphSuccess, (), "", "Dependency graph submission successful.") @@ -1928,10 +1929,6 @@ DECLARE_MESSAGE(InvalidCommentStyle, "comments.") DECLARE_MESSAGE(InvalidCommitId, (msg::commit_sha), "", "Invalid commit id: {commit_sha}") DECLARE_MESSAGE(InvalidDefaultFeatureName, (), "", "'default' is a reserved feature name") -DECLARE_MESSAGE(InvalidDependency, - (), - "", - "dependencies must be lowercase alphanumeric+hyphens, and not one of the reserved names") DECLARE_MESSAGE(InvalidFeature, (), "", @@ -2294,22 +2291,29 @@ DECLARE_MESSAGE(ParseControlErrorInfoWhileLoading, "Error messages are is printed after this.", "while loading {path}:") DECLARE_MESSAGE(ParseControlErrorInfoWrongTypeFields, (), "", "The following fields had the wrong types:") +DECLARE_MESSAGE( + ParseFeatureNameError, + (msg::package_name, msg::url), + "", + "\"{package_name}\" is not a valid feature name. " + "Feature names must be lowercase alphanumeric+hypens and not reserved (see {url} for more information).") DECLARE_MESSAGE(ParseIdentifierError, (msg::value, msg::url), "{value} is a lowercase identifier like 'boost'", "\"{value}\" is not a valid identifier. " - "Identifiers must be lowercase alphanumeric+hypens and not reserved (see {url} for more information)") -DECLARE_MESSAGE(ParsePackageNameError, - (msg::package_name, msg::url), - "", - "\"{package_name}\" is not a valid package name. " - "Package names must be lowercase alphanumeric+hypens and not reserved (see {url} for more information)") + "Identifiers must be lowercase alphanumeric+hypens and not reserved (see {url} for more information).") +DECLARE_MESSAGE( + ParsePackageNameError, + (msg::package_name, msg::url), + "", + "\"{package_name}\" is not a valid package name. " + "Package names must be lowercase alphanumeric+hypens and not reserved (see {url} for more information).") DECLARE_MESSAGE(ParsePackagePatternError, (msg::package_name, msg::url), "", "\"{package_name}\" is not a valid package pattern. " "Package patterns must use only one wildcard character (*) and it must be the last character in " - "the pattern (see {url} for more information)") + "the pattern (see {url} for more information).") DECLARE_MESSAGE(PathMustBeAbsolute, (msg::path), "", diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index 2f6524c751..004da79113 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -41,14 +41,7 @@ namespace vcpkg { std::string name; PlatformExpression::Expr platform; - DependencyRequestedFeature(const std::string& name) - : DependencyRequestedFeature(name, PlatformExpression::Expr::Empty()) - { - } - DependencyRequestedFeature(const std::string& name, PlatformExpression::Expr&& platform) - : name(name), platform(std::move(platform)) - { - } + friend bool operator==(const DependencyRequestedFeature& lhs, const DependencyRequestedFeature& rhs); friend bool operator!=(const DependencyRequestedFeature& lhs, const DependencyRequestedFeature& rhs); }; diff --git a/locales/messages.json b/locales/messages.json index 2039451fb8..fbc50143d7 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -5,13 +5,14 @@ "ABuiltinRegistry": "a builtin registry", "AConfigurationObject": "a configuration object", "ADateVersionString": "a date version string", + "ADefaultFeature": "a default feature", "ADemandObject": "a demand object", "_ADemandObject.comment": "'demands' are a concept in the schema of a JSON file the user can edit", "ADependency": "a dependency", - "ADependencyFeature": "a feature in a dependency", - "ADependencyFeatureName": "the name of a feature of a dependency", + "ADependencyFeature": "a feature of a dependency", "ADictionaryOfContacts": "a dictionary of contacts", "AFeature": "a feature", + "AFeatureName": "a feature name", "AFilesystemRegistry": "a filesystem registry", "AGitObjectSha": "a git object SHA", "AGitReference": "a git reference (for example, a branch)", @@ -116,6 +117,7 @@ "_AlreadyInstalledNotHead.comment": "'HEAD' means the most recent version of source code An example of {spec} is zlib:x64-windows.", "AmbiguousConfigDeleteConfigFile": "Ambiguous vcpkg configuration provided by both manifest and configuration file.\n-- Delete configuration file {path}", "_AmbiguousConfigDeleteConfigFile.comment": "An example of {path} is /foo/bar.", + "AnArrayOfDefaultFeatures": "an array of default features", "AnArrayOfDependencies": "an array of dependencies", "AnArrayOfDependencyOverrides": "an array of dependency overrides", "AnArrayOfFeatures": "an array of features", @@ -575,10 +577,10 @@ "_DefaultBinaryCacheRequiresAbsolutePath.comment": "An example of {path} is /foo/bar.", "DefaultBinaryCacheRequiresDirectory": "Environment variable VCPKG_DEFAULT_BINARY_CACHE must be a directory (was: {path})", "_DefaultBinaryCacheRequiresDirectory.comment": "An example of {path} is /foo/bar.", - "DefaultFeatureCore": "the feature 'core' turns off default features and thus can't be in the default features list", - "_DefaultFeatureCore.comment": "The word 'core' is an on-disk name that must not be localized.", - "DefaultFeatureDefault": "the feature 'default' refers to the set of default features and thus can't be in the default features list", - "_DefaultFeatureDefault.comment": "The word 'default' is an on-disk name that must not be localized.", + "DefaultFeatureCore": "the feature \"core\" turns off default features and thus can't be in the default features list", + "_DefaultFeatureCore.comment": "The word \"core\" is an on-disk name that must not be localized.", + "DefaultFeatureDefault": "the feature \"default\" refers to the set of default features and thus can't be in the default features list", + "_DefaultFeatureDefault.comment": "The word \"default\" is an on-disk name that must not be localized.", "DefaultFeatureIdentifier": "the names of default features must be identifiers", "DefaultFlag": "Defaulting to --{option} being on.", "_DefaultFlag.comment": "An example of {option} is editable.", @@ -587,10 +589,10 @@ "_DefaultTripletChanged.comment": "The parts naming --triplet are command line switches that should be unlocalized. The space after the last 'triplet' and the period is intended to avoid the period looking like it's part of the command line switch An example of {triplet} is x64-windows.", "DeleteVcpkgConfigFromManifest": "-- Or remove \"vcpkg-configuration\" from the manifest file {path}.", "_DeleteVcpkgConfigFromManifest.comment": "An example of {path} is /foo/bar.", - "DependencyFeatureCore": "The feature 'core' cannot be in a dependency's feature list. To turn off default features, add \"default-features\": false instead.", - "_DependencyFeatureCore.comment": "The word 'core' is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", - "DependencyFeatureDefault": "The feature 'default' cannot be in a dependency's feature list. To turn on default features, add \"default-features\": true instead.", - "_DependencyFeatureDefault.comment": "The word 'default' is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", + "DependencyFeatureCore": "the feature \"core\" cannot be in a dependency's feature list. To turn off default features, add \"default-features\": false instead.", + "_DependencyFeatureCore.comment": "The word \"core\" is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", + "DependencyFeatureDefault": "the feature \"default\" cannot be in a dependency's feature list. To turn on default features, add \"default-features\": true instead.", + "_DependencyFeatureDefault.comment": "The word \"default\" is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", "DependencyGraphCalculation": "Dependency graph submission enabled.", "DependencyGraphFailure": "Dependency graph submission failed.", "DependencyGraphSuccess": "Dependency graph submission successful.", @@ -1086,7 +1088,6 @@ "InvalidCommitId": "Invalid commit id: {commit_sha}", "_InvalidCommitId.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "InvalidDefaultFeatureName": "'default' is a reserved feature name", - "InvalidDependency": "dependencies must be lowercase alphanumeric+hyphens, and not one of the reserved names", "InvalidFeature": "features must be lowercase alphanumeric+hyphens, and not one of the reserved names", "InvalidFileType": "failed: {path} cannot handle file type", "_InvalidFileType.comment": "An example of {path} is /foo/bar.", @@ -1322,11 +1323,13 @@ "ParseControlErrorInfoWhileLoading": "while loading {path}:", "_ParseControlErrorInfoWhileLoading.comment": "Error messages are is printed after this. An example of {path} is /foo/bar.", "ParseControlErrorInfoWrongTypeFields": "The following fields had the wrong types:", - "ParseIdentifierError": "\"{value}\" is not a valid identifier. Identifiers must be lowercase alphanumeric+hypens and not reserved (see {url} for more information)", + "ParseFeatureNameError": "\"{package_name}\" is not a valid feature name. Feature names must be lowercase alphanumeric+hypens and not reserved (see {url} for more information).", + "_ParseFeatureNameError.comment": "An example of {package_name} is zlib. An example of {url} is https://github.com/microsoft/vcpkg.", + "ParseIdentifierError": "\"{value}\" is not a valid identifier. Identifiers must be lowercase alphanumeric+hypens and not reserved (see {url} for more information).", "_ParseIdentifierError.comment": "{value} is a lowercase identifier like 'boost' An example of {url} is https://github.com/microsoft/vcpkg.", - "ParsePackageNameError": "\"{package_name}\" is not a valid package name. Package names must be lowercase alphanumeric+hypens and not reserved (see {url} for more information)", + "ParsePackageNameError": "\"{package_name}\" is not a valid package name. Package names must be lowercase alphanumeric+hypens and not reserved (see {url} for more information).", "_ParsePackageNameError.comment": "An example of {package_name} is zlib. An example of {url} is https://github.com/microsoft/vcpkg.", - "ParsePackagePatternError": "\"{package_name}\" is not a valid package pattern. Package patterns must use only one wildcard character (*) and it must be the last character in the pattern (see {url} for more information)", + "ParsePackagePatternError": "\"{package_name}\" is not a valid package pattern. Package patterns must use only one wildcard character (*) and it must be the last character in the pattern (see {url} for more information).", "_ParsePackagePatternError.comment": "An example of {package_name} is zlib. An example of {url} is https://github.com/microsoft/vcpkg.", "PathMustBeAbsolute": "Value of environment variable X_VCPKG_REGISTRIES_CACHE is not absolute: {path}", "_PathMustBeAbsolute.comment": "An example of {path} is /foo/bar.", diff --git a/src/vcpkg-test/dependencies.cpp b/src/vcpkg-test/dependencies.cpp index eef42ad3a7..e25623e8a6 100644 --- a/src/vcpkg-test/dependencies.cpp +++ b/src/vcpkg-test/dependencies.cpp @@ -1619,7 +1619,7 @@ TEST_CASE ("version install default features", "[versionplan]") auto a_x = make_fpgh("x"); auto& a_scf = vp.emplace("a", {"1", 0}, VersionScheme::Relaxed).source_control_file; - a_scf->core_paragraph->default_features.emplace_back("x"); + a_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"x"}); a_scf->feature_paragraphs.push_back(std::move(a_x)); MockCMakeVarProvider var_provider; @@ -1640,7 +1640,7 @@ TEST_CASE ("version dont install default features", "[versionplan]") auto a_x = make_fpgh("x"); auto& a_scf = vp.emplace("a", {"1", 0}, VersionScheme::Relaxed).source_control_file; - a_scf->core_paragraph->default_features.emplace_back("x"); + a_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"x"}); a_scf->feature_paragraphs.push_back(std::move(a_x)); MockCMakeVarProvider var_provider; @@ -1661,7 +1661,7 @@ TEST_CASE ("version install transitive default features", "[versionplan]") auto a_x = make_fpgh("x"); auto& a_scf = vp.emplace("a", {"1", 0}, VersionScheme::Relaxed).source_control_file; - a_scf->core_paragraph->default_features.emplace_back("x"); + a_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"x"}); a_scf->feature_paragraphs.push_back(std::move(a_x)); auto& b_scf = vp.emplace("b", {"1", 0}, VersionScheme::Relaxed).source_control_file; @@ -1752,7 +1752,7 @@ TEST_CASE ("version install qualified default suppression", "[versionplan]") MockVersionedPortfileProvider vp; auto& a_scf = vp.emplace("a", {"1", 0}, VersionScheme::Relaxed).source_control_file; - a_scf->core_paragraph->default_features.emplace_back("x"); + a_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"x"}); a_scf->feature_paragraphs.push_back(make_fpgh("x")); vp.emplace("b", {"1", 0}, VersionScheme::Relaxed) @@ -1837,17 +1837,17 @@ TEST_CASE ("version install qualified features", "[versionplan]") MockVersionedPortfileProvider vp; auto& b_scf = vp.emplace("b", {"1", 0}, VersionScheme::Relaxed).source_control_file; - b_scf->core_paragraph->default_features.emplace_back("x"); + b_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"x"}); b_scf->feature_paragraphs.push_back(make_fpgh("x")); b_scf->feature_paragraphs.back()->dependencies.push_back({"a", {}, parse_platform("!linux")}); auto& a_scf = vp.emplace("a", {"1", 0}, VersionScheme::Relaxed).source_control_file; - a_scf->core_paragraph->default_features.emplace_back("y"); + a_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"y"}); a_scf->feature_paragraphs.push_back(make_fpgh("y")); a_scf->feature_paragraphs.back()->dependencies.push_back({"c", {}, parse_platform("linux")}); auto& c_scf = vp.emplace("c", {"1", 0}, VersionScheme::Relaxed).source_control_file; - c_scf->core_paragraph->default_features.emplace_back("z"); + c_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"z"}); c_scf->feature_paragraphs.push_back(make_fpgh("z")); c_scf->feature_paragraphs.back()->dependencies.push_back({"d", {}, parse_platform("linux")}); @@ -2313,8 +2313,8 @@ TEST_CASE ("respect platform expressions in default features", "[versionplan]") a_x->name = "x"; auto& scf = vp.emplace("a", {"1", 0}).source_control_file; scf->feature_paragraphs.push_back(std::move(a_x)); - scf->core_paragraph->default_features.emplace_back( - "x", parse_platform_expression("linux", MultipleBinaryOperators::Deny).value_or_exit(VCPKG_LINE_INFO)); + scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{ + "x", parse_platform_expression("linux", MultipleBinaryOperators::Deny).value_or_exit(VCPKG_LINE_INFO)}); } MockCMakeVarProvider var_provider; diff --git a/src/vcpkg-test/manifests.cpp b/src/vcpkg-test/manifests.cpp index 696a9fc88e..9411dfb071 100644 --- a/src/vcpkg-test/manifests.cpp +++ b/src/vcpkg-test/manifests.cpp @@ -1263,3 +1263,216 @@ TEST_CASE ("license error messages", "[manifests][license]") on expression: MIT AND unknownlicense ^)"); } + +TEST_CASE ("default-feature-core errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "default-features": ["core"] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == "error: while loading :\n" + "$.default-features[0] (a default feature): the feature \"core\" turns off " + "default features and thus can't be in the default features list"); +} + +TEST_CASE ("default-feature-core-object errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "default-features": [ { "name": "core" } ] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == "error: while loading :\n" + "$.default-features[0].name (a default feature): the feature \"core\" turns " + "off default features and thus can't be in the default features list"); +} + +TEST_CASE ("default-feature-default errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "default-features": ["default"] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == + "error: while loading :\n" + "$.default-features[0] (a default feature): the feature \"default\" refers to " + "the set of default features and thus can't be in the default features list"); +} + +TEST_CASE ("default-feature-default-object errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "default-features": [ { "name": "default" } ] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == + "error: while loading :\n" + "$.default-features[0].name (a default feature): the feature \"default\" refers to the set of default " + "features and thus can't be in the default features list"); +} + +TEST_CASE ("default-feature-empty errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "default-features": [""] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == "error: while loading :\n" + "$.default-features[0] (a feature name): \"\" is not a valid feature name. " + "Feature names must be lowercase alphanumeric+hypens and not reserved (see " + "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); +} + +TEST_CASE ("default-feature-empty-object errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "default-features": [ { "name": "" } ] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == + "error: while loading :\n" + "$.default-features[0].name (a feature name): \"\" is not a valid feature name. " + "Feature names must be lowercase alphanumeric+hypens and not reserved (see " + "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); +} + +TEST_CASE ("dependency-name-empty errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "dependencies": [ "" ] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == "error: while loading :\n" + "$.dependencies[0] (a package name): \"\" is not a valid package name. " + "Package names must be lowercase alphanumeric+hypens and not reserved (see " + "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); +} + +TEST_CASE ("dependency-name-empty-object errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "dependencies": [ { "name": "" } ] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == "error: while loading :\n" + "$.dependencies[0].name (a package name): \"\" is not a valid package name. " + "Package names must be lowercase alphanumeric+hypens and not reserved (see " + "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); +} + +TEST_CASE ("dependency-feature-name-core errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "dependencies": [ + { + "name": "icu", + "features": [ "core" ] + } + ] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == + "error: while loading :\n" + "$.dependencies[0].features[0] (a feature name): the feature \"core\" cannot be in a dependency's feature " + "list. To turn off default features, add \"default-features\": false instead."); +} + +TEST_CASE ("dependency-feature-name-core-object errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "dependencies": [ + { + "name": "icu", + "features": [ { "name": "core" } ] + } + ] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE( + m_pgh.error()->to_string() == + "error: while loading :\n" + "$.dependencies[0].features[0].name (a feature name): the feature \"core\" cannot be in a dependency's feature " + "list. To turn off default features, add \"default-features\": false instead."); +} + +TEST_CASE ("dependency-feature-name-default errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "dependencies": [ + { + "name": "icu", + "features": [ "default" ] + } + ] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == + "error: while loading :\n" + "$.dependencies[0].features[0] (a feature name): the feature \"default\" cannot be in a dependency's " + "feature list. To turn on default features, add \"default-features\": true instead."); +} + +TEST_CASE ("dependency-feature-name-default-object errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "dependencies": [ + { + "name": "icu", + "features": [ { "name": "default" } ] + } + ] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == + "error: while loading :\n" + "$.dependencies[0].features[0].name (a feature name): the feature \"default\" cannot be in a dependency's " + "feature list. To turn on default features, add \"default-features\": true instead."); +} +TEST_CASE ("dependency-feature-name-empty errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "dependencies": [ + { + "name": "icu", + "features": [ "" ] + } + ] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == + "error: while loading :\n" + "$.dependencies[0].features[0] (a feature name): \"\" is not a valid feature name. Feature names must be " + "lowercase alphanumeric+hypens and not reserved (see https://learn.microsoft.com/vcpkg/users/manifests for " + "more information)."); +} + +TEST_CASE ("dependency-feature-name-empty-object errors", "[manifests]") +{ + auto m_pgh = test_parse_project_manifest(R"json({ + "dependencies": [ + { + "name": "icu", + "features": [ { "name": "" } ] + } + ] + })json", + PrintErrors::No); + REQUIRE(!m_pgh.has_value()); + REQUIRE(m_pgh.error()->to_string() == + "error: while loading :\n" + "$.dependencies[0].features[0].name (a feature name): \"\" is not a valid feature name. Feature names must " + "be lowercase alphanumeric+hypens and not reserved (see https://learn.microsoft.com/vcpkg/users/manifests " + "for more information)."); +} diff --git a/src/vcpkg-test/registries.cpp b/src/vcpkg-test/registries.cpp index 9c81680f24..e5fd422825 100644 --- a/src/vcpkg-test/registries.cpp +++ b/src/vcpkg-test/registries.cpp @@ -422,15 +422,15 @@ TEST_CASE ("registries report pattern errors", "[registries]") CHECK(errors[0] == "$.registries[0].packages[1] (a package pattern): \"\" is not a valid package pattern. Package patterns must " "use only one wildcard character (*) and it must be the last character in the pattern (see " - "https://learn.microsoft.com/vcpkg/users/registries for more information)"); + "https://learn.microsoft.com/vcpkg/users/registries for more information)."); CHECK(errors[1] == "$.registries[0].packages[2] (a package pattern): \"a*a\" is not a valid package pattern. Package patterns " "must use only one wildcard character (*) and it must be the last character in the pattern (see " - "https://learn.microsoft.com/vcpkg/users/registries for more information)"); + "https://learn.microsoft.com/vcpkg/users/registries for more information)."); CHECK(errors[2] == "$.registries[0].packages[3] (a package pattern): \"*a\" is not a valid package pattern. Package patterns " "must use only one wildcard character (*) and it must be the last character in the pattern (see " - "https://learn.microsoft.com/vcpkg/users/registries for more information)"); + "https://learn.microsoft.com/vcpkg/users/registries for more information)."); } TEST_CASE ("registries ignored patterns warning", "[registries]") diff --git a/src/vcpkg/base/json.cpp b/src/vcpkg/base/json.cpp index 3020f365ce..6ca47f27db 100644 --- a/src/vcpkg/base/json.cpp +++ b/src/vcpkg/base/json.cpp @@ -1518,4 +1518,19 @@ namespace vcpkg::Json } const PackageNameDeserializer PackageNameDeserializer::instance; + + LocalizedString FeatureNameDeserializer::type_name() const { return msg::format(msgAFeatureName); } + + Optional FeatureNameDeserializer::visit_string(Json::Reader& r, StringView sv) const + { + if (!IdentifierDeserializer::is_ident(sv)) + { + r.add_generic_error( + type_name(), + msg::format(msgParseFeatureNameError, msg::package_name = sv, msg::url = docs::manifests_url)); + } + return sv.to_string(); + } + + const FeatureNameDeserializer FeatureNameDeserializer::instance; } diff --git a/src/vcpkg/paragraphs.cpp b/src/vcpkg/paragraphs.cpp index 8166b9adc3..49c48776b2 100644 --- a/src/vcpkg/paragraphs.cpp +++ b/src/vcpkg/paragraphs.cpp @@ -215,7 +215,7 @@ namespace vcpkg } else { - dependency.features.emplace_back(feature); + dependency.features.push_back(DependencyRequestedFeature{feature}); } } return dependency; diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 07e810939c..75b40598ae 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -394,7 +394,7 @@ namespace vcpkg msg::url = docs::manifests_url)); } - spgh->default_features.emplace_back(std::move(default_feature)); + spgh->default_features.push_back(DependencyRequestedFeature{std::move(default_feature)}); } } else @@ -531,7 +531,7 @@ namespace vcpkg return sv.to_string(); } - return Json::IdentifierDeserializer::instance.visit_string(r, sv); + return Json::FeatureNameDeserializer::instance.visit_string(r, sv); } static const DefaultFeatureNameDeserializer instance; }; @@ -557,16 +557,15 @@ namespace vcpkg Optional visit_string(Json::Reader& r, StringView sv) const override { return DefaultFeatureNameDeserializer::instance.visit_string(r, sv).map( - [](std::string&& name) -> DependencyRequestedFeature { return std::move(name); }); + [](std::string&& name) { return DependencyRequestedFeature{std::move(name)}; }); } Optional visit_object(Json::Reader& r, const Json::Object& obj) const override { - std::string name; - PlatformExpression::Expr platform; - r.required_object_field(type_name(), obj, NAME, name, DefaultFeatureNameDeserializer::instance); - r.optional_object_field(obj, PLATFORM, platform, PlatformExprDeserializer::instance); - return DependencyRequestedFeature{std::move(name), std::move(platform)}; + DependencyRequestedFeature answer; + r.required_object_field(type_name(), obj, NAME, answer.name, DefaultFeatureNameDeserializer::instance); + r.optional_object_field(obj, PLATFORM, answer.platform, PlatformExprDeserializer::instance); + return answer; } const static DefaultFeatureDeserializer instance; @@ -583,7 +582,7 @@ namespace vcpkg struct DependencyFeatureNameDeserializer : Json::IDeserializer { - virtual LocalizedString type_name() const override { return msg::format(msgADependencyFeatureName); } + virtual LocalizedString type_name() const override { return msg::format(msgAFeatureName); } virtual Optional visit_string(Json::Reader& r, StringView sv) const override { if (sv == "core") @@ -598,7 +597,7 @@ namespace vcpkg return sv.to_string(); } - return Json::IdentifierDeserializer::instance.visit_string(r, sv); + return Json::FeatureNameDeserializer::instance.visit_string(r, sv); } static const DependencyFeatureNameDeserializer instance; }; @@ -624,16 +623,15 @@ namespace vcpkg Optional visit_string(Json::Reader& r, StringView sv) const override { return DependencyFeatureNameDeserializer::instance.visit_string(r, sv).map( - [](std::string&& name) -> DependencyRequestedFeature { return std::move(name); }); + [](std::string&& name) { return DependencyRequestedFeature{std::move(name)}; }); } Optional visit_object(Json::Reader& r, const Json::Object& obj) const override { - std::string name; - PlatformExpression::Expr platform; - r.required_object_field(type_name(), obj, NAME, name, DependencyFeatureNameDeserializer::instance); - r.optional_object_field(obj, PLATFORM, platform, PlatformExprDeserializer::instance); - return DependencyRequestedFeature{std::move(name), std::move(platform)}; + DependencyRequestedFeature result; + r.required_object_field(type_name(), obj, NAME, result.name, DependencyFeatureNameDeserializer::instance); + r.optional_object_field(obj, PLATFORM, result.platform, PlatformExprDeserializer::instance); + return result; } const static DependencyFeatureDeserializer instance; @@ -675,14 +673,8 @@ namespace vcpkg virtual Optional visit_string(Json::Reader& r, StringView sv) const override { - if (!Json::IdentifierDeserializer::is_ident(sv)) - { - r.add_generic_error(type_name(), msg::format(msgInvalidDependency)); - } - - Dependency dep; - dep.name = sv.to_string(); - return dep; + return Json::PackageNameDeserializer::instance.visit_string(r, sv).map( + [](std::string&& name) { return Dependency{std::move(name)}; }); } virtual Optional visit_object(Json::Reader& r, const Json::Object& obj) const override @@ -776,7 +768,7 @@ namespace vcpkg VersionScheme& version_scheme, int& port_version) { - r.required_object_field(type_name, obj, NAME, name, Json::IdentifierDeserializer::instance); + r.required_object_field(type_name, obj, NAME, name, Json::PackageNameDeserializer::instance); auto schemed_version = visit_required_schemed_deserializer(type_name, r, obj, true); version = schemed_version.version.text(); @@ -1338,7 +1330,7 @@ namespace vcpkg auto& spgh = *control_file->core_paragraph; - r.optional_object_field(obj, NAME, spgh.name, Json::IdentifierDeserializer::instance); + r.optional_object_field(obj, NAME, spgh.name, Json::PackageNameDeserializer::instance); auto maybe_schemed_version = visit_optional_schemed_deserializer(type_name(), r, obj, false); if (auto p = maybe_schemed_version.get()) { @@ -1369,7 +1361,7 @@ namespace vcpkg auto& spgh = *control_file->core_paragraph; - r.required_object_field(type_name(), obj, NAME, spgh.name, Json::IdentifierDeserializer::instance); + r.required_object_field(type_name(), obj, NAME, spgh.name, Json::PackageNameDeserializer::instance); auto schemed_version = visit_required_schemed_deserializer(type_name(), r, obj, false); spgh.raw_version = schemed_version.version.text(); spgh.version_scheme = schemed_version.scheme; From 918269b50fe955e5e2b61dd7827f8109b8b94ed9 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 28 Sep 2023 19:56:21 -0700 Subject: [PATCH 21/48] Burninate Expr::Empty --- include/vcpkg/platform-expression.h | 5 +---- src/vcpkg/commands.add.cpp | 2 +- src/vcpkg/sourceparagraph.cpp | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/include/vcpkg/platform-expression.h b/include/vcpkg/platform-expression.h index 6d93abc7b4..25a66bdb71 100644 --- a/include/vcpkg/platform-expression.h +++ b/include/vcpkg/platform-expression.h @@ -24,11 +24,8 @@ namespace vcpkg::PlatformExpression static Expr And(std::vector&& exprs); static Expr Or(std::vector&& exprs); - // The empty expression is always true - static Expr Empty() { return Expr(); } - // since ExprImpl is not yet defined, we need to define the ctor and dtor in the C++ file - Expr(); + Expr(); // always true Expr(const Expr&); Expr(Expr&&); Expr& operator=(const Expr& e); diff --git a/src/vcpkg/commands.add.cpp b/src/vcpkg/commands.add.cpp index 62d0c5a109..fc1c7937c5 100644 --- a/src/vcpkg/commands.add.cpp +++ b/src/vcpkg/commands.add.cpp @@ -112,7 +112,7 @@ namespace vcpkg }); const auto features = Util::fmap(spec.features.value_or({}), [](const std::string& feature) { Checks::check_exit(VCPKG_LINE_INFO, !feature.empty() && feature != "core" && feature != "default"); - return DependencyRequestedFeature{feature, PlatformExpression::Expr::Empty()}; + return DependencyRequestedFeature{feature}; }); if (dep == manifest_scf.core_paragraph->dependencies.end()) { diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 75b40598ae..772cbb49fd 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -506,7 +506,7 @@ namespace vcpkg else { r.add_generic_error(type_name(), std::move(opt).error()); - return PlatformExpression::Expr::Empty(); + return PlatformExpression::Expr(); } } From 582382f172df936d3fa74d597ad5aeea450da577 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Fri, 29 Sep 2023 21:14:06 -0700 Subject: [PATCH 22/48] Code review feedback --- include/vcpkg/base/message-data.inc.h | 19 ++++++++++--------- locales/messages.json | 8 ++++---- src/vcpkg-test/dependencies.cpp | 18 +++++++++--------- src/vcpkg/paragraphs.cpp | 2 +- src/vcpkg/sourceparagraph.cpp | 2 +- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 07e7499832..4c385a3af2 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -1007,16 +1007,17 @@ DECLARE_MESSAGE(DeleteVcpkgConfigFromManifest, (msg::path), "", "-- Or remove \"vcpkg-configuration\" from the manifest file {path}.") -DECLARE_MESSAGE(DependencyFeatureCore, - (), - "The word \"core\" is an on-disk name that must not be localized. The 'default-features' part is JSON " - "syntax that must be copied verbatim into the user's file.", - "the feature \"core\" cannot be in a dependency's feature list. To turn off default features, add " - "\"default-features\": false instead.") +DECLARE_MESSAGE( + DependencyFeatureCore, + (), + "The word \"core\" is an on-disk name that must not be localized. The \"default-features\" part is JSON " + "syntax that must be copied verbatim into the user's file.", + "the feature \"core\" cannot be in a dependency's feature list. To turn off default features, add " + "\"default-features\": false instead.") DECLARE_MESSAGE( DependencyFeatureDefault, (), - "The word \"default\" is an on-disk name that must not be localized. The 'default-features' part is JSON " + "The word \"default\" is an on-disk name that must not be localized. The \"default-features\" part is JSON " "syntax that must be copied verbatim into the user's file.", "the feature \"default\" cannot be in a dependency's feature list. To turn on default features, add " "\"default-features\": true instead.") @@ -2325,11 +2326,11 @@ DECLARE_MESSAGE(PECoffHeaderTooShort, DECLARE_MESSAGE(PEConfigCrossesSectionBoundary, (msg::path), "Portable executable is a term-of-art, see https://learn.microsoft.com/windows/win32/debug/pe-format", - "While parsing Portable Executable {path}, image config directory crosses a secion boundary.") + "While parsing Portable Executable {path}, image config directory crosses a section boundary.") DECLARE_MESSAGE(PEImportCrossesSectionBoundary, (msg::path), "Portable executable is a term-of-art, see https://learn.microsoft.com/windows/win32/debug/pe-format", - "While parsing Portable Executable {path}, import table crosses a secion boundary.") + "While parsing Portable Executable {path}, import table crosses a section boundary.") DECLARE_MESSAGE(PEPlusTagInvalid, (msg::path), "Portable executable is a term-of-art, see https://learn.microsoft.com/windows/win32/debug/pe-format", diff --git a/locales/messages.json b/locales/messages.json index fbc50143d7..145675625a 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -590,9 +590,9 @@ "DeleteVcpkgConfigFromManifest": "-- Or remove \"vcpkg-configuration\" from the manifest file {path}.", "_DeleteVcpkgConfigFromManifest.comment": "An example of {path} is /foo/bar.", "DependencyFeatureCore": "the feature \"core\" cannot be in a dependency's feature list. To turn off default features, add \"default-features\": false instead.", - "_DependencyFeatureCore.comment": "The word \"core\" is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", + "_DependencyFeatureCore.comment": "The word \"core\" is an on-disk name that must not be localized. The \"default-features\" part is JSON syntax that must be copied verbatim into the user's file.", "DependencyFeatureDefault": "the feature \"default\" cannot be in a dependency's feature list. To turn on default features, add \"default-features\": true instead.", - "_DependencyFeatureDefault.comment": "The word \"default\" is an on-disk name that must not be localized. The 'default-features' part is JSON syntax that must be copied verbatim into the user's file.", + "_DependencyFeatureDefault.comment": "The word \"default\" is an on-disk name that must not be localized. The \"default-features\" part is JSON syntax that must be copied verbatim into the user's file.", "DependencyGraphCalculation": "Dependency graph submission enabled.", "DependencyGraphFailure": "Dependency graph submission failed.", "DependencyGraphSuccess": "Dependency graph submission successful.", @@ -1282,9 +1282,9 @@ "_OverwritingFile.comment": "An example of {path} is /foo/bar.", "PECoffHeaderTooShort": "While parsing Portable Executable {path}, size of COFF header too small to contain a valid PE header.", "_PECoffHeaderTooShort.comment": "Portable executable is a term-of-art, see https://learn.microsoft.com/windows/win32/debug/pe-format An example of {path} is /foo/bar.", - "PEConfigCrossesSectionBoundary": "While parsing Portable Executable {path}, image config directory crosses a secion boundary.", + "PEConfigCrossesSectionBoundary": "While parsing Portable Executable {path}, image config directory crosses a section boundary.", "_PEConfigCrossesSectionBoundary.comment": "Portable executable is a term-of-art, see https://learn.microsoft.com/windows/win32/debug/pe-format An example of {path} is /foo/bar.", - "PEImportCrossesSectionBoundary": "While parsing Portable Executable {path}, import table crosses a secion boundary.", + "PEImportCrossesSectionBoundary": "While parsing Portable Executable {path}, import table crosses a section boundary.", "_PEImportCrossesSectionBoundary.comment": "Portable executable is a term-of-art, see https://learn.microsoft.com/windows/win32/debug/pe-format An example of {path} is /foo/bar.", "PEPlusTagInvalid": "While parsing Portable Executable {path}, optional header was neither PE32 nor PE32+.", "_PEPlusTagInvalid.comment": "Portable executable is a term-of-art, see https://learn.microsoft.com/windows/win32/debug/pe-format An example of {path} is /foo/bar.", diff --git a/src/vcpkg-test/dependencies.cpp b/src/vcpkg-test/dependencies.cpp index e25623e8a6..359e4233ae 100644 --- a/src/vcpkg-test/dependencies.cpp +++ b/src/vcpkg-test/dependencies.cpp @@ -1619,7 +1619,7 @@ TEST_CASE ("version install default features", "[versionplan]") auto a_x = make_fpgh("x"); auto& a_scf = vp.emplace("a", {"1", 0}, VersionScheme::Relaxed).source_control_file; - a_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"x"}); + a_scf->core_paragraph->default_features.push_back({"x"}); a_scf->feature_paragraphs.push_back(std::move(a_x)); MockCMakeVarProvider var_provider; @@ -1640,7 +1640,7 @@ TEST_CASE ("version dont install default features", "[versionplan]") auto a_x = make_fpgh("x"); auto& a_scf = vp.emplace("a", {"1", 0}, VersionScheme::Relaxed).source_control_file; - a_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"x"}); + a_scf->core_paragraph->default_features.push_back({"x"}); a_scf->feature_paragraphs.push_back(std::move(a_x)); MockCMakeVarProvider var_provider; @@ -1661,7 +1661,7 @@ TEST_CASE ("version install transitive default features", "[versionplan]") auto a_x = make_fpgh("x"); auto& a_scf = vp.emplace("a", {"1", 0}, VersionScheme::Relaxed).source_control_file; - a_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"x"}); + a_scf->core_paragraph->default_features.push_back({"x"}); a_scf->feature_paragraphs.push_back(std::move(a_x)); auto& b_scf = vp.emplace("b", {"1", 0}, VersionScheme::Relaxed).source_control_file; @@ -1752,7 +1752,7 @@ TEST_CASE ("version install qualified default suppression", "[versionplan]") MockVersionedPortfileProvider vp; auto& a_scf = vp.emplace("a", {"1", 0}, VersionScheme::Relaxed).source_control_file; - a_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"x"}); + a_scf->core_paragraph->default_features.push_back({"x"}); a_scf->feature_paragraphs.push_back(make_fpgh("x")); vp.emplace("b", {"1", 0}, VersionScheme::Relaxed) @@ -1837,17 +1837,17 @@ TEST_CASE ("version install qualified features", "[versionplan]") MockVersionedPortfileProvider vp; auto& b_scf = vp.emplace("b", {"1", 0}, VersionScheme::Relaxed).source_control_file; - b_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"x"}); + b_scf->core_paragraph->default_features.push_back({"x"}); b_scf->feature_paragraphs.push_back(make_fpgh("x")); b_scf->feature_paragraphs.back()->dependencies.push_back({"a", {}, parse_platform("!linux")}); auto& a_scf = vp.emplace("a", {"1", 0}, VersionScheme::Relaxed).source_control_file; - a_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"y"}); + a_scf->core_paragraph->default_features.push_back({"y"}); a_scf->feature_paragraphs.push_back(make_fpgh("y")); a_scf->feature_paragraphs.back()->dependencies.push_back({"c", {}, parse_platform("linux")}); auto& c_scf = vp.emplace("c", {"1", 0}, VersionScheme::Relaxed).source_control_file; - c_scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{"z"}); + c_scf->core_paragraph->default_features.push_back({"z"}); c_scf->feature_paragraphs.push_back(make_fpgh("z")); c_scf->feature_paragraphs.back()->dependencies.push_back({"d", {}, parse_platform("linux")}); @@ -2313,8 +2313,8 @@ TEST_CASE ("respect platform expressions in default features", "[versionplan]") a_x->name = "x"; auto& scf = vp.emplace("a", {"1", 0}).source_control_file; scf->feature_paragraphs.push_back(std::move(a_x)); - scf->core_paragraph->default_features.push_back(DependencyRequestedFeature{ - "x", parse_platform_expression("linux", MultipleBinaryOperators::Deny).value_or_exit(VCPKG_LINE_INFO)}); + scf->core_paragraph->default_features.push_back( + {"x", parse_platform_expression("linux", MultipleBinaryOperators::Deny).value_or_exit(VCPKG_LINE_INFO)}); } MockCMakeVarProvider var_provider; diff --git a/src/vcpkg/paragraphs.cpp b/src/vcpkg/paragraphs.cpp index 49c48776b2..14e58538b6 100644 --- a/src/vcpkg/paragraphs.cpp +++ b/src/vcpkg/paragraphs.cpp @@ -215,7 +215,7 @@ namespace vcpkg } else { - dependency.features.push_back(DependencyRequestedFeature{feature}); + dependency.features.push_back({feature}); } } return dependency; diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 772cbb49fd..7d8bcfbae1 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -394,7 +394,7 @@ namespace vcpkg msg::url = docs::manifests_url)); } - spgh->default_features.push_back(DependencyRequestedFeature{std::move(default_feature)}); + spgh->default_features.push_back({std::move(default_feature)}); } } else From b2a6334cc87ec931492ed3482943d66728055edd Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Fri, 29 Sep 2023 22:33:34 -0700 Subject: [PATCH 23/48] Fix merge conflicts --- src/vcpkg-test/manifests.cpp | 102 +++++++++++++++------------------ src/vcpkg/commands.add.cpp | 12 ++-- src/vcpkg/commands.install.cpp | 4 +- 3 files changed, 55 insertions(+), 63 deletions(-) diff --git a/src/vcpkg-test/manifests.cpp b/src/vcpkg-test/manifests.cpp index d6aa2baced..e1eaa41b1d 100644 --- a/src/vcpkg-test/manifests.cpp +++ b/src/vcpkg-test/manifests.cpp @@ -1272,9 +1272,9 @@ TEST_CASE ("default-feature-core errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == "error: while loading :\n" - "$.default-features[0] (a default feature): the feature \"core\" turns off " - "default features and thus can't be in the default features list"); + REQUIRE(m_pgh.error().data() == + ": error: $.default-features[0] (a default feature): the feature \"core\" turns off default " + "features and thus can't be in the default features list"); } TEST_CASE ("default-feature-core-object errors", "[manifests]") @@ -1284,9 +1284,9 @@ TEST_CASE ("default-feature-core-object errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == "error: while loading :\n" - "$.default-features[0].name (a default feature): the feature \"core\" turns " - "off default features and thus can't be in the default features list"); + REQUIRE(m_pgh.error().data() == + ": error: $.default-features[0].name (a default feature): the feature \"core\" turns off " + "default features and thus can't be in the default features list"); } TEST_CASE ("default-feature-default errors", "[manifests]") @@ -1296,10 +1296,9 @@ TEST_CASE ("default-feature-default errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == - "error: while loading :\n" - "$.default-features[0] (a default feature): the feature \"default\" refers to " - "the set of default features and thus can't be in the default features list"); + REQUIRE(m_pgh.error().data() == + ": error: $.default-features[0] (a default feature): the feature \"default\" refers to the " + "set of default features and thus can't be in the default features list"); } TEST_CASE ("default-feature-default-object errors", "[manifests]") @@ -1309,10 +1308,9 @@ TEST_CASE ("default-feature-default-object errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == - "error: while loading :\n" - "$.default-features[0].name (a default feature): the feature \"default\" refers to the set of default " - "features and thus can't be in the default features list"); + REQUIRE(m_pgh.error().data() == + ": error: $.default-features[0].name (a default feature): the feature \"default\" refers to " + "the set of default features and thus can't be in the default features list"); } TEST_CASE ("default-feature-empty errors", "[manifests]") @@ -1322,10 +1320,10 @@ TEST_CASE ("default-feature-empty errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == "error: while loading :\n" - "$.default-features[0] (a feature name): \"\" is not a valid feature name. " - "Feature names must be lowercase alphanumeric+hypens and not reserved (see " - "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); + REQUIRE(m_pgh.error().data() == + ": error: $.default-features[0] (a feature name): \"\" is not a valid feature name. Feature " + "names must be lowercase alphanumeric+hypens and not reserved (see " + "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); } TEST_CASE ("default-feature-empty-object errors", "[manifests]") @@ -1335,9 +1333,8 @@ TEST_CASE ("default-feature-empty-object errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == - "error: while loading :\n" - "$.default-features[0].name (a feature name): \"\" is not a valid feature name. " + REQUIRE(m_pgh.error().data() == + ": error: $.default-features[0].name (a feature name): \"\" is not a valid feature name. " "Feature names must be lowercase alphanumeric+hypens and not reserved (see " "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); } @@ -1349,10 +1346,10 @@ TEST_CASE ("dependency-name-empty errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == "error: while loading :\n" - "$.dependencies[0] (a package name): \"\" is not a valid package name. " - "Package names must be lowercase alphanumeric+hypens and not reserved (see " - "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); + REQUIRE(m_pgh.error().data() == + ": error: $.dependencies[0] (a package name): \"\" is not a valid package name. Package " + "names must be lowercase alphanumeric+hypens and not reserved (see " + "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); } TEST_CASE ("dependency-name-empty-object errors", "[manifests]") @@ -1362,10 +1359,10 @@ TEST_CASE ("dependency-name-empty-object errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == "error: while loading :\n" - "$.dependencies[0].name (a package name): \"\" is not a valid package name. " - "Package names must be lowercase alphanumeric+hypens and not reserved (see " - "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); + REQUIRE(m_pgh.error().data() == + ": error: $.dependencies[0].name (a package name): \"\" is not a valid package name. " + "Package names must be lowercase alphanumeric+hypens and not reserved (see " + "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); } TEST_CASE ("dependency-feature-name-core errors", "[manifests]") @@ -1380,10 +1377,9 @@ TEST_CASE ("dependency-feature-name-core errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == - "error: while loading :\n" - "$.dependencies[0].features[0] (a feature name): the feature \"core\" cannot be in a dependency's feature " - "list. To turn off default features, add \"default-features\": false instead."); + REQUIRE(m_pgh.error().data() == + ": error: $.dependencies[0].features[0] (a feature name): the feature \"core\" cannot be in " + "a dependency's feature list. To turn off default features, add \"default-features\": false instead."); } TEST_CASE ("dependency-feature-name-core-object errors", "[manifests]") @@ -1399,10 +1395,9 @@ TEST_CASE ("dependency-feature-name-core-object errors", "[manifests]") PrintErrors::No); REQUIRE(!m_pgh.has_value()); REQUIRE( - m_pgh.error()->to_string() == - "error: while loading :\n" - "$.dependencies[0].features[0].name (a feature name): the feature \"core\" cannot be in a dependency's feature " - "list. To turn off default features, add \"default-features\": false instead."); + m_pgh.error().data() == + ": error: $.dependencies[0].features[0].name (a feature name): the feature \"core\" cannot be " + "in a dependency's feature list. To turn off default features, add \"default-features\": false instead."); } TEST_CASE ("dependency-feature-name-default errors", "[manifests]") @@ -1417,10 +1412,9 @@ TEST_CASE ("dependency-feature-name-default errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == - "error: while loading :\n" - "$.dependencies[0].features[0] (a feature name): the feature \"default\" cannot be in a dependency's " - "feature list. To turn on default features, add \"default-features\": true instead."); + REQUIRE(m_pgh.error().data() == + ": error: $.dependencies[0].features[0] (a feature name): the feature \"default\" cannot be " + "in a dependency's feature list. To turn on default features, add \"default-features\": true instead."); } TEST_CASE ("dependency-feature-name-default-object errors", "[manifests]") @@ -1435,10 +1429,10 @@ TEST_CASE ("dependency-feature-name-default-object errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == - "error: while loading :\n" - "$.dependencies[0].features[0].name (a feature name): the feature \"default\" cannot be in a dependency's " - "feature list. To turn on default features, add \"default-features\": true instead."); + REQUIRE( + m_pgh.error().data() == + ": error: $.dependencies[0].features[0].name (a feature name): the feature \"default\" cannot be " + "in a dependency's feature list. To turn on default features, add \"default-features\": true instead."); } TEST_CASE ("dependency-feature-name-empty errors", "[manifests]") { @@ -1452,11 +1446,10 @@ TEST_CASE ("dependency-feature-name-empty errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == - "error: while loading :\n" - "$.dependencies[0].features[0] (a feature name): \"\" is not a valid feature name. Feature names must be " - "lowercase alphanumeric+hypens and not reserved (see https://learn.microsoft.com/vcpkg/users/manifests for " - "more information)."); + REQUIRE(m_pgh.error().data() == + ": error: $.dependencies[0].features[0] (a feature name): \"\" is not a valid feature name. " + "Feature names must be lowercase alphanumeric+hypens and not reserved (see " + "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); } TEST_CASE ("dependency-feature-name-empty-object errors", "[manifests]") @@ -1471,9 +1464,8 @@ TEST_CASE ("dependency-feature-name-empty-object errors", "[manifests]") })json", PrintErrors::No); REQUIRE(!m_pgh.has_value()); - REQUIRE(m_pgh.error()->to_string() == - "error: while loading :\n" - "$.dependencies[0].features[0].name (a feature name): \"\" is not a valid feature name. Feature names must " - "be lowercase alphanumeric+hypens and not reserved (see https://learn.microsoft.com/vcpkg/users/manifests " - "for more information)."); + REQUIRE(m_pgh.error().data() == + ": error: $.dependencies[0].features[0].name (a feature name): \"\" is not a valid feature " + "name. Feature names must be lowercase alphanumeric+hypens and not reserved (see " + "https://learn.microsoft.com/vcpkg/users/manifests for more information)."); } diff --git a/src/vcpkg/commands.add.cpp b/src/vcpkg/commands.add.cpp index b2916465d3..1635541564 100644 --- a/src/vcpkg/commands.add.cpp +++ b/src/vcpkg/commands.add.cpp @@ -100,12 +100,12 @@ namespace vcpkg if (!pmanifest_scf) { msg::print(Color::error, - std::move(maybe_manifest_scf) - .error() - .append_raw('\n') - .append(msgNoteMessage) - .append(msg::msgSeeURL, msg::url = docs::manifests_url) - .append_raw('\n')); + std::move(maybe_manifest_scf) + .error() + .append_raw('\n') + .append(msgNoteMessage) + .append(msg::msgSeeURL, msg::url = docs::manifests_url) + .append_raw('\n')); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/commands.install.cpp b/src/vcpkg/commands.install.cpp index 407ad91407..6df1105de2 100644 --- a/src/vcpkg/commands.install.cpp +++ b/src/vcpkg/commands.install.cpp @@ -1114,9 +1114,9 @@ namespace vcpkg std::move(maybe_manifest_scf) .error() .append_raw('\n') - .append(msgNoteMessage) + .append(msgNoteMessage) .append(msgExtendedDocumentationAtUrl, msg::url = docs::manifests_url) - .append_raw('\n'); + .append_raw('\n')); Checks::exit_fail(VCPKG_LINE_INFO); } From ae5300bad57008d190f7e66106f2ce4fbe7766e9 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Sat, 30 Sep 2023 00:01:51 -0700 Subject: [PATCH 24/48] Restore spdx_location. --- include/vcpkg/fwd/sourceparagraph.h | 9 +++- include/vcpkg/paragraphs.h | 10 +++-- include/vcpkg/registries.h | 12 +----- include/vcpkg/sourceparagraph.h | 15 ++++++- src/vcpkg-test/manifests.cpp | 4 +- src/vcpkg-test/spdx.cpp | 3 +- src/vcpkg-test/versionplan.cpp | 7 +-- src/vcpkg/commands.add-version.cpp | 6 +-- src/vcpkg/commands.autocomplete.cpp | 2 +- src/vcpkg/commands.ci-verify-versions.cpp | 6 ++- src/vcpkg/commands.format-manifest.cpp | 9 ++-- src/vcpkg/paragraphs.cpp | 52 ++++++++++++++--------- src/vcpkg/portfileprovider.cpp | 17 +++++--- src/vcpkg/registries.cpp | 31 +++++++------- src/vcpkg/spdx.cpp | 2 +- 15 files changed, 109 insertions(+), 76 deletions(-) diff --git a/include/vcpkg/fwd/sourceparagraph.h b/include/vcpkg/fwd/sourceparagraph.h index 78fe57cdc5..0b8083bd05 100644 --- a/include/vcpkg/fwd/sourceparagraph.h +++ b/include/vcpkg/fwd/sourceparagraph.h @@ -3,6 +3,13 @@ namespace vcpkg { struct ManifestAndPath; + struct DependencyConstraint; + struct DependencyRequestedFeature; + struct Dependency; + struct DependencyOverride; + struct FeatureParagraph; + struct SourceParagraph; + struct PortLocation; struct SourceControlFile; struct SourceControlFileAndLocation; -} \ No newline at end of file +} diff --git a/include/vcpkg/paragraphs.h b/include/vcpkg/paragraphs.h index aeb288c279..bb7e962e29 100644 --- a/include/vcpkg/paragraphs.h +++ b/include/vcpkg/paragraphs.h @@ -35,18 +35,22 @@ namespace vcpkg::Paragraphs // If an error occurs, the Expected will be in the error state. // Otherwise, if the port is known, the maybe_scfl->source_control_file contains the loaded port information. // Otherwise, maybe_scfl->source_control_file is nullptr. - PortLoadResult try_load_port(const ReadOnlyFilesystem& fs, StringView port_name, const Path& port_directory); + PortLoadResult try_load_port(const ReadOnlyFilesystem& fs, StringView port_name, const PortLocation& port_location); // Identical to try_load_port, but the port unknown condition is mapped to an error. PortLoadResult try_load_port_required(const ReadOnlyFilesystem& fs, StringView port_name, - const Path& port_directory); + const PortLocation& port_location); ExpectedL try_load_project_manifest_text(StringView text, StringView origin, + StringView spdx_location, MessageSink& warning_sink); ExpectedL try_load_port_manifest_text(StringView text, StringView origin, + StringView spdx_location, MessageSink& warning_sink); - ExpectedL try_load_control_file_text(StringView text, StringView origin); + ExpectedL try_load_control_file_text(StringView text, + StringView origin, + StringView spdx_location); ExpectedL try_load_cached_package(const ReadOnlyFilesystem& fs, const Path& package_dir, diff --git a/include/vcpkg/registries.h b/include/vcpkg/registries.h index 366dab5212..43939d7e38 100644 --- a/include/vcpkg/registries.h +++ b/include/vcpkg/registries.h @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -53,20 +54,11 @@ namespace vcpkg bool modified = false; }; - struct PathAndLocation - { - Path path; - - /// Should model SPDX PackageDownloadLocation. Empty implies NOASSERTION. - /// See https://spdx.github.io/spdx-spec/package-information/#77-package-download-location-field - std::string location; - }; - struct RegistryEntry { virtual ExpectedL> get_port_versions() const = 0; - virtual ExpectedL get_version(const Version& version) const = 0; + virtual ExpectedL get_version(const Version& version) const = 0; virtual ~RegistryEntry() = default; }; diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index 8f1bd46b17..586a3d6e47 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -141,6 +141,15 @@ namespace vcpkg friend bool operator!=(const SourceParagraph& lhs, const SourceParagraph& rhs) { return !(lhs == rhs); } }; + struct PortLocation + { + Path port_directory; + + /// Should model SPDX PackageDownloadLocation. Empty implies NOASSERTION. + /// See https://spdx.github.io/spdx-spec/package-information/#77-package-download-location-field + std::string spdx_location; + }; + ///

/// Full metadata of a package: core and other features. /// @@ -200,6 +209,10 @@ namespace vcpkg std::unique_ptr source_control_file; Path control_location; + + /// Should model SPDX PackageDownloadLocation. Empty implies NOASSERTION. + /// See https://spdx.github.io/spdx-spec/package-information/#77-package-download-location-field + std::string spdx_location; }; void print_error_message(const LocalizedString& message); @@ -209,6 +222,6 @@ namespace vcpkg // Exposed for testing ExpectedL> parse_dependencies_list(const std::string& str, - StringView origin = "", + StringView origin, TextRowCol textrowcol = {}); } diff --git a/src/vcpkg-test/manifests.cpp b/src/vcpkg-test/manifests.cpp index e1eaa41b1d..60ef289aae 100644 --- a/src/vcpkg-test/manifests.cpp +++ b/src/vcpkg-test/manifests.cpp @@ -1431,8 +1431,8 @@ TEST_CASE ("dependency-feature-name-default-object errors", "[manifests]") REQUIRE(!m_pgh.has_value()); REQUIRE( m_pgh.error().data() == - ": error: $.dependencies[0].features[0].name (a feature name): the feature \"default\" cannot be " - "in a dependency's feature list. To turn on default features, add \"default-features\": true instead."); + ": error: $.dependencies[0].features[0].name (a feature name): the feature \"default\" cannot " + "be in a dependency's feature list. To turn on default features, add \"default-features\": true instead."); } TEST_CASE ("dependency-feature-name-empty errors", "[manifests]") { diff --git a/src/vcpkg-test/spdx.cpp b/src/vcpkg-test/spdx.cpp index 290b1aeda7..8b414894e8 100644 --- a/src/vcpkg-test/spdx.cpp +++ b/src/vcpkg-test/spdx.cpp @@ -9,6 +9,7 @@ TEST_CASE ("spdx maximum serialization", "[spdx]") { PackageSpec spec{"zlib", Test::ARM_UWP}; SourceControlFileAndLocation scfl; + scfl.spdx_location = "git://some-vcs-url"; auto& scf = *(scfl.source_control_file = std::make_unique()); auto& cpgh = *(scf.core_paragraph = std::make_unique()); cpgh.name = "zlib"; @@ -98,7 +99,7 @@ TEST_CASE ("spdx maximum serialization", "[spdx]") "name": "zlib", "SPDXID": "SPDXRef-port", "versionInfo": "1.0#5", - "downloadLocation": "NOASSERTION", + "downloadLocation": "git://some-vcs-url", "homepage": "homepage", "licenseConcluded": "MIT", "licenseDeclared": "NOASSERTION", diff --git a/src/vcpkg-test/versionplan.cpp b/src/vcpkg-test/versionplan.cpp index a7d2d5fcaf..b237e4d38a 100644 --- a/src/vcpkg-test/versionplan.cpp +++ b/src/vcpkg-test/versionplan.cpp @@ -12,7 +12,7 @@ using namespace vcpkg; TEST_CASE ("parse depends", "[dependencies]") { - auto w = parse_dependencies_list("liba (windows)"); + auto w = parse_dependencies_list("liba (windows)", ""); REQUIRE(w); auto& v = *w.get(); REQUIRE(v.size() == 1); @@ -31,7 +31,7 @@ TEST_CASE ("filter depends", "[dependencies]") const std::unordered_map arm_uwp_cmake_vars{{"VCPKG_TARGET_ARCHITECTURE", "arm"}, {"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}; - auto deps_ = parse_dependencies_list("liba (!uwp), libb, libc (uwp)"); + auto deps_ = parse_dependencies_list("liba (!uwp), libb, libc (uwp)", ""); REQUIRE(deps_); auto& deps = *deps_.get(); SECTION ("x64-windows") @@ -58,7 +58,8 @@ TEST_CASE ("filter depends", "[dependencies]") TEST_CASE ("parse feature depends", "[dependencies]") { auto u_ = parse_dependencies_list("libwebp[anim, gif2webp, img2webp, info, mux, nearlossless, " - "simd, cwebp, dwebp], libwebp[vwebp-sdl, extras] (!osx)"); + "simd, cwebp, dwebp], libwebp[vwebp-sdl, extras] (!osx)", + ""); REQUIRE(u_); auto& v = *u_.get(); REQUIRE(v.size() == 2); diff --git a/src/vcpkg/commands.add-version.cpp b/src/vcpkg/commands.add-version.cpp index c2aeb4547b..08ae0dda7f 100644 --- a/src/vcpkg/commands.add-version.cpp +++ b/src/vcpkg/commands.add-version.cpp @@ -397,9 +397,9 @@ namespace vcpkg { auto port_dir = paths.builtin_ports_directory() / port_name; - auto maybe_scf = - Paragraphs::try_load_port_required(fs, port_name, paths.builtin_ports_directory() / port_name) - .maybe_scfl; + auto maybe_scf = Paragraphs::try_load_port_required( + fs, port_name, PortLocation{paths.builtin_ports_directory() / port_name}) + .maybe_scfl; auto scf = maybe_scf.get(); if (!scf) { diff --git a/src/vcpkg/commands.autocomplete.cpp b/src/vcpkg/commands.autocomplete.cpp index d948728cb9..07197032c7 100644 --- a/src/vcpkg/commands.autocomplete.cpp +++ b/src/vcpkg/commands.autocomplete.cpp @@ -105,7 +105,7 @@ namespace vcpkg StringView triplet_prefix{colon + 1, last_arg.end()}; // TODO: Support autocomplete for ports in --overlay-ports auto maybe_port = Paragraphs::try_load_port_required( - paths.get_filesystem(), port_name, paths.builtin_ports_directory() / port_name); + paths.get_filesystem(), port_name, PortLocation{paths.builtin_ports_directory() / port_name}); if (!maybe_port.maybe_scfl) { Checks::exit_success(VCPKG_LINE_INFO); diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index 084f4703bd..f2ab7d0fd8 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -53,7 +53,8 @@ namespace return success; } - auto load_result = Paragraphs::try_load_port_required(paths.get_filesystem(), port_name, *extracted_tree); + auto load_result = + Paragraphs::try_load_port_required(paths.get_filesystem(), port_name, PortLocation{*extracted_tree}); auto scfl = load_result.maybe_scfl.get(); if (!scfl) { @@ -478,7 +479,8 @@ namespace vcpkg for (auto&& port_path : fs.get_directories_non_recursive(paths.builtin_ports_directory(), VCPKG_LINE_INFO)) { auto port_name = port_path.stem().to_string(); - auto maybe_loaded_port = Paragraphs::try_load_port_required(fs, port_name, port_path).maybe_scfl; + auto maybe_loaded_port = + Paragraphs::try_load_port_required(fs, port_name, PortLocation{port_path}).maybe_scfl; auto loaded_port = maybe_loaded_port.get(); if (loaded_port) { diff --git a/src/vcpkg/commands.format-manifest.cpp b/src/vcpkg/commands.format-manifest.cpp index 31de5e6361..de403b2534 100644 --- a/src/vcpkg/commands.format-manifest.cpp +++ b/src/vcpkg/commands.format-manifest.cpp @@ -132,7 +132,8 @@ namespace vcpkg if (path.filename() == "CONTROL") { - auto maybe_control = Paragraphs::try_load_control_file_text(contents->content, contents->origin); + auto maybe_control = + Paragraphs::try_load_control_file_text(contents->content, contents->origin, StringView{}); if (auto control = maybe_control.get()) { to_write.push_back( @@ -146,8 +147,8 @@ namespace vcpkg } else { - auto maybe_manifest = - Paragraphs::try_load_project_manifest_text(contents->content, contents->origin, stdout_sink); + auto maybe_manifest = Paragraphs::try_load_project_manifest_text( + contents->content, contents->origin, StringView{}, stdout_sink); if (auto manifest = maybe_manifest.get()) { to_write.push_back(ToWrite{contents->content, std::move(*manifest), path}); @@ -164,7 +165,7 @@ namespace vcpkg { for (const auto& dir : fs.get_directories_non_recursive(paths.builtin_ports_directory(), VCPKG_LINE_INFO)) { - auto maybe_manifest = Paragraphs::try_load_port_required(fs, dir.filename(), dir); + auto maybe_manifest = Paragraphs::try_load_port_required(fs, dir.filename(), PortLocation{dir}); if (auto manifest = maybe_manifest.maybe_scfl.get()) { auto original = manifest->control_location; diff --git a/src/vcpkg/paragraphs.cpp b/src/vcpkg/paragraphs.cpp index 15b7d7fdce..8a516c0905 100644 --- a/src/vcpkg/paragraphs.cpp +++ b/src/vcpkg/paragraphs.cpp @@ -409,6 +409,7 @@ namespace ExpectedL try_load_any_manifest_text( StringView text, StringView origin, + StringView spdx_location, MessageSink& warning_sink, ExpectedL> (*do_parse)(StringView, const Json::Object&, MessageSink&)) { @@ -419,7 +420,7 @@ namespace auto maybe_parsed = do_parse(origin, *object, warning_sink); if (auto parsed = maybe_parsed.get()) { - return SourceControlFileAndLocation{std::move(*parsed), origin.to_string()}; + return SourceControlFileAndLocation{std::move(*parsed), origin.to_string(), spdx_location.to_string()}; } return std::move(maybe_parsed).error(); @@ -433,19 +434,25 @@ namespace vcpkg::Paragraphs { ExpectedL try_load_project_manifest_text(StringView text, StringView origin, + StringView spdx_location, MessageSink& warning_sink) { - return try_load_any_manifest_text(text, origin, warning_sink, SourceControlFile::parse_project_manifest_object); + return try_load_any_manifest_text( + text, origin, spdx_location, warning_sink, SourceControlFile::parse_project_manifest_object); } ExpectedL try_load_port_manifest_text(StringView text, StringView origin, + StringView spdx_location, MessageSink& warning_sink) { - return try_load_any_manifest_text(text, origin, warning_sink, SourceControlFile::parse_port_manifest_object); + return try_load_any_manifest_text( + text, origin, spdx_location, warning_sink, SourceControlFile::parse_port_manifest_object); } - ExpectedL try_load_control_file_text(StringView text, StringView origin) + ExpectedL try_load_control_file_text(StringView text, + StringView origin, + StringView spdx_location) { StatsTimer timer(g_load_ports_stats); ExpectedL> pghs = parse_paragraphs(text, origin); @@ -455,7 +462,7 @@ namespace vcpkg::Paragraphs SourceControlFile::parse_control_file(origin, std::move(*vector_pghs))); if (auto parsed = maybe_parsed.get()) { - return SourceControlFileAndLocation{std::move(*parsed), origin.to_string()}; + return SourceControlFileAndLocation{std::move(*parsed), origin.to_string(), spdx_location.to_string()}; } return std::move(maybe_parsed).error(); @@ -464,12 +471,12 @@ namespace vcpkg::Paragraphs return std::move(pghs).error(); } - PortLoadResult try_load_port(const ReadOnlyFilesystem& fs, StringView port_name, const Path& port_directory) + PortLoadResult try_load_port(const ReadOnlyFilesystem& fs, StringView port_name, const PortLocation& port_location) { StatsTimer timer(g_load_ports_stats); - const auto manifest_path = port_directory / "vcpkg.json"; - const auto control_path = port_directory / "CONTROL"; + const auto manifest_path = port_location.port_directory / "vcpkg.json"; + const auto control_path = port_location.port_directory / "CONTROL"; std::error_code ec; auto manifest_contents = fs.read_contents(manifest_path, ec); if (ec) @@ -477,7 +484,7 @@ namespace vcpkg::Paragraphs auto manifest_exists = ec != std::errc::no_such_file_or_directory; if (manifest_exists) { - return PortLoadResult{LocalizedString::from_raw(port_directory) + return PortLoadResult{LocalizedString::from_raw(port_location.port_directory) .append_raw(": ") .append(format_filesystem_call_error(ec, "read_contents", {manifest_path})), std::string{}}; @@ -489,49 +496,52 @@ namespace vcpkg::Paragraphs if (ec != std::errc::no_such_file_or_directory) { return PortLoadResult{ - LocalizedString::from_raw(port_directory) + LocalizedString::from_raw(port_location.port_directory) .append_raw(": ") .append(format_filesystem_call_error(ec, "read_contents", {control_path})), std::string{}}; } - if (fs.exists(port_directory, IgnoreErrors{})) + if (fs.exists(port_location.port_directory, IgnoreErrors{})) { - return PortLoadResult{LocalizedString::from_raw(port_directory) + return PortLoadResult{LocalizedString::from_raw(port_location.port_directory) .append_raw(": ") .append(msgErrorMessage) .append(msgPortMissingManifest2, msg::package_name = port_name), std::string{}}; } - return PortLoadResult{LocalizedString::from_raw(port_directory) + return PortLoadResult{LocalizedString::from_raw(port_location.port_directory) .append_raw(": ") .append(msgErrorMessage) .append(msgPortDoesNotExist, msg::package_name = port_name), std::string{}}; } - return PortLoadResult{try_load_control_file_text(control_contents, control_path), control_contents}; + return PortLoadResult{ + try_load_control_file_text(control_contents, control_path, port_location.spdx_location), + control_contents}; } if (fs.exists(control_path, IgnoreErrors{})) { - return PortLoadResult{LocalizedString::from_raw(port_directory) + return PortLoadResult{LocalizedString::from_raw(port_location.port_directory) .append_raw(": ") .append(msgErrorMessage) .append(msgManifestConflict2), std::string{}}; } - return PortLoadResult{try_load_port_manifest_text(manifest_contents, manifest_path, stdout_sink), - manifest_contents}; + return PortLoadResult{ + try_load_port_manifest_text(manifest_contents, manifest_path, port_location.spdx_location, stdout_sink), + manifest_contents}; } PortLoadResult try_load_port_required(const ReadOnlyFilesystem& fs, StringView port_name, - const Path& port_directory) + const PortLocation& port_location) { - auto maybe_maybe_res = try_load_port(fs, port_name, port_directory); + auto maybe_maybe_res = try_load_port(fs, port_name, port_location); auto maybe_res = maybe_maybe_res.maybe_scfl.get(); if (maybe_res) { @@ -602,7 +612,7 @@ namespace vcpkg::Paragraphs auto maybe_port_location = (*port_entry)->get_version(*baseline_version); const auto port_location = maybe_port_location.get(); if (!port_location) continue; // baseline version was not in version db (registry consistency issue) - auto maybe_spgh = try_load_port_required(fs, port_name, port_location->path).maybe_scfl; + auto maybe_spgh = try_load_port_required(fs, port_name, *port_location).maybe_scfl; if (const auto spgh = maybe_spgh.get()) { ret.paragraphs.push_back(std::move(*spgh)); @@ -664,7 +674,7 @@ namespace vcpkg::Paragraphs for (auto&& path : port_dirs) { auto port_name = path.filename(); - auto maybe_spgh = try_load_port_required(fs, port_name, path).maybe_scfl; + auto maybe_spgh = try_load_port_required(fs, port_name, PortLocation{path}).maybe_scfl; if (const auto spgh = maybe_spgh.get()) { ret.paragraphs.push_back(std::move(*spgh)); diff --git a/src/vcpkg/portfileprovider.cpp b/src/vcpkg/portfileprovider.cpp index 7e0ce78f1c..f19b93823c 100644 --- a/src/vcpkg/portfileprovider.cpp +++ b/src/vcpkg/portfileprovider.cpp @@ -22,11 +22,11 @@ namespace OverlayRegistryEntry(Path&& p, Version&& v) : root(p), version(v) { } ExpectedL> get_port_versions() const override { return View{&version, 1}; } - ExpectedL get_version(const Version& v) const override + ExpectedL get_version(const Version& v) const override { if (v == version) { - return PathAndLocation{root, ""}; + return PortLocation{root}; } return msg::format(msgVersionNotFound, msg::expected = v, msg::actual = version); } @@ -188,7 +188,7 @@ namespace vcpkg if (auto path = maybe_path.get()) { auto maybe_control_file = - Paragraphs::try_load_port_required(m_fs, version_spec.port_name, path->path).maybe_scfl; + Paragraphs::try_load_port_required(m_fs, version_spec.port_name, *path).maybe_scfl; if (auto scf = maybe_control_file.get()) { auto scf_vspec = scf->source_control_file.get()->to_version_spec(); @@ -200,7 +200,7 @@ namespace vcpkg { return msg::format(msg::msgErrorMessage) .append(msgVersionSpecMismatch, - msg::path = path->path, + msg::path = path->port_directory, msg::expected_version = version_spec, msg::actual_version = scf_vspec); } @@ -291,7 +291,8 @@ namespace vcpkg // Try loading individual port if (Paragraphs::is_port_directory(m_fs, ports_dir)) { - auto maybe_scf = Paragraphs::try_load_port_required(m_fs, port_name, ports_dir).maybe_scfl; + auto maybe_scf = + Paragraphs::try_load_port_required(m_fs, port_name, PortLocation{ports_dir}).maybe_scfl; if (auto scfp = maybe_scf.get()) { if (scfp->source_control_file->core_paragraph->name == port_name) @@ -312,7 +313,8 @@ namespace vcpkg auto ports_spec = ports_dir / port_name; if (Paragraphs::is_port_directory(m_fs, ports_spec)) { - auto found_scf = Paragraphs::try_load_port_required(m_fs, port_name, ports_spec).maybe_scfl; + auto found_scf = + Paragraphs::try_load_port_required(m_fs, port_name, PortLocation{ports_spec}).maybe_scfl; if (auto scfp = found_scf.get()) { if (scfp->source_control_file->core_paragraph->name == port_name) @@ -362,7 +364,8 @@ namespace vcpkg if (Paragraphs::is_port_directory(m_fs, ports_dir)) { auto maybe_scf = - Paragraphs::try_load_port_required(m_fs, ports_dir.filename(), ports_dir).maybe_scfl; + Paragraphs::try_load_port_required(m_fs, ports_dir.filename(), PortLocation{ports_dir}) + .maybe_scfl; if (auto scfp = maybe_scf.get()) { // copy name before moving *scfp diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index 7dd93672c9..6c57d41f62 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -251,7 +251,7 @@ namespace std::vector&& version_entries); ExpectedL> get_port_versions() const override; - ExpectedL get_version(const Version& version) const override; + ExpectedL get_version(const Version& version) const override; private: ExpectedL ensure_not_stale() const; @@ -412,11 +412,11 @@ namespace } ExpectedL> get_port_versions() const override { return View{&version, 1}; } - ExpectedL get_version(const Version& v) const override + ExpectedL get_version(const Version& v) const override { if (v == version) { - return PathAndLocation{root, "git+https://github.com/Microsoft/vcpkg#ports/" + name}; + return PortLocation{root, "git+https://github.com/Microsoft/vcpkg#ports/" + name}; } return msg::format_error(msgVersionBuiltinPortTreeEntryMissing, @@ -438,7 +438,7 @@ namespace { return View{port_versions_soa.port_versions()}; } - ExpectedL get_version(const Version& version) const override; + ExpectedL get_version(const Version& version) const override; const VcpkgPaths& m_paths; @@ -453,7 +453,7 @@ namespace ExpectedL> get_port_versions() const override { return View{port_versions}; } - ExpectedL get_version(const Version& version) const override; + ExpectedL get_version(const Version& version) const override; std::string port_name; // these two map port versions to paths @@ -490,8 +490,9 @@ namespace private: const ExpectedL& get_scf(StringView port_name, const Path& path) const { - return m_scfs.get_lazy(path, - [&, this]() { return Paragraphs::try_load_port(m_fs, port_name, path).maybe_scfl; }); + return m_scfs.get_lazy(path, [&, this]() { + return Paragraphs::try_load_port(m_fs, port_name, PortLocation{path}).maybe_scfl; + }); } const ReadOnlyFilesystem& m_fs; @@ -1148,7 +1149,7 @@ namespace // { RegistryEntry // { BuiltinRegistryEntry::RegistryEntry - ExpectedL BuiltinGitRegistryEntry::get_version(const Version& version) const + ExpectedL BuiltinGitRegistryEntry::get_version(const Version& version) const { auto& port_versions = port_versions_soa.port_versions(); auto it = std::find(port_versions.begin(), port_versions.end(), version); @@ -1162,7 +1163,7 @@ namespace const auto& git_tree = port_versions_soa.git_trees()[it - port_versions.begin()]; return m_paths.git_checkout_port(port_name, git_tree, m_paths.root / ".git") - .map([&git_tree](Path&& p) -> PathAndLocation { + .map([&git_tree](Path&& p) -> PortLocation { return { std::move(p), "git+https://github.com/Microsoft/vcpkg@" + git_tree, @@ -1172,7 +1173,7 @@ namespace // } BuiltinRegistryEntry::RegistryEntry // { FilesystemRegistryEntry::RegistryEntry - ExpectedL FilesystemRegistryEntry::get_version(const Version& version) const + ExpectedL FilesystemRegistryEntry::get_version(const Version& version) const { auto it = std::find(port_versions.begin(), port_versions.end(), version); if (it == port_versions.end()) @@ -1180,10 +1181,8 @@ namespace return msg::format_error( msgVersionDatabaseEntryMissing, msg::package_name = port_name, msg::version = version); } - return PathAndLocation{ - version_paths[it - port_versions.begin()], - "", - }; + + return PortLocation{version_paths[it - port_versions.begin()]}; } // } FilesystemRegistryEntry::RegistryEntry @@ -1235,7 +1234,7 @@ namespace return std::move(maybe_not_stale).error(); } - ExpectedL GitRegistryEntry::get_version(const Version& version) const + ExpectedL GitRegistryEntry::get_version(const Version& version) const { auto it = std::find(last_loaded.port_versions().begin(), last_loaded.port_versions().end(), version); if (it == last_loaded.port_versions().end() && stale) @@ -1257,7 +1256,7 @@ namespace const auto& git_tree = last_loaded.git_trees()[it - last_loaded.port_versions().begin()]; return parent.m_paths.git_extract_tree_from_remote_registry(git_tree).map( - [this, &git_tree](Path&& p) -> PathAndLocation { + [this, &git_tree](Path&& p) -> PortLocation { return { std::move(p), Strings::concat("git+", parent.m_repo, "@", git_tree), diff --git a/src/vcpkg/spdx.cpp b/src/vcpkg/spdx.cpp index 975f496229..fe6cd8d5ad 100644 --- a/src/vcpkg/spdx.cpp +++ b/src/vcpkg/spdx.cpp @@ -167,7 +167,7 @@ std::string vcpkg::create_spdx_sbom(const InstallPlanAction& action, obj.insert("name", action.spec.name()); obj.insert("SPDXID", "SPDXRef-port"); obj.insert("versionInfo", cpgh.to_version().to_string()); - obj.insert("downloadLocation", noassert); + obj.insert("downloadLocation", scfl.spdx_location.empty() ? noassert : scfl.spdx_location); if (!cpgh.homepage.empty()) { obj.insert("homepage", cpgh.homepage); From e2f38d8aac192b568d0fd15c22626bdd01498837 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Sat, 30 Sep 2023 04:49:06 -0700 Subject: [PATCH 25/48] Add end to end tests and make errors more pretty. --- .../.gitattributes | 1 + .../bad-git-tree-1.0/portfile.cmake | 1 + .../bad-git-tree-1.0/vcpkg.json | 4 + .../bad-history-name-1.0/portfile.cmake | 1 + .../bad-history-name-1.0/vcpkg.json | 4 + .../portfile.cmake | 1 + .../baseline-version-mismatch-1.0/vcpkg.json | 4 + .../malformed-1.0/portfile.cmake | 1 + .../malformed-1.0/vcpkg.json | 5 + .../mismatch-git-tree-1.0/portfile.cmake | 1 + .../mismatch-git-tree-1.0/vcpkg.json | 4 + .../version-mismatch-1.0/portfile.cmake | 1 + .../version-mismatch-1.0/vcpkg.json | 4 + .../version-missing-1.0/portfile.cmake | 1 + .../version-missing-1.0/vcpkg.json | 4 + .../portfile.cmake | 1 + .../version-scheme-mismatch-1.0/vcpkg.json | 4 + .../ports/bad-git-tree/portfile.cmake | 1 + .../ports/bad-git-tree/vcpkg.json | 4 + .../ports/bad-history-name/portfile.cmake | 1 + .../ports/bad-history-name/vcpkg.json | 4 + .../baseline-version-mismatch/portfile.cmake | 1 + .../baseline-version-mismatch/vcpkg.json | 4 + .../baseline-version-missing/portfile.cmake | 1 + .../ports/baseline-version-missing/vcpkg.json | 4 + .../portfile.cmake | 1 + .../vcpkg.json | 12 ++ .../portfile.cmake | 1 + .../vcpkg.json | 7 + .../portfile.cmake | 1 + .../vcpkg.json | 15 ++ .../portfile.cmake | 1 + .../vcpkg.json | 10 ++ .../ports/good/portfile.cmake | 1 + .../ports/good/vcpkg.json | 4 + .../ports/malformed/portfile.cmake | 1 + .../ports/malformed/vcpkg.json | 5 + .../ports/mismatch-git-tree/portfile.cmake | 1 + .../ports/mismatch-git-tree/vcpkg.json | 5 + .../ports/no-versions/portfile.cmake | 1 + .../ports/no-versions/vcpkg.json | 4 + .../portfile.cmake | 1 + .../vcpkg.json | 10 ++ .../portfile.cmake | 1 + .../vcpkg.json | 10 ++ .../ports/version-mismatch/portfile.cmake | 1 + .../ports/version-mismatch/vcpkg.json | 4 + .../ports/version-missing/portfile.cmake | 1 + .../ports/version-missing/vcpkg.json | 4 + .../version-scheme-mismatch/portfile.cmake | 1 + .../ports/version-scheme-mismatch/vcpkg.json | 4 + .../versions/b-/bad-git-tree.json | 14 ++ .../versions/b-/bad-history-name.json | 14 ++ .../b-/baseline-version-mismatch.json | 14 ++ .../versions/b-/baseline-version-missing.json | 9 ++ .../versions/baseline.json | 72 +++++++++ ...ency-not-in-versions-database-feature.json | 9 ++ .../dependency-not-in-versions-database.json | 9 ++ ...sion-not-in-versions-database-feature.json | 9 ++ ...ency-version-not-in-versions-database.json | 9 ++ .../versions/g-/good.json | 9 ++ .../versions/m-/malformed.json | 14 ++ .../versions/m-/mismatch-git-tree.json | 9 ++ .../o-/override-not-in-versions-database.json | 9 ++ ...ride-version-not-in-versions-database.json | 9 ++ .../versions/v-/version-mismatch.json | 14 ++ .../versions/v-/version-missing.json | 9 ++ .../versions/v-/version-scheme-mismatch.json | 14 ++ .../ci-verify-versions.ps1 | 153 ++++++++++++++++++ include/vcpkg/base/message-data.inc.h | 71 ++++---- locales/messages.json | 36 +++-- src/vcpkg/commands.add-version.cpp | 1 - src/vcpkg/commands.ci-verify-versions.cpp | 117 +++++++++----- src/vcpkg/commands.portsdiff.cpp | 4 +- src/vcpkg/registries.cpp | 5 +- src/vcpkg/vcpkgpaths.cpp | 2 +- 76 files changed, 707 insertions(+), 97 deletions(-) create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/.gitattributes create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-git-tree-1.0/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-git-tree-1.0/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-history-name-1.0/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-history-name-1.0/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/baseline-version-mismatch-1.0/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/baseline-version-mismatch-1.0/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/malformed-1.0/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/malformed-1.0/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/mismatch-git-tree-1.0/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/mismatch-git-tree-1.0/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-mismatch-1.0/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-mismatch-1.0/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-missing-1.0/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-missing-1.0/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-scheme-mismatch-1.0/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-scheme-mismatch-1.0/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-git-tree/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-history-name/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-history-name/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-mismatch/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-missing/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/good/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/good/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/malformed/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/malformed/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/mismatch-git-tree/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/no-versions/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/no-versions/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-not-in-versions-database/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-not-in-versions-database/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-version-not-in-versions-database/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-version-not-in-versions-database/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-mismatch/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-missing/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-missing/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-scheme-mismatch/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/bad-git-tree.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/bad-history-name.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/baseline-version-mismatch.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/baseline-version-missing.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/baseline.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database-feature.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database-feature.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/g-/good.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/m-/malformed.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/o-/override-not-in-versions-database.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/o-/override-version-not-in-versions-database.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-mismatch.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-missing.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json create mode 100644 azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/.gitattributes b/azure-pipelines/e2e-assets/ci-verify-versions-registry/.gitattributes new file mode 100644 index 0000000000..fa1385d99a --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/.gitattributes @@ -0,0 +1 @@ +* -text diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-git-tree-1.0/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-git-tree-1.0/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-git-tree-1.0/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-git-tree-1.0/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-git-tree-1.0/vcpkg.json new file mode 100644 index 0000000000..cc29e93073 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-git-tree-1.0/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "bad-git-tree", + "version": "1.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-history-name-1.0/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-history-name-1.0/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-history-name-1.0/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-history-name-1.0/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-history-name-1.0/vcpkg.json new file mode 100644 index 0000000000..b95ea8e159 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/bad-history-name-1.0/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "bad-history-name-is-bad", + "version": "1.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/baseline-version-mismatch-1.0/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/baseline-version-mismatch-1.0/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/baseline-version-mismatch-1.0/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/baseline-version-mismatch-1.0/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/baseline-version-mismatch-1.0/vcpkg.json new file mode 100644 index 0000000000..6fddfd04d8 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/baseline-version-mismatch-1.0/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "baseline-version-mismatch", + "version": "1.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/malformed-1.0/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/malformed-1.0/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/malformed-1.0/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/malformed-1.0/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/malformed-1.0/vcpkg.json new file mode 100644 index 0000000000..fc9f86f7b9 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/malformed-1.0/vcpkg.json @@ -0,0 +1,5 @@ +{ + "name": "malformed", + "version": "1.0", + ~broken +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/mismatch-git-tree-1.0/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/mismatch-git-tree-1.0/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/mismatch-git-tree-1.0/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/mismatch-git-tree-1.0/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/mismatch-git-tree-1.0/vcpkg.json new file mode 100644 index 0000000000..e3f2c372d8 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/mismatch-git-tree-1.0/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "mismatch-git-tree", + "version": "1.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-mismatch-1.0/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-mismatch-1.0/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-mismatch-1.0/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-mismatch-1.0/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-mismatch-1.0/vcpkg.json new file mode 100644 index 0000000000..3ee37270e8 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-mismatch-1.0/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "version-mismatch", + "version": "1.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-missing-1.0/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-missing-1.0/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-missing-1.0/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-missing-1.0/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-missing-1.0/vcpkg.json new file mode 100644 index 0000000000..5e1d6e8427 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-missing-1.0/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "version-missing", + "version": "1.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-scheme-mismatch-1.0/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-scheme-mismatch-1.0/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-scheme-mismatch-1.0/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-scheme-mismatch-1.0/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-scheme-mismatch-1.0/vcpkg.json new file mode 100644 index 0000000000..428c44f8a5 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/version-scheme-mismatch-1.0/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "version-scheme-mismatch", + "version": "1.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-git-tree/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-git-tree/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-git-tree/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json new file mode 100644 index 0000000000..506a46ce93 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "bad-git-tree", + "version": "1.1" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-history-name/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-history-name/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-history-name/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-history-name/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-history-name/vcpkg.json new file mode 100644 index 0000000000..b490211723 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/bad-history-name/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "bad-history-name", + "version": "1.1" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-mismatch/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-mismatch/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-mismatch/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json new file mode 100644 index 0000000000..acb5a35f53 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "baseline-version-mismatch", + "version": "1.1" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-missing/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-missing/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-missing/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json new file mode 100644 index 0000000000..5b9b5b2204 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "baseline-version-missing", + "version": "1.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature/vcpkg.json new file mode 100644 index 0000000000..ea2024dd89 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature/vcpkg.json @@ -0,0 +1,12 @@ +{ + "name": "dependency-not-in-versions-database-feature", + "version": "1.0", + "features": { + "add-things": { + "description": "an example feature that adds some things", + "dependencies": [ + "no-versions" + ] + } + } +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database/vcpkg.json new file mode 100644 index 0000000000..4a252a2a78 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-not-in-versions-database/vcpkg.json @@ -0,0 +1,7 @@ +{ + "name": "dependency-not-in-versions-database", + "version": "1.0", + "dependencies": [ + "no-versions" + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/vcpkg.json new file mode 100644 index 0000000000..74fb7c7850 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/vcpkg.json @@ -0,0 +1,15 @@ +{ + "name": "dependency-version-not-in-versions-database-feature", + "version": "1.0", + "features": { + "add-things": { + "description": "an example feature that adds some things", + "dependencies": [ + { + "name": "good", + "version>=": "0.9" + } + ] + } + } +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/vcpkg.json new file mode 100644 index 0000000000..f1b434486a --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/vcpkg.json @@ -0,0 +1,10 @@ +{ + "name": "dependency-version-not-in-versions-database", + "version": "1.0", + "dependencies": [ + { + "name": "good", + "version>=": "0.9" + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/good/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/good/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/good/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/good/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/good/vcpkg.json new file mode 100644 index 0000000000..c16b969626 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/good/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "good", + "version": "1.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/malformed/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/malformed/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/malformed/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/malformed/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/malformed/vcpkg.json new file mode 100644 index 0000000000..129f63eef9 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/malformed/vcpkg.json @@ -0,0 +1,5 @@ +{ + "name": "malformed", + "version": "1.1", + ~broken +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/mismatch-git-tree/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/mismatch-git-tree/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/mismatch-git-tree/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json new file mode 100644 index 0000000000..2ef341b777 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json @@ -0,0 +1,5 @@ +{ + "$comment": "This comment changes the correct git-tree without changing the version", + "name": "mismatch-git-tree", + "version": "1.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/no-versions/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/no-versions/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/no-versions/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/no-versions/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/no-versions/vcpkg.json new file mode 100644 index 0000000000..5aa000f4de --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/no-versions/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "no-versions", + "version": "1.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-not-in-versions-database/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-not-in-versions-database/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-not-in-versions-database/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-not-in-versions-database/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-not-in-versions-database/vcpkg.json new file mode 100644 index 0000000000..8e88744937 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-not-in-versions-database/vcpkg.json @@ -0,0 +1,10 @@ +{ + "name": "override-not-in-versions-database", + "version": "1.0", + "overrides": [ + { + "name": "no-versions", + "version": "1.0" + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-version-not-in-versions-database/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-version-not-in-versions-database/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-version-not-in-versions-database/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-version-not-in-versions-database/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-version-not-in-versions-database/vcpkg.json new file mode 100644 index 0000000000..0043df67b2 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/override-version-not-in-versions-database/vcpkg.json @@ -0,0 +1,10 @@ +{ + "name": "override-version-not-in-versions-database", + "version": "1.0", + "overrides": [ + { + "name": "good", + "version": "0.9" + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-mismatch/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-mismatch/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-mismatch/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json new file mode 100644 index 0000000000..cc609c6036 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "version-mismatch", + "version": "1.1" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-missing/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-missing/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-missing/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-missing/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-missing/vcpkg.json new file mode 100644 index 0000000000..9990713c6d --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-missing/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "version-missing", + "version": "1.1" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-scheme-mismatch/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-scheme-mismatch/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-scheme-mismatch/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json new file mode 100644 index 0000000000..d71e35cc7c --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "version-scheme-mismatch", + "version": "1.1" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/bad-git-tree.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/bad-git-tree.json new file mode 100644 index 0000000000..2918fc4661 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/bad-git-tree.json @@ -0,0 +1,14 @@ +{ + "versions": [ + { + "git-tree": "000000070c5f496fcf1a97cf654d5e81f0d2685a", + "version": "1.1", + "port-version": 0 + }, + { + "git-tree": "00000005fb6b76058ce09252f521847363c6b266", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/bad-history-name.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/bad-history-name.json new file mode 100644 index 0000000000..e81800032e --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/bad-history-name.json @@ -0,0 +1,14 @@ +{ + "versions": [ + { + "git-tree": "f34f4ad3dfcc4d46d467d7b6aa04f9732a7951d6", + "version": "1.1", + "port-version": 0 + }, + { + "git-tree": "db9d98300e7daeb2c0652bae94a0283a1b1a13d1", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/baseline-version-mismatch.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/baseline-version-mismatch.json new file mode 100644 index 0000000000..75204c85f1 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/baseline-version-mismatch.json @@ -0,0 +1,14 @@ +{ + "versions": [ + { + "git-tree": "cf8a1faa9f94f7ceb9513d65093d407e11ac1402", + "version": "1.1", + "port-version": 0 + }, + { + "git-tree": "a6d7dde2f5a9ea80db16c7f73c43556a7e21e5cf", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/baseline-version-missing.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/baseline-version-missing.json new file mode 100644 index 0000000000..6a6605ebe9 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/b-/baseline-version-missing.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "git-tree": "a5c21769008f52ed66afa344f13b786dde4b8d7d", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/baseline.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/baseline.json new file mode 100644 index 0000000000..96a69166a1 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/baseline.json @@ -0,0 +1,72 @@ +{ + "default": { + "bad-git-tree": { + "baseline": "1.1", + "port-version": 0 + }, + "bad-history-name": { + "baseline": "1.1", + "port-version": 0 + }, + "baseline-version-mismatch": { + "baseline": "1.0", + "port-version": 0 + }, + "dependency-not-in-versions-database": { + "baseline": "1.0", + "port-version": 0 + }, + "dependency-not-in-versions-database-feature": { + "baseline": "1.0", + "port-version": 0 + }, + "dependency-version-not-in-versions-database": { + "baseline": "1.0", + "port-version": 0 + }, + "dependency-version-not-in-versions-database-feature": { + "baseline": "1.0", + "port-version": 0 + }, + "empty-versions": { + "baseline": "1.0", + "port-version": 0 + }, + "good": { + "baseline": "1.0", + "port-version": 0 + }, + "malformed": { + "baseline": "1.0", + "port-version": 0 + }, + "mismatch-git-tree": { + "baseline": "1.0", + "port-version": 0 + }, + "no-versions": { + "baseline": "1.0", + "port-version": 0 + }, + "override-not-in-versions-database": { + "baseline": "1.0", + "port-version": 0 + }, + "override-version-not-in-versions-database": { + "baseline": "1.0", + "port-version": 0 + }, + "version-mismatch": { + "baseline": "1.1", + "port-version": 0 + }, + "version-missing": { + "baseline": "1.1", + "port-version": 0 + }, + "version-scheme-mismatch": { + "baseline": "1.1", + "port-version": 0 + } + } +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database-feature.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database-feature.json new file mode 100644 index 0000000000..6ac3cc1b2c --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database-feature.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "git-tree": "2298ee25ea54ed92595250a2be07d01bdd76f47c", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database.json new file mode 100644 index 0000000000..670e02ea77 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "git-tree": "321c8b400526dc412a987285ef469eec6221a4b4", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database-feature.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database-feature.json new file mode 100644 index 0000000000..399bfc5d06 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database-feature.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "git-tree": "ba3008bb2d42c61f172b7d9592de0212edf20fc6", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database.json new file mode 100644 index 0000000000..371981acf3 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "git-tree": "f0d44555fe7714929e432ab9e12a436e28ffef9e", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/g-/good.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/g-/good.json new file mode 100644 index 0000000000..38366a09dc --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/g-/good.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "git-tree": "0f3d67db0dbb6aa5499bc09367a606b495e16d35", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/m-/malformed.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/m-/malformed.json new file mode 100644 index 0000000000..7ad4853f4b --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/m-/malformed.json @@ -0,0 +1,14 @@ +{ + "versions": [ + { + "git-tree": "a1f22424b0fb1460200c12e1b7933f309f9c8373", + "version": "1.1", + "port-version": 0 + }, + { + "git-tree": "72b37802dbdc176ce20b718ce4a332ac38bd0116", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json new file mode 100644 index 0000000000..3ff9b857c6 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "git-tree": "41d20d2a02d75343b0933b624faf9f061b112dad", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/o-/override-not-in-versions-database.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/o-/override-not-in-versions-database.json new file mode 100644 index 0000000000..33d069fb05 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/o-/override-not-in-versions-database.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "git-tree": "0ff80cd22d5ca881efab3329ce596566a8642bec", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/o-/override-version-not-in-versions-database.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/o-/override-version-not-in-versions-database.json new file mode 100644 index 0000000000..ac1bb00cad --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/o-/override-version-not-in-versions-database.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "git-tree": "49fafaad46408296e50e9d0fd1a3d531bf97d420", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-mismatch.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-mismatch.json new file mode 100644 index 0000000000..9328f1244a --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-mismatch.json @@ -0,0 +1,14 @@ +{ + "versions": [ + { + "git-tree": "220bdcf2d4836ec9fe867eaff2945b58c08f5618", + "version": "1.1-a", + "port-version": 0 + }, + { + "git-tree": "5c1a69be3303fcd085d473d10e311b85202ee93c", + "version": "1.0-a", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-missing.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-missing.json new file mode 100644 index 0000000000..5a73a4d89b --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-missing.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "git-tree": "d3b4c8bf4bee7654f63b223a442741bb16f45957", + "version": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json new file mode 100644 index 0000000000..a24ba4b01a --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json @@ -0,0 +1,14 @@ +{ + "versions": [ + { + "git-tree": "ea2006a1188b81f1f2f6e0aba9bef236d1fb2725", + "version-string": "1.1", + "port-version": 0 + }, + { + "git-tree": "89c88798a9fa17ea6753da87887a1fec48c421b0", + "version-string": "1.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 new file mode 100644 index 0000000000..a87db47d83 --- /dev/null +++ b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 @@ -0,0 +1,153 @@ +. "$PSScriptRoot/../end-to-end-tests-prelude.ps1" + +Refresh-TestRoot +Copy-Item -Recurse "$PSScriptRoot/../e2e-assets/ci-verify-versions-registry" "$TestingRoot/ci-verify-versions-registry" +git -C "$TestingRoot/ci-verify-versions-registry" init +git -C "$TestingRoot/ci-verify-versions-registry" add -A +git -C "$TestingRoot/ci-verify-versions-registry" commit -m testing +$git = (Get-Command git).Path +$expected = @" +$TestingRoot/ci-verify-versions-registry/ports/malformed/vcpkg.json:4:3: error: Unexpected character; expected property name + on expression: ~broken + ^ +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: bad-git-tree@1.1 is declared to have git tree 000000070c5f496fcf1a97cf654d5e81f0d2685a, but the local port $TestingRoot/ci-verify-versions-registry/ports/bad-git-tree has git tree 6528b2c70c5f496fcf1a97cf654d5e81f0d2685a +note: If bad-git-tree@1.1 is already published, update the bad-git-tree manifest with a new version or port-version, then add the new version by running: + vcpkg x-add-version bad-git-tree + git add versions + git commit -m `"Update version database`" +note: if bad-git-tree@1.1 is not yet published, overwrite the previous git tree by running: + vcpkg x-add-version bad-git-tree --overwrite-version + git add versions + git commit -m `"Update version database`" +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: bad-git-tree@1.1 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/bad-history-name: message: bad-history-name@1.1 is correctly in the version database (f34f4ad3dfcc4d46d467d7b6aa04f9732a7951d6) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: bad-history-name@1.1 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/bad-history-name/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch: message: baseline-version-mismatch@1.1 is correctly in the version database (cf8a1faa9f94f7ceb9513d65093d407e11ac1402) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: baseline-version-mismatch is declared at version 1.0, but the local port is 1.1 +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json: note: baseline-version-mismatch is declared here +note: you can run the following commands to add the current version of baseline-version-mismatch automatically: + vcpkg x-add-version baseline-version-mismatch + git add versions + git commit -m `"Update version database`" +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing: message: baseline-version-missing@1.0 is correctly in the version database (a5c21769008f52ed66afa344f13b786dde4b8d7d) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: no version of baseline-version-missing is set +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json: note: baseline-version-missing is declared here +note: you can run the following commands to add the current version of baseline-version-missing automatically: + vcpkg x-add-version baseline-version-missing + git add versions + git commit -m `"Update version database`" +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database: message: dependency-not-in-versions-database@1.0 is correctly in the version database (321c8b400526dc412a987285ef469eec6221a4b4) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-not-in-versions-database@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database/vcpkg.json: error: the dependency no-versions does not exist in the version database; does that port exist? +$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature: message: dependency-not-in-versions-database-feature@1.0 is correctly in the version database (2298ee25ea54ed92595250a2be07d01bdd76f47c) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-not-in-versions-database-feature@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature/vcpkg.json: error: the dependency no-versions does not exist in the version database; does that port exist? +note: the dependency is in the feature named add-things +$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database: message: dependency-version-not-in-versions-database@1.0 is correctly in the version database (f0d44555fe7714929e432ab9e12a436e28ffef9e) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-version-not-in-versions-database@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/vcpkg.json: error: the "version>=" constraint to good names version 0.9 which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. Consider removing the version constraint or choosing a value declared in $TestingRoot/ci-verify-versions-registry/versions/g-/good.json. +$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature: message: dependency-version-not-in-versions-database-feature@1.0 is correctly in the version database (ba3008bb2d42c61f172b7d9592de0212edf20fc6) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-version-not-in-versions-database-feature@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/vcpkg.json: error: the "version>=" constraint to good names version 0.9 which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. Consider removing the version constraint or choosing a value declared in $TestingRoot/ci-verify-versions-registry/versions/g-/good.json. +note: the dependency is in the feature named add-things +$TestingRoot/ci-verify-versions-registry/ports/good: message: good@1.0 is correctly in the version database (0f3d67db0dbb6aa5499bc09367a606b495e16d35) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: good@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/good/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json: error: mismatch-git-tree@1.0 is declared to have git tree 41d20d2a02d75343b0933b624faf9f061b112dad, but the local port $TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree has git tree 34b3289caaa7a97950828905d354dc971c3c15a7 +note: If mismatch-git-tree@1.0 is already published, update the mismatch-git-tree manifest with a new version or port-version, then add the new version by running: + vcpkg x-add-version mismatch-git-tree + git add versions + git commit -m `"Update version database`" +note: if mismatch-git-tree@1.0 is not yet published, overwrite the previous git tree by running: + vcpkg x-add-version mismatch-git-tree --overwrite-version + git add versions + git commit -m `"Update version database`" +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: mismatch-git-tree@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/no-versions/vcpkg.json: error: missing a version database file at $TestingRoot/ci-verify-versions-registry/versions/n-/no-versions.json +note: run 'vcpkg x-add-version no-versions' to create the version database file. +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: no-versions@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/no-versions/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/override-not-in-versions-database: message: override-not-in-versions-database@1.0 is correctly in the version database (0ff80cd22d5ca881efab3329ce596566a8642bec) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: override-not-in-versions-database@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/override-not-in-versions-database/vcpkg.json: error: the version override no-versions does not exist in the version database; does that port exist? +$TestingRoot/ci-verify-versions-registry/ports/override-version-not-in-versions-database: message: override-version-not-in-versions-database@1.0 is correctly in the version database (49fafaad46408296e50e9d0fd1a3d531bf97d420) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: override-version-not-in-versions-database@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/override-version-not-in-versions-database/vcpkg.json: error: the override of good names version 0.9 which does not exist in the version database. Installing this port at the top level will fail as that version will be unresolvable. Consider removing the version override or choosing a value declared in $TestingRoot/ci-verify-versions-registry/versions/g-/good.json. +$TestingRoot/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json: error: version-mismatch@1.1 was not found in versions database $TestingRoot/ci-verify-versions-registry/versions/v-/version-mismatch.json. +note: run 'vcpkg x-add-version version-mismatch' to add the new port version. +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-mismatch@1.1 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/version-missing/vcpkg.json: error: version-missing@1.1 was not found in versions database $TestingRoot/ci-verify-versions-registry/versions/v-/version-missing.json. +note: run 'vcpkg x-add-version version-missing' to add the new port version. +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-missing@1.1 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/version-missing/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json: error: 1.1 is declared version-string, but version-scheme-mismatch is declared with version +$TestingRoot/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json: note: version-scheme-mismatch is declared here +note: versions must be unique, even if they are declared with different schemes +note: you can overwrite version-scheme-mismatch@1.1 with correct local values by running: +vcpkg x-add-version version-scheme-mismatch --overwrite-version +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-scheme-mismatch@1.1 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: failed to execute: `"$git`" `"--git-dir=$TestingRoot/ci-verify-versions-registry/.git`" `"--work-tree=$buildtreesRoot/versioning_/versions/bad-git-tree/000000070c5f496fcf1a97cf654d5e81f0d2685a_82336.tmp`" -c core.autocrlf=false read-tree -m -u 000000070c5f496fcf1a97cf654d5e81f0d2685a +error: git failed with exit code: (128). +fatal: failed to unpack tree object 000000070c5f496fcf1a97cf654d5e81f0d2685a +note: while checking out port bad-git-tree with git tree 000000070c5f496fcf1a97cf654d5e81f0d2685a +note: while validating version: 1.1 +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: failed to execute: `"$git`" `"--git-dir=$TestingRoot/ci-verify-versions-registry/.git`" `"--work-tree=$buildtreesRoot/versioning_/versions/bad-git-tree/00000005fb6b76058ce09252f521847363c6b266_82336.tmp`" -c core.autocrlf=false read-tree -m -u 00000005fb6b76058ce09252f521847363c6b266 +error: git failed with exit code: (128). +fatal: failed to unpack tree object 00000005fb6b76058ce09252f521847363c6b266 +note: while checking out port bad-git-tree with git tree 00000005fb6b76058ce09252f521847363c6b266 +note: while validating version: 1.0 +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-history-name.json: message: bad-history-name@1.1 is correctly in the version database (f34f4ad3dfcc4d46d467d7b6aa04f9732a7951d6) +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-history-name.json: error: db9d98300e7daeb2c0652bae94a0283a1b1a13d1 is declared to contain bad-history-name@1.0, but appears to contain bad-history-name-is-bad@1.0 +$TestingRoot/ci-verify-versions-registry/versions/b-/baseline-version-mismatch.json: message: baseline-version-mismatch@1.1 is correctly in the version database (cf8a1faa9f94f7ceb9513d65093d407e11ac1402) +$TestingRoot/ci-verify-versions-registry/versions/b-/baseline-version-mismatch.json: message: baseline-version-mismatch@1.0 is correctly in the version database (a6d7dde2f5a9ea80db16c7f73c43556a7e21e5cf) +$TestingRoot/ci-verify-versions-registry/versions/b-/baseline-version-missing.json: message: baseline-version-missing@1.0 is correctly in the version database (a5c21769008f52ed66afa344f13b786dde4b8d7d) +$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database.json: message: dependency-not-in-versions-database@1.0 is correctly in the version database (321c8b400526dc412a987285ef469eec6221a4b4) +$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database-feature.json: message: dependency-not-in-versions-database-feature@1.0 is correctly in the version database (2298ee25ea54ed92595250a2be07d01bdd76f47c) +$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database.json: message: dependency-version-not-in-versions-database@1.0 is correctly in the version database (f0d44555fe7714929e432ab9e12a436e28ffef9e) +$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database-feature.json: message: dependency-version-not-in-versions-database-feature@1.0 is correctly in the version database (ba3008bb2d42c61f172b7d9592de0212edf20fc6) +$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: message: good@1.0 is correctly in the version database (0f3d67db0dbb6aa5499bc09367a606b495e16d35) +$TestingRoot/ci-verify-versions-registry/versions/m-/malformed.json: $buildtreesRoot/versioning_/versions/malformed/a1f22424b0fb1460200c12e1b7933f309f9c8373/vcpkg.json:4:3: error: Unexpected character; expected property name + on expression: ~broken + ^ +note: while validating version: 1.1 +$TestingRoot/ci-verify-versions-registry/versions/m-/malformed.json: $buildtreesRoot/versioning_/versions/malformed/72b37802dbdc176ce20b718ce4a332ac38bd0116/vcpkg.json:4:3: error: Unexpected character; expected property name + on expression: ~broken + ^ +note: while validating version: 1.0 +$TestingRoot/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json: message: mismatch-git-tree@1.0 is correctly in the version database (41d20d2a02d75343b0933b624faf9f061b112dad) +$TestingRoot/ci-verify-versions-registry/versions/o-/override-not-in-versions-database.json: message: override-not-in-versions-database@1.0 is correctly in the version database (0ff80cd22d5ca881efab3329ce596566a8642bec) +$TestingRoot/ci-verify-versions-registry/versions/o-/override-version-not-in-versions-database.json: message: override-version-not-in-versions-database@1.0 is correctly in the version database (49fafaad46408296e50e9d0fd1a3d531bf97d420) +$TestingRoot/ci-verify-versions-registry/versions/v-/version-mismatch.json: error: 220bdcf2d4836ec9fe867eaff2945b58c08f5618 is declared to contain version-mismatch@1.1-a, but appears to contain version-mismatch@1.1 +$TestingRoot/ci-verify-versions-registry/versions/v-/version-mismatch.json: error: 5c1a69be3303fcd085d473d10e311b85202ee93c is declared to contain version-mismatch@1.0-a, but appears to contain version-mismatch@1.0 +$TestingRoot/ci-verify-versions-registry/versions/v-/version-missing.json: message: version-missing@1.0 is correctly in the version database (d3b4c8bf4bee7654f63b223a442741bb16f45957) +$TestingRoot/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json: error: 1.1 is declared version-string, but version-scheme-mismatch@ea2006a1188b81f1f2f6e0aba9bef236d1fb2725 is declared with version +$buildtreesRoot/versioning_/versions/version-scheme-mismatch/ea2006a1188b81f1f2f6e0aba9bef236d1fb2725/vcpkg.json: note: version-scheme-mismatch is declared here +note: versions must be unique, even if they are declared with different schemes +$TestingRoot/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json: error: 1.0 is declared version-string, but version-scheme-mismatch@89c88798a9fa17ea6753da87887a1fec48c421b0 is declared with version +$buildtreesRoot/versioning_/versions/version-scheme-mismatch/89c88798a9fa17ea6753da87887a1fec48c421b0/vcpkg.json: note: version-scheme-mismatch is declared here +note: versions must be unique, even if they are declared with different schemes + +"@ + +$actual = Run-VcpkgAndCaptureOutput x-ci-verify-versions @directoryArgs "--x-builtin-ports-root=$TestingRoot/ci-verify-versions-registry/ports" "--x-builtin-registry-versions-dir=$TestingRoot/ci-verify-versions-registry/versions" --verbose --verify-git-trees +Throw-IfNotFailed + +$workTreeRegex = '"--work-tree=[^"]+\.tmp' # This has an unpredictable PID inside +$expected = $expected.Replace('\', '/') +$expected = [System.Text.RegularExpressions.Regex]::Replace($expected, $workTreeRegex, '') +$actual = $actual.Replace('\', '/') +$actual = [System.Text.RegularExpressions.Regex]::Replace($actual, $workTreeRegex, '') +if ($actual -ne $expected) { + Write-Host "Expected:" + Write-Host $expected + Write-Host "Actual:" + Write-Host $actual + throw "Bad x-ci-verify-versions output." +} diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 1ddf052714..53d308c62b 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -56,7 +56,10 @@ DECLARE_MESSAGE(AddVersionIgnoringOptionAll, (msg::option), "The -- before {option} must be preserved as they're part of the help message for the user.", "ignoring --{option} since a port name argument was provided") -DECLARE_MESSAGE(AddVersionLoadPortFailed, (msg::package_name), "", "can't load port {package_name}") +DECLARE_MESSAGE(AddVersionInstructions, + (msg::package_name), + "", + "you can run the following commands to add the current version of {package_name} automatically:") DECLARE_MESSAGE(AddVersionNewFile, (), "", "(new file)") DECLARE_MESSAGE(AddVersionNewShaIs, (msg::commit_sha), "", "new SHA: {commit_sha}") DECLARE_MESSAGE(AddVersionNoFilesUpdated, (), "", "No files were updated") @@ -292,14 +295,7 @@ DECLARE_MESSAGE(BaselineGitShowFailed, "", "while checking out baseline from commit '{commit_sha}', failed to `git show` " "versions/baseline.json. This may be fixed by fetching commits with `git fetch`.") -DECLARE_MESSAGE(BaselineMissing, - (msg::package_name, msg::version), - "", - "Baseline version not found. Run:\n" - "vcpkg x-add-version {package_name}\n" - "git add versions\n" - "git commit -m \"Update version database\"\n" - "to set {version} as the baseline version.") +DECLARE_MESSAGE(BaselineMissing, (msg::package_name), "", "no version of {package_name} is set") DECLARE_MESSAGE(BaselineMissingDefault, (msg::commit_sha, msg::url), "", @@ -418,7 +414,6 @@ DECLARE_MESSAGE(BuildTroubleshootingMessage4, "Please use the prefilled template from {path} when reporting your issue.") DECLARE_MESSAGE(BuiltInTriplets, (), "", "Built-in Triplets:") DECLARE_MESSAGE(BuiltWithIncorrectArchitecture, (), "", "The following files were built for an incorrect architecture:") -DECLARE_MESSAGE(CheckedOutGitSha, (msg::commit_sha), "", "Checked out Git SHA: {commit_sha}") DECLARE_MESSAGE(ChecksFailedCheck, (), "", "vcpkg has crashed; no additional details are available.") DECLARE_MESSAGE(ChecksUnreachableCode, (), "", "unreachable code was reached") DECLARE_MESSAGE(ChecksUpdateVcpkg, (), "", "updating vcpkg by rerunning bootstrap-vcpkg may resolve this failure.") @@ -1016,7 +1011,7 @@ DECLARE_MESSAGE( DECLARE_MESSAGE(DependencyGraphCalculation, (), "", "Dependency graph submission enabled.") DECLARE_MESSAGE(DependencyGraphFailure, (), "", "Dependency graph submission failed.") DECLARE_MESSAGE(DependencyGraphSuccess, (), "", "Dependency graph submission successful.") -DECLARE_MESSAGE(DependencyInFeature, (msg::feature), "", "the dependency is in the feature named {feature}.") +DECLARE_MESSAGE(DependencyInFeature, (msg::feature), "", "the dependency is in the feature named {feature}") DECLARE_MESSAGE(DependencyNotInVersionDatabase, (msg::package_name), "", @@ -1388,6 +1383,10 @@ DECLARE_MESSAGE(GHAParametersMissing, "The GHA binary source requires the ACTIONS_RUNTIME_TOKEN and ACTIONS_CACHE_URL environment variables " "to be set. See {url} for details.") DECLARE_MESSAGE(GitCommandFailed, (msg::command_line), "", "failed to execute: {command_line}") +DECLARE_MESSAGE(GitCommitUpdateVersionDatabase, + (), + "This is a command line; only the 'update version database' part should be localized", + "git commit -m \"Update version database\"") DECLARE_MESSAGE(GitFailedToFetch, (msg::value, msg::url), "{value} is a git ref like 'origin/main'", @@ -1410,10 +1409,6 @@ DECLARE_MESSAGE(GitUnexpectedCommandOutputCmd, (msg::command_line), "", "git produced unexpected output when running {command_line}") -DECLARE_MESSAGE(GitCommitUpdateVersionDatabase, - (), - "This is a command line; only the 'update version database' part should be localized", - "git commit -m \"Update version database\"") DECLARE_MESSAGE(GraphCycleDetected, (msg::package_name), "A list of package names comprising the cycle will be printed after this message.", @@ -1946,7 +1941,6 @@ DECLARE_MESSAGE( "Invalid {system_name} linkage type: [{value}]") DECLARE_MESSAGE(InvalidLogicExpressionUnexpectedCharacter, (), "", "invalid logic expression, unexpected character") DECLARE_MESSAGE(InvalidLogicExpressionUsePipe, (), "", "invalid logic expression, use '|' rather than 'or'") -DECLARE_MESSAGE(InvalidNoVersions, (), "", "File contains no versions.") DECLARE_MESSAGE(InvalidOptionForRemove, (), "'remove' is a command that should not be changed.", @@ -2495,6 +2489,10 @@ DECLARE_MESSAGE(PortBugSetDllsWithoutExports, "following line in the portfile:\n" "set(VCPKG_POLICY_DLLS_WITHOUT_EXPORTS enabled)\n" "The following DLLs have no exports:") +DECLARE_MESSAGE(PortDeclaredHere, + (msg::package_name), + "This is printed after NoteMessage to tell the user the path on disk of a related port", + "{package_name} is declared here") DECLARE_MESSAGE(PortDependencyConflict, (msg::package_name), "", @@ -2965,13 +2963,8 @@ DECLARE_MESSAGE(VcvarsRunFailedExitCode, DECLARE_MESSAGE(VersionBaselineMatch, (msg::version_spec), "", "message: {version_spec} matches the current baseline") DECLARE_MESSAGE(VersionBaselineMismatch, (msg::expected, msg::actual, msg::package_name), - "{expected} and {actual} are versions", - "The latest version is {expected}, but the baseline file contains {actual}.\n" - "Run:\n" - "vcpkg x-add-version {package_name}\n" - "git add versions\n" - "git commit -m \"Update version database\"\n" - "to update the baseline version.") + "{actual} and {expected} are versions", + "{package_name} is declared at version {actual}, but the local port is {expected}") DECLARE_MESSAGE(VersionBuiltinPortTreeEntryMissing, (msg::package_name, msg::expected, msg::actual), "{expected} and {actual} are versions like 1.0.", @@ -3039,9 +3032,9 @@ DECLARE_MESSAGE(VersionIncomparable3, "This can be resolved by adding an explicit override to the preferred version. For example:") DECLARE_MESSAGE(VersionIncomparable4, (msg::url), "", "See `vcpkg help versioning` or {url} for more information.") DECLARE_MESSAGE(VersionInDeclarationDoesNotMatch, - (msg::version), - "", - "The version declared in file does not match checked-out version: {version}") + (msg::commit_sha, msg::expected, msg::actual), + "{expected} and {actual} are version specs", + "{commit_sha} is declared to contain {expected}, but appears to contain {actual}") DECLARE_MESSAGE( VersionInvalidDate, (msg::version), @@ -3085,6 +3078,10 @@ DECLARE_MESSAGE( "the override of {package_name} names version {version} which does not exist in the " "version database. Installing this port at the top level will fail as that version will be unresolvable. " "Consider removing the version override or choosing a value declared in {path}.") +DECLARE_MESSAGE(VersionOverwriteVersion, + (msg::version_spec), + "", + "you can overwrite {version_spec} with correct local values by running:") DECLARE_MESSAGE(VersionRejectedDueToBaselineMissing, (msg::path, msg::json_field), "", @@ -3097,28 +3094,32 @@ DECLARE_MESSAGE(VersionRejectedDueToFeatureFlagOff, "{path} was rejected because it uses \"{json_field}\" and the `versions` feature flag is disabled. " "This can be fixed by removing \"{json_field}\" or enabling the `versions` feature flag.\nSee " "`vcpkg help versioning` for more information.") -DECLARE_MESSAGE(VersionSchemeMismatch, - (msg::version, msg::expected, msg::actual, msg::path, msg::package_name), +DECLARE_MESSAGE(VersionSchemeMismatch1, + (msg::version, msg::expected, msg::actual, msg::package_name), "{expected} and {actual} are version schemes; it here refers to the {version}", - "The version database declares {version} as {expected}, but {path} declares it as {actual}. " - "Versions must be unique, even if they are declared with different schemes.\n" - "note: run:\n" - "vcpkg x-add-version {package_name} --overwrite-version\n" - "to overwrite the scheme declared in the version database with that declared in the port.") + "{version} is declared {expected}, but {package_name} is declared with {actual}") +DECLARE_MESSAGE(VersionSchemeMismatch1Old, + (msg::version, msg::expected, msg::actual, msg::package_name, msg::commit_sha), + "{expected} and {actual} are version schemes; it here refers to the {version}", + "{version} is declared {expected}, but {package_name}@{commit_sha} is declared with {actual}") +DECLARE_MESSAGE(VersionSchemeMismatch2, + (), + "", + "versions must be unique, even if they are declared with different schemes") DECLARE_MESSAGE( VersionShaMismatch1, (msg::version_spec, msg::expected, msg::actual, msg::package_name, msg::path), "{expected} and {actual} are git tree SHAs. Console commands the user can run are printed after. 'git tree' is " "https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish", "{version_spec} is declared to have git tree {expected}, but the local port {path} has git tree " - "{actual}.\n" + "{actual}\n" "note: If {version_spec} is already published, update the {package_name} manifest with a new version or " "port-version, then add the new version by running:") DECLARE_MESSAGE(VersionShaMismatch2, (msg::version_spec), "Console commands the user can run are printed after. 'git tree' is " "https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish", - "note: If {version_spec} is not yet published, overwrite the previous git tree by running:") + "note: if {version_spec} is not yet published, overwrite the previous git tree by running:") DECLARE_MESSAGE(VersionShaMissing, (msg::package_name, msg::path), "", diff --git a/locales/messages.json b/locales/messages.json index 06270c5207..2b0aaebf52 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -69,8 +69,8 @@ "_AddVersionFormatPortSuggestion.comment": "An example of {command_line} is vcpkg install zlib.", "AddVersionIgnoringOptionAll": "ignoring --{option} since a port name argument was provided", "_AddVersionIgnoringOptionAll.comment": "The -- before {option} must be preserved as they're part of the help message for the user. An example of {option} is editable.", - "AddVersionLoadPortFailed": "can't load port {package_name}", - "_AddVersionLoadPortFailed.comment": "An example of {package_name} is zlib.", + "AddVersionInstructions": "you can run the following commands to add the current version of {package_name} automatically:", + "_AddVersionInstructions.comment": "An example of {package_name} is zlib.", "AddVersionNewFile": "(new file)", "AddVersionNewShaIs": "new SHA: {commit_sha}", "_AddVersionNewShaIs.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", @@ -196,8 +196,8 @@ "_BaselineFileNoDefaultFieldPath.comment": "An example of {path} is /foo/bar.", "BaselineGitShowFailed": "while checking out baseline from commit '{commit_sha}', failed to `git show` versions/baseline.json. This may be fixed by fetching commits with `git fetch`.", "_BaselineGitShowFailed.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", - "BaselineMissing": "Baseline version not found. Run:\nvcpkg x-add-version {package_name}\ngit add versions\ngit commit -m \"Update version database\"\nto set {version} as the baseline version.", - "_BaselineMissing.comment": "An example of {package_name} is zlib. An example of {version} is 1.3.8.", + "BaselineMissing": "no version of {package_name} is set", + "_BaselineMissing.comment": "An example of {package_name} is zlib.", "BaselineMissingDefault": "The baseline.json from commit `\"{commit_sha}\"` in the repo {url} was invalid (did not contain a \"default\" field).", "_BaselineMissingDefault.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949. An example of {url} is https://github.com/microsoft/vcpkg.", "BinaryCacheVendorHTTP": "HTTP servers", @@ -277,8 +277,6 @@ "_CMakeToolChainFile.comment": "An example of {path} is /foo/bar.", "CMakeUsingExportedLibs": "To use exported libraries in CMake projects, add {value} to your CMake command line.", "_CMakeUsingExportedLibs.comment": "{value} is a CMake command line switch of the form -DFOO=BAR", - "CheckedOutGitSha": "Checked out Git SHA: {commit_sha}", - "_CheckedOutGitSha.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "ChecksFailedCheck": "vcpkg has crashed; no additional details are available.", "ChecksUnreachableCode": "unreachable code was reached", "ChecksUpdateVcpkg": "updating vcpkg by rerunning bootstrap-vcpkg may resolve this failure.", @@ -593,7 +591,7 @@ "DependencyGraphCalculation": "Dependency graph submission enabled.", "DependencyGraphFailure": "Dependency graph submission failed.", "DependencyGraphSuccess": "Dependency graph submission successful.", - "DependencyInFeature": "the dependency is in the feature named {feature}.", + "DependencyInFeature": "the dependency is in the feature named {feature}", "_DependencyInFeature.comment": "An example of {feature} is avisynthplus.", "DependencyNotInVersionDatabase": "the dependency {package_name} does not exist in the version database; does that port exist?", "_DependencyNotInVersionDatabase.comment": "An example of {package_name} is zlib.", @@ -1086,7 +1084,6 @@ "_InvalidLinkage.comment": "'{value}' is the linkage type vcpkg would did not understand. (Correct values would be static ofr dynamic) An example of {system_name} is Darwin.", "InvalidLogicExpressionUnexpectedCharacter": "invalid logic expression, unexpected character", "InvalidLogicExpressionUsePipe": "invalid logic expression, use '|' rather than 'or'", - "InvalidNoVersions": "File contains no versions.", "InvalidOptionForRemove": "'remove' accepts either libraries or '--outdated'", "_InvalidOptionForRemove.comment": "'remove' is a command that should not be changed.", "InvalidPortVersonName": "Found invalid port version file name: `{path}`.", @@ -1372,6 +1369,8 @@ "_PortBugRestrictedHeaderPaths.comment": "A list of restricted headers is printed after this message, one per line. ", "PortBugSetDllsWithoutExports": "DLLs without any exports are likely a bug in the build script. If this is intended, add the following line in the portfile:\nset(VCPKG_POLICY_DLLS_WITHOUT_EXPORTS enabled)\nThe following DLLs have no exports:", "_PortBugSetDllsWithoutExports.comment": "'exports' means an entry in a DLL's export table. After this message, one file path per line is printed listing each DLL with an empty export table.", + "PortDeclaredHere": "{package_name} is declared here", + "_PortDeclaredHere.comment": "This is printed after NoteMessage to tell the user the path on disk of a related port An example of {package_name} is zlib.", "PortDependencyConflict": "Port {package_name} has the following unsupported dependencies:", "_PortDependencyConflict.comment": "An example of {package_name} is zlib.", "PortDoesNotExist": "{package_name} does not exist", @@ -1644,8 +1643,8 @@ "_VcvarsRunFailedExitCode.comment": "An example of {exit_code} is 127.", "VersionBaselineMatch": "message: {version_spec} matches the current baseline", "_VersionBaselineMatch.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0.", - "VersionBaselineMismatch": "The latest version is {expected}, but the baseline file contains {actual}.\nRun:\nvcpkg x-add-version {package_name}\ngit add versions\ngit commit -m \"Update version database\"\nto update the baseline version.", - "_VersionBaselineMismatch.comment": "{expected} and {actual} are versions An example of {package_name} is zlib.", + "VersionBaselineMismatch": "{package_name} is declared at version {actual}, but the local port is {expected}", + "_VersionBaselineMismatch.comment": "{actual} and {expected} are versions An example of {package_name} is zlib.", "VersionBuiltinPortTreeEntryMissing": "no version database entry for {package_name} at {expected}; using the checked out ports tree version ({actual}).", "_VersionBuiltinPortTreeEntryMissing.comment": "{expected} and {actual} are versions like 1.0. An example of {package_name} is zlib.", "VersionCommandHeader": "vcpkg package management program version {version}\n\nSee LICENSE.txt for license information.", @@ -1666,8 +1665,8 @@ "_VersionDatabaseFileMissing.comment": "An example of {package_name} is zlib. An example of {path} is /foo/bar.", "VersionGitEntryMissing": "no version database entry for {package_name} at {version}.\nAvailable versions:", "_VersionGitEntryMissing.comment": "A list of versions, 1 per line, are printed after this message. An example of {package_name} is zlib. An example of {version} is 1.3.8.", - "VersionInDeclarationDoesNotMatch": "The version declared in file does not match checked-out version: {version}", - "_VersionInDeclarationDoesNotMatch.comment": "An example of {version} is 1.3.8.", + "VersionInDeclarationDoesNotMatch": "{commit_sha} is declared to contain {expected}, but appears to contain {actual}", + "_VersionInDeclarationDoesNotMatch.comment": "{expected} and {actual} are version specs An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "VersionIncomparable1": "version conflict on {spec}: {constraint_origin} required {expected}, which cannot be compared with the baseline version {actual}.", "_VersionIncomparable1.comment": "{expected} and {actual} are versions like 1.0 An example of {spec} is zlib:x64-windows. An example of {constraint_origin} is zlib:x64-windows@1.0.0.", "VersionIncomparable2": "{version_spec} has scheme {new_scheme}", @@ -1696,15 +1695,20 @@ "_VersionOverrideNotInVersionDatabase.comment": "An example of {package_name} is zlib.", "VersionOverrideVersionNotInVersionDatabase": "the override of {package_name} names version {version} which does not exist in the version database. Installing this port at the top level will fail as that version will be unresolvable. Consider removing the version override or choosing a value declared in {path}.", "_VersionOverrideVersionNotInVersionDatabase.comment": "An example of {package_name} is zlib. An example of {version} is 1.3.8. An example of {path} is /foo/bar.", + "VersionOverwriteVersion": "you can overwrite {version_spec} with correct local values by running:", + "_VersionOverwriteVersion.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0.", "VersionRejectedDueToBaselineMissing": "{path} was rejected because it uses \"{json_field}\" and does not have a \"builtin-baseline\". This can be fixed by removing the uses of \"{json_field}\" or adding a \"builtin-baseline\".\nSee `vcpkg help versioning` for more information.", "_VersionRejectedDueToBaselineMissing.comment": "An example of {path} is /foo/bar. An example of {json_field} is identifer.", "VersionRejectedDueToFeatureFlagOff": "{path} was rejected because it uses \"{json_field}\" and the `versions` feature flag is disabled. This can be fixed by removing \"{json_field}\" or enabling the `versions` feature flag.\nSee `vcpkg help versioning` for more information.", "_VersionRejectedDueToFeatureFlagOff.comment": "An example of {path} is /foo/bar. An example of {json_field} is identifer.", - "VersionSchemeMismatch": "The version database declares {version} as {expected}, but {path} declares it as {actual}. Versions must be unique, even if they are declared with different schemes.\nnote: run:\nvcpkg x-add-version {package_name} --overwrite-version\nto overwrite the scheme declared in the version database with that declared in the port.", - "_VersionSchemeMismatch.comment": "{expected} and {actual} are version schemes; it here refers to the {version} An example of {version} is 1.3.8. An example of {path} is /foo/bar. An example of {package_name} is zlib.", - "VersionShaMismatch1": "{version_spec} is declared to have git tree {expected}, but the local port {path} has git tree {actual}.\nnote: If {version_spec} is already published, update the {package_name} manifest with a new version or port-version, then add the new version by running:", + "VersionSchemeMismatch1": "{version} is declared {expected}, but {package_name} is declared with {actual}", + "_VersionSchemeMismatch1.comment": "{expected} and {actual} are version schemes; it here refers to the {version} An example of {version} is 1.3.8. An example of {package_name} is zlib.", + "VersionSchemeMismatch1Old": "{version} is declared {expected}, but {package_name}@{commit_sha} is declared with {actual}", + "_VersionSchemeMismatch1Old.comment": "{expected} and {actual} are version schemes; it here refers to the {version} An example of {version} is 1.3.8. An example of {package_name} is zlib. An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", + "VersionSchemeMismatch2": "versions must be unique, even if they are declared with different schemes", + "VersionShaMismatch1": "{version_spec} is declared to have git tree {expected}, but the local port {path} has git tree {actual}\nnote: If {version_spec} is already published, update the {package_name} manifest with a new version or port-version, then add the new version by running:", "_VersionShaMismatch1.comment": "{expected} and {actual} are git tree SHAs. Console commands the user can run are printed after. 'git tree' is https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {package_name} is zlib. An example of {path} is /foo/bar.", - "VersionShaMismatch2": "note: If {version_spec} is not yet published, overwrite the previous git tree by running:", + "VersionShaMismatch2": "note: if {version_spec} is not yet published, overwrite the previous git tree by running:", "_VersionShaMismatch2.comment": "Console commands the user can run are printed after. 'git tree' is https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish An example of {version_spec} is zlib:x64-windows@1.0.0.", "VersionShaMissing": "Unknown git tree. This is usually caused by uncommitted changes.\nnote: You can commit your changes and add them to the version database by running:\ngit add \"{path}\"\ngit commit -m wip\nvcpkg x-add-version {package_name}\ngit add versions\ngit commit --amend -m \"[{package_name}] Add new port\"", "_VersionShaMissing.comment": "An example of {package_name} is zlib. An example of {path} is /foo/bar.", diff --git a/src/vcpkg/commands.add-version.cpp b/src/vcpkg/commands.add-version.cpp index 08ae0dda7f..811f57f4c3 100644 --- a/src/vcpkg/commands.add-version.cpp +++ b/src/vcpkg/commands.add-version.cpp @@ -403,7 +403,6 @@ namespace vcpkg auto scf = maybe_scf.get(); if (!scf) { - msg::println_error(msgAddVersionLoadPortFailed, msg::package_name = port_name); msg::println(Color::error, maybe_scf.error()); Checks::check_exit(VCPKG_LINE_INFO, !add_all); continue; diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index f2ab7d0fd8..260314f3e6 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -37,7 +37,8 @@ namespace const GitVersionDbEntry& version_entry) { bool success = true; - auto maybe_extracted_tree = paths.git_checkout_port(port_name, version_entry.git_tree, paths.root / ".git"); + auto maybe_extracted_tree = paths.git_checkout_port( + port_name, version_entry.git_tree, Path{paths.builtin_registry_versions.parent_path()} / ".git"); auto extracted_tree = maybe_extracted_tree.get(); if (!extracted_tree) { @@ -81,20 +82,19 @@ namespace } auto&& git_tree_version = scfl->source_control_file->to_schemed_version(); - if (version_entry.version.version != git_tree_version.version) + auto version_entry_spec = VersionSpec{port_name, version_entry.version.version}; + auto scfl_spec = scfl->source_control_file->to_version_spec(); + if (version_entry_spec != scfl_spec) { success = false; errors_sink.print(Color::error, LocalizedString::from_raw(versions_file_path) .append_raw(": ") .append(msgErrorMessage) - .append(msgVersionInDeclarationDoesNotMatch, msg::version = git_tree_version.version) - .append_raw('\n') - .append(msgNoteMessage) - .append(msgCheckedOutGitSha, msg::commit_sha = version_entry.git_tree) - .append_raw('\n') - .append(msgNoteMessage) - .append(msgWhileValidatingVersion, msg::version = version_entry.version.version) + .append(msgVersionInDeclarationDoesNotMatch, + msg::commit_sha = version_entry.git_tree, + msg::expected = version_entry_spec, + msg::actual = scfl_spec) .append_raw('\n')); } @@ -105,12 +105,20 @@ namespace LocalizedString::from_raw(versions_file_path) .append_raw(": ") .append(msgErrorMessage) - .append(msgVersionSchemeMismatch, + .append(msgVersionSchemeMismatch1Old, msg::version = version_entry.version.version, msg::expected = get_scheme_name(version_entry.version.scheme), msg::actual = get_scheme_name(git_tree_version.scheme), - msg::path = version_entry.git_tree, - msg::package_name = port_name) + msg::package_name = port_name, + msg::commit_sha = version_entry.git_tree) + .append_raw('\n') + .append_raw(scfl->control_location) + .append_raw(": ") + .append(msgNoteMessage) + .append(msgPortDeclaredHere, msg::package_name = port_name) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgVersionSchemeMismatch2) .append_raw('\n')); } @@ -158,17 +166,6 @@ namespace return success; } - if (entries->empty()) - { - success = false; - errors_sink.print(Color::error, - LocalizedString::from_raw(versions_database_entry.versions_file_path) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgInvalidNoVersions) - .append_raw('\n')); - } - const auto local_port_version = scfl.source_control_file->to_schemed_version(); auto versions_end = entries->end(); @@ -196,17 +193,29 @@ namespace { success = false; // assume the port is correct, so report the error on the version database file - errors_sink.print(Color::error, - LocalizedString::from_raw(versions_database_entry.versions_file_path) - .append_raw(": ") - .append(msgErrorMessage) - .append(msgVersionSchemeMismatch, - msg::version = version_entry.version.version, - msg::expected = get_scheme_name(version_entry.version.scheme), - msg::actual = get_scheme_name(local_port_version.scheme), - msg::path = scfl.port_directory(), - msg::package_name = port_name) - .append_raw('\n')); + errors_sink.print( + Color::error, + LocalizedString::from_raw(versions_database_entry.versions_file_path) + .append_raw(": ") + .append(msgErrorMessage) + .append(msgVersionSchemeMismatch1, + msg::version = version_entry.version.version, + msg::expected = get_scheme_name(version_entry.version.scheme), + msg::actual = get_scheme_name(local_port_version.scheme), + msg::package_name = port_name) + .append_raw('\n') + .append_raw(scfl.control_location) + .append_raw(": ") + .append(msgNoteMessage) + .append(msgPortDeclaredHere, msg::package_name = port_name) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgVersionSchemeMismatch2) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgVersionOverwriteVersion, + msg::version_spec = VersionSpec{port_name, local_port_version.version}) + .append_raw(fmt::format("\nvcpkg x-add-version {} --overwrite-version\n", port_name))); } if (local_git_tree != version_entry.git_tree) @@ -267,12 +276,25 @@ namespace if (maybe_baseline == baseline.end()) { errors_sink.print(Color::error, - LocalizedString::from_raw(scfl.control_location) + LocalizedString::from_raw(baseline_path) .append_raw(": ") .append(msgErrorMessage) - .append(msgBaselineMissing, - msg::package_name = port_name, - msg::version = local_port_version.version) + .append(msgBaselineMissing, msg::package_name = port_name) + .append_raw('\n') + .append_raw(scfl.control_location) + .append_raw(": ") + .append(msgNoteMessage) + .append(msgPortDeclaredHere, msg::package_name = port_name) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgAddVersionInstructions, msg::package_name = port_name) + .append_raw('\n') + .append_indent() + .append_raw(fmt::format("vcpkg x-add-version {}\n", port_name)) + .append_indent() + .append_raw("git add versions\n") + .append_indent() + .append(msgGitCommitUpdateVersionDatabase) .append_raw('\n')); return false; } @@ -297,6 +319,21 @@ namespace msg::expected = local_port_version.version, msg::actual = baseline_version, msg::package_name = port_name) + .append_raw('\n') + .append_raw(scfl.control_location) + .append_raw(": ") + .append(msgNoteMessage) + .append(msgPortDeclaredHere, msg::package_name = port_name) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgAddVersionInstructions, msg::package_name = port_name) + .append_raw('\n') + .append_indent() + .append_raw(fmt::format("vcpkg x-add-version {}\n", port_name)) + .append_indent() + .append_raw("git add versions\n") + .append_indent() + .append(msgGitCommitUpdateVersionDatabase) .append_raw('\n')); return false; } @@ -540,8 +577,8 @@ namespace vcpkg auto entries = maybe_entries->get(); if (!entries) { - // missing version database entry is OK; should have been reported as one of the other error categories - // by one of the other checks + // missing version database entry is OK; should have been reported as one of the other error + // categories by one of the other checks continue; } diff --git a/src/vcpkg/commands.portsdiff.cpp b/src/vcpkg/commands.portsdiff.cpp index 81461da6a8..29698105fc 100644 --- a/src/vcpkg/commands.portsdiff.cpp +++ b/src/vcpkg/commands.portsdiff.cpp @@ -80,9 +80,9 @@ namespace std::map read_ports_from_commit(const VcpkgPaths& paths, const std::string& git_commit_id) { auto& fs = paths.get_filesystem(); - const auto dot_git_dir = paths.root / ".git"; + const auto dot_git_dir = Path{paths.builtin_ports_directory().parent_path()} / ".git"; const auto ports_dir_name = paths.builtin_ports_directory().filename(); - const auto temp_checkout_path = paths.root / fmt::format("{}-{}", ports_dir_name, git_commit_id); + const auto temp_checkout_path = paths.buildtrees() / fmt::format("{}-{}", ports_dir_name, git_commit_id); fs.create_directory(temp_checkout_path, IgnoreErrors{}); const auto checkout_this_dir = fmt::format(R"(.\{})", ports_dir_name); // Must be relative to the root of the repository diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index 6c57d41f62..ccfaef2b60 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -654,7 +654,7 @@ namespace { const auto destination_tmp = destination_parent / "baseline.json.tmp"; auto treeish = Strings::concat(commit_sha, ":versions/baseline.json"); - auto maybe_contents = paths.git_show(treeish, paths.root / ".git"); + auto maybe_contents = paths.git_show(treeish, Path{paths.builtin_registry_versions.parent_path()} / ".git"); if (auto contents = maybe_contents.get()) { std::error_code ec; @@ -1162,7 +1162,8 @@ namespace } const auto& git_tree = port_versions_soa.git_trees()[it - port_versions.begin()]; - return m_paths.git_checkout_port(port_name, git_tree, m_paths.root / ".git") + return m_paths + .git_checkout_port(port_name, git_tree, Path{m_paths.builtin_registry_versions.parent_path()} / ".git") .map([&git_tree](Path&& p) -> PortLocation { return { std::move(p), diff --git a/src/vcpkg/vcpkgpaths.cpp b/src/vcpkg/vcpkgpaths.cpp index 969e684552..ec312821ba 100644 --- a/src/vcpkg/vcpkgpaths.cpp +++ b/src/vcpkg/vcpkgpaths.cpp @@ -952,7 +952,7 @@ namespace vcpkg ExpectedL>> VcpkgPaths::git_get_local_port_treeish_map() const { - const auto local_repo = this->root / ".git"; + const auto local_repo = Path{this->builtin_registry_versions.parent_path()} / ".git"; const auto git_cmd = git_cmd_builder({}, {}) .string_arg("-C") .string_arg(this->builtin_ports_directory()) From cdcbfb565244b1b1438c05acabc3ec8c4bc009fe Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Sat, 30 Sep 2023 05:38:31 -0700 Subject: [PATCH 26/48] Tolerate no user.name etc. --- .../end-to-end-tests-dir/ci-verify-versions.ps1 | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 index a87db47d83..5b73cf6d4c 100644 --- a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 @@ -1,10 +1,17 @@ . "$PSScriptRoot/../end-to-end-tests-prelude.ps1" Refresh-TestRoot + +$gitConfigOptions = @( + '-c', 'user.name=Nobody', + '-c', 'user.email=nobody@example.com', + '-c', 'core.autocrlf=false' +) + Copy-Item -Recurse "$PSScriptRoot/../e2e-assets/ci-verify-versions-registry" "$TestingRoot/ci-verify-versions-registry" -git -C "$TestingRoot/ci-verify-versions-registry" init -git -C "$TestingRoot/ci-verify-versions-registry" add -A -git -C "$TestingRoot/ci-verify-versions-registry" commit -m testing +git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions init +git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions add -A +git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions commit -m testing $git = (Get-Command git).Path $expected = @" $TestingRoot/ci-verify-versions-registry/ports/malformed/vcpkg.json:4:3: error: Unexpected character; expected property name From 5c260310e0f89d7fa1ac85a5182f8a0e8c108f99 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Sat, 30 Sep 2023 13:03:36 -0700 Subject: [PATCH 27/48] Fix registries test that tried to set --x-builtin-registry-versions-dir to a non git dir --- .../e2e-ports/versions/baseline.json | 5 --- .../v-/vcpkg-internal-e2e-test-port.json | 8 ----- .../ci-verify-versions.ps1 | 6 ---- .../end-to-end-tests-dir/registries.ps1 | 36 +++++++++---------- azure-pipelines/end-to-end-tests-prelude.ps1 | 6 ++++ 5 files changed, 22 insertions(+), 39 deletions(-) delete mode 100644 azure-pipelines/e2e-ports/versions/baseline.json delete mode 100644 azure-pipelines/e2e-ports/versions/v-/vcpkg-internal-e2e-test-port.json diff --git a/azure-pipelines/e2e-ports/versions/baseline.json b/azure-pipelines/e2e-ports/versions/baseline.json deleted file mode 100644 index 2413f8afc6..0000000000 --- a/azure-pipelines/e2e-ports/versions/baseline.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "default": { - "vcpkg-internal-e2e-test-port": { "baseline": "1.0.0" } - } -} diff --git a/azure-pipelines/e2e-ports/versions/v-/vcpkg-internal-e2e-test-port.json b/azure-pipelines/e2e-ports/versions/v-/vcpkg-internal-e2e-test-port.json deleted file mode 100644 index ce7698ebb8..0000000000 --- a/azure-pipelines/e2e-ports/versions/v-/vcpkg-internal-e2e-test-port.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "versions": [ - { - "version-string": "1.0.0", - "git-tree": "1dc3e42a3c0cafe2884d379af4399273238b986e" - } - ] -} diff --git a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 index 5b73cf6d4c..bea42da09f 100644 --- a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 @@ -2,12 +2,6 @@ Refresh-TestRoot -$gitConfigOptions = @( - '-c', 'user.name=Nobody', - '-c', 'user.email=nobody@example.com', - '-c', 'core.autocrlf=false' -) - Copy-Item -Recurse "$PSScriptRoot/../e2e-assets/ci-verify-versions-registry" "$TestingRoot/ci-verify-versions-registry" git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions init git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions add -A diff --git a/azure-pipelines/end-to-end-tests-dir/registries.ps1 b/azure-pipelines/end-to-end-tests-dir/registries.ps1 index b3134d91ab..24cb90a80e 100644 --- a/azure-pipelines/end-to-end-tests-dir/registries.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/registries.ps1 @@ -3,17 +3,15 @@ $env:X_VCPKG_REGISTRIES_CACHE = Join-Path $TestingRoot 'registries' New-Item -ItemType Directory -Force $env:X_VCPKG_REGISTRIES_CACHE | Out-Null -$builtinRegistryArgs = $commonArgs + @("--x-builtin-registry-versions-dir=$PSScriptRoot/../e2e-ports/versions") - -Run-Vcpkg install @builtinRegistryArgs 'vcpkg-internal-e2e-test-port' +Run-Vcpkg install @commonArgs 'vcpkg-internal-e2e-test-port' Throw-IfNotFailed # We should not look into the versions directory unless we have a baseline, # even if we pass the registries feature flag -Run-Vcpkg install @builtinRegistryArgs --feature-flags=registries 'vcpkg-internal-e2e-test-port' +Run-Vcpkg install @commonArgs --feature-flags=registries 'vcpkg-internal-e2e-test-port' Throw-IfNotFailed -Run-Vcpkg install @builtinRegistryArgs --feature-flags=registries 'vcpkg-cmake' +Run-Vcpkg install @commonArgs --feature-flags=registries 'vcpkg-cmake' Throw-IfFailed Write-Trace "Test git and filesystem registries" @@ -33,9 +31,13 @@ Copy-Item -Recurse ` New-Item ` -Path "$filesystemRegistry/versions" ` -ItemType Directory -Copy-Item ` - -LiteralPath "$PSScriptRoot/../e2e-ports/versions/baseline.json" ` - -Destination "$filesystemRegistry/versions/baseline.json" +Set-Content -Value @" +{ + "default": { + "vcpkg-internal-e2e-test-port": { "baseline": "1.0.0" } + } +} +"@ -LiteralPath "$filesystemRegistry/versions/baseline.json" New-Item ` -Path "$filesystemRegistry/versions/v-" ` -ItemType Directory @@ -62,12 +64,6 @@ $gitRegistryUpstream = (Get-Item $gitRegistryUpstream).FullName Push-Location $gitRegistryUpstream try { - $gitConfigOptions = @( - '-c', 'user.name=Nobody', - '-c', 'user.email=nobody@example.com', - '-c', 'core.autocrlf=false' - ) - $gitMainBranch = 'main' $gitSecondaryBranch = 'secondary' @@ -221,7 +217,7 @@ try New-Item -Path 'vcpkg-configuration.json' -ItemType File ` -Value (ConvertTo-Json -Depth 5 -InputObject $vcpkgConfigurationJson) - Run-Vcpkg install @builtinRegistryArgs '--feature-flags=registries,manifests' + Run-Vcpkg install @commonArgs '--feature-flags=registries,manifests' Throw-IfFailed } finally @@ -267,7 +263,7 @@ try New-Item -Path 'vcpkg-configuration.json' -ItemType File ` -Value (ConvertTo-Json -Depth 5 -InputObject $vcpkgConfigurationJson) - Run-Vcpkg install @builtinRegistryArgs '--feature-flags=registries,manifests' + Run-Vcpkg install @commonArgs '--feature-flags=registries,manifests' Throw-IfFailed } finally @@ -324,7 +320,7 @@ try New-Item -Path 'vcpkg-configuration.json' -ItemType File ` -Value (ConvertTo-Json -Depth 5 -InputObject $vcpkgConfigurationJson) - Run-Vcpkg install @builtinRegistryArgs '--feature-flags=registries,manifests' --dry-run + Run-Vcpkg install @commonArgs '--feature-flags=registries,manifests' --dry-run Throw-IfFailed Require-FileExists $env:X_VCPKG_REGISTRIES_CACHE/git-trees/$vcpkgInternalE2eTestPortGitTree Require-FileExists $env:X_VCPKG_REGISTRIES_CACHE/git-trees/$vcpkgInternalE2eTestPort2GitTree @@ -334,7 +330,7 @@ try # Dry run does not create a lockfile Require-FileNotExists $installRoot/vcpkg/vcpkg-lock.json - Run-Vcpkg install @builtinRegistryArgs '--feature-flags=registries,manifests' + Run-Vcpkg install @commonArgs '--feature-flags=registries,manifests' Throw-IfFailed $expectedVcpkgLockJson = "{$(ConvertTo-Json $gitRegistryUpstream):{ @@ -379,7 +375,7 @@ try } New-Item -Path $installRoot/vcpkg/vcpkg-lock.json -ItemType File ` -Value (ConvertTo-Json -Depth 5 -InputObject $vcpkgLockJson) - Run-Vcpkg install @builtinRegistryArgs '--feature-flags=registries,manifests' + Run-Vcpkg install @commonArgs '--feature-flags=registries,manifests' Throw-IfFailed } finally @@ -407,7 +403,7 @@ try New-Item -Path 'vcpkg.json' -ItemType File ` -Value (ConvertTo-Json -Depth 5 -InputObject $vcpkgJson) - Run-Vcpkg search @builtinRegistryArgs zlib + Run-Vcpkg search @commonArgs zlib Throw-IfFailed } finally diff --git a/azure-pipelines/end-to-end-tests-prelude.ps1 b/azure-pipelines/end-to-end-tests-prelude.ps1 index f8ec6de480..ec656f301f 100644 --- a/azure-pipelines/end-to-end-tests-prelude.ps1 +++ b/azure-pipelines/end-to-end-tests-prelude.ps1 @@ -19,6 +19,12 @@ $commonArgs = @( $Triplet ) + $directoryArgs +$gitConfigOptions = @( + '-c', 'user.name=Nobody', + '-c', 'user.email=nobody@example.com', + '-c', 'core.autocrlf=false' +) + $Script:CurrentTest = 'unassigned' function Refresh-TestRoot { From c77b92b7135a54f84b413747c56e4258337dbdc0 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 2 Oct 2023 02:23:10 -0700 Subject: [PATCH 28/48] Also fix broken versions e2e tests. --- .../end-to-end-tests-dir/versions.ps1 | 18 ++++++++++++++---- include/vcpkg/base/files.h | 1 + include/vcpkg/vcpkgpaths.h | 1 + src/vcpkg/base/files.cpp | 13 +++++++++++++ src/vcpkg/commands.ci-verify-versions.cpp | 4 ++-- src/vcpkg/commands.portsdiff.cpp | 4 +++- src/vcpkg/registries.cpp | 8 +++++--- src/vcpkg/vcpkgpaths.cpp | 7 ++++++- 8 files changed, 45 insertions(+), 11 deletions(-) diff --git a/azure-pipelines/end-to-end-tests-dir/versions.ps1 b/azure-pipelines/end-to-end-tests-dir/versions.ps1 index 8921ed1061..a8c649296c 100644 --- a/azure-pipelines/end-to-end-tests-dir/versions.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/versions.ps1 @@ -1,6 +1,18 @@ . $PSScriptRoot/../end-to-end-tests-prelude.ps1 -$versionFilesPath = "$PSScriptRoot/../e2e-ports/version-files" +$versionFilesPathSources = "$PSScriptRoot/../e2e-ports/version-files" +$versionFilesPath = "$TestingRoot/version-files" + +function Refresh-VersionFiles() { + Refresh-TestRoot + Copy-Item -Recurse $versionFilesPathSources $versionFilesPath + git -C $versionFilesPath @gitConfigOptions init + git -C $versionFilesPath @gitConfigOptions add -A + git -C $versionFilesPath @gitConfigOptions commit -m testing + git -C $versionFilesPath fetch https://github.com/vicroms/test-registries +} + +Refresh-VersionFiles # Ensure transitive packages can be used even if they add version constraints $CurrentTest = "transitive constraints without baseline" @@ -8,7 +20,6 @@ Run-Vcpkg install @commonArgs --dry-run ` "--x-builtin-ports-root=$versionFilesPath/transitive-constraints/ports" ` "--x-manifest-root=$versionFilesPath/transitive-constraints" Throw-IfFailed -Refresh-TestRoot # Test verify versions mkdir $VersionFilesRoot | Out-Null @@ -86,11 +97,10 @@ if (($out -notmatch ".*error: Failed to load port because versions are inconsist 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")) { Write-Trace "testing baselines: $opt_registries" - Refresh-TestRoot + Refresh-VersionFiles $CurrentTest = "without default baseline 2 -- enabling versions should not change behavior" Remove-Item -Recurse $buildtreesRoot/versioning_ -ErrorAction SilentlyContinue Run-Vcpkg @commonArgs "--feature-flags=versions$opt_registries" install ` diff --git a/include/vcpkg/base/files.h b/include/vcpkg/base/files.h index 2e6bc164cc..d7ffd92f8b 100644 --- a/include/vcpkg/base/files.h +++ b/include/vcpkg/base/files.h @@ -137,6 +137,7 @@ namespace vcpkg const Path& filename, std::error_code& ec) const = 0; Path find_file_recursively_up(const Path& starting_dir, const Path& filename, LineInfo li) const; + ExpectedL try_find_file_recursively_up(const Path& starting_dir, const Path& filename) const; virtual std::vector get_files_recursive(const Path& dir, std::error_code& ec) const = 0; std::vector get_files_recursive(const Path& dir, LineInfo li) const; diff --git a/include/vcpkg/vcpkgpaths.h b/include/vcpkg/vcpkgpaths.h index 79339089c9..05c8e34a85 100644 --- a/include/vcpkg/vcpkgpaths.h +++ b/include/vcpkg/vcpkgpaths.h @@ -89,6 +89,7 @@ namespace vcpkg const Path& downloads; const Path& tools; const Path builtin_registry_versions; + ExpectedL versions_dot_git_dir() const; const Path prefab; const Path buildsystems; const Path buildsystems_msbuild_targets; diff --git a/src/vcpkg/base/files.cpp b/src/vcpkg/base/files.cpp index 0ff799233b..2e307bc75a 100644 --- a/src/vcpkg/base/files.cpp +++ b/src/vcpkg/base/files.cpp @@ -1566,6 +1566,19 @@ namespace vcpkg return result; } + ExpectedL ReadOnlyFilesystem::try_find_file_recursively_up(const Path& starting_dir, + const Path& filename) const + { + std::error_code ec; + auto result = this->find_file_recursively_up(starting_dir, filename, ec); + if (ec) + { + return format_filesystem_call_error(ec, __func__, {starting_dir, filename}); + } + + return result; + } + std::vector ReadOnlyFilesystem::get_files_recursive(const Path& dir, LineInfo li) const { return this->try_get_files_recursive(dir).value_or_exit(li); diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index 260314f3e6..e6a3304566 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -37,8 +37,8 @@ namespace const GitVersionDbEntry& version_entry) { bool success = true; - auto maybe_extracted_tree = paths.git_checkout_port( - port_name, version_entry.git_tree, Path{paths.builtin_registry_versions.parent_path()} / ".git"); + auto maybe_extracted_tree = paths.versions_dot_git_dir().then( + [&](Path&& dot_git) { return paths.git_checkout_port(port_name, version_entry.git_tree, dot_git); }); auto extracted_tree = maybe_extracted_tree.get(); if (!extracted_tree) { diff --git a/src/vcpkg/commands.portsdiff.cpp b/src/vcpkg/commands.portsdiff.cpp index 29698105fc..af2b6f5400 100644 --- a/src/vcpkg/commands.portsdiff.cpp +++ b/src/vcpkg/commands.portsdiff.cpp @@ -80,7 +80,9 @@ namespace std::map read_ports_from_commit(const VcpkgPaths& paths, const std::string& git_commit_id) { auto& fs = paths.get_filesystem(); - const auto dot_git_dir = Path{paths.builtin_ports_directory().parent_path()} / ".git"; + const auto dot_git_dir = fs.try_find_file_recursively_up(paths.builtin_ports_directory().parent_path(), ".git") + .map([](Path&& dot_git_parent) { return std::move(dot_git_parent) / ".git"; }) + .value_or_exit(VCPKG_LINE_INFO);; const auto ports_dir_name = paths.builtin_ports_directory().filename(); const auto temp_checkout_path = paths.buildtrees() / fmt::format("{}-{}", ports_dir_name, git_commit_id); fs.create_directory(temp_checkout_path, IgnoreErrors{}); diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index ccfaef2b60..4643cfe773 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -654,7 +654,9 @@ namespace { const auto destination_tmp = destination_parent / "baseline.json.tmp"; auto treeish = Strings::concat(commit_sha, ":versions/baseline.json"); - auto maybe_contents = paths.git_show(treeish, Path{paths.builtin_registry_versions.parent_path()} / ".git"); + auto maybe_contents = + paths.versions_dot_git_dir().then([&](Path&& dot_git) { return paths.git_show(treeish, dot_git); }); + if (auto contents = maybe_contents.get()) { std::error_code ec; @@ -1162,8 +1164,8 @@ namespace } const auto& git_tree = port_versions_soa.git_trees()[it - port_versions.begin()]; - return m_paths - .git_checkout_port(port_name, git_tree, Path{m_paths.builtin_registry_versions.parent_path()} / ".git") + return m_paths.versions_dot_git_dir() + .then([&, this](Path&& dot_git) { return m_paths.git_checkout_port(port_name, git_tree, dot_git); }) .map([&git_tree](Path&& p) -> PortLocation { return { std::move(p), diff --git a/src/vcpkg/vcpkgpaths.cpp b/src/vcpkg/vcpkgpaths.cpp index ec312821ba..da20f4d875 100644 --- a/src/vcpkg/vcpkgpaths.cpp +++ b/src/vcpkg/vcpkgpaths.cpp @@ -812,6 +812,12 @@ namespace vcpkg } } + ExpectedL VcpkgPaths::versions_dot_git_dir() const + { + return m_pimpl->m_fs.try_find_file_recursively_up(builtin_registry_versions.parent_path(), ".git") + .map([](Path&& dot_git_parent) { return std::move(dot_git_parent) / ".git"; }); + } + std::string VcpkgPaths::get_toolver_diagnostics() const { std::string ret; @@ -952,7 +958,6 @@ namespace vcpkg ExpectedL>> VcpkgPaths::git_get_local_port_treeish_map() const { - const auto local_repo = Path{this->builtin_registry_versions.parent_path()} / ".git"; const auto git_cmd = git_cmd_builder({}, {}) .string_arg("-C") .string_arg(this->builtin_ports_directory()) From 89e216e7a8c59748d3c1473392a4f5738c2159bc Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 2 Oct 2023 02:33:44 -0700 Subject: [PATCH 29/48] Attempt better *nix defenses --- .../end-to-end-tests-dir/ci-verify-versions.ps1 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 index bea42da09f..2d08fa2805 100644 --- a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 @@ -6,7 +6,6 @@ Copy-Item -Recurse "$PSScriptRoot/../e2e-assets/ci-verify-versions-registry" "$T git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions init git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions add -A git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions commit -m testing -$git = (Get-Command git).Path $expected = @" $TestingRoot/ci-verify-versions-registry/ports/malformed/vcpkg.json:4:3: error: Unexpected character; expected property name on expression: ~broken @@ -94,12 +93,12 @@ note: you can overwrite version-scheme-mismatch@1.1 with correct local values by vcpkg x-add-version version-scheme-mismatch --overwrite-version $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-scheme-mismatch@1.1 matches the current baseline $TestingRoot/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json: All version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: failed to execute: `"$git`" `"--git-dir=$TestingRoot/ci-verify-versions-registry/.git`" `"--work-tree=$buildtreesRoot/versioning_/versions/bad-git-tree/000000070c5f496fcf1a97cf654d5e81f0d2685a_82336.tmp`" -c core.autocrlf=false read-tree -m -u 000000070c5f496fcf1a97cf654d5e81f0d2685a +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: failed to execute: `"C:\Program Files\Git\cmd\git.exe`" `"--git-dir=$TestingRoot/ci-verify-versions-registry/.git`" `"--work-tree=$buildtreesRoot/versioning_/versions/bad-git-tree/000000070c5f496fcf1a97cf654d5e81f0d2685a_82336.tmp`" -c core.autocrlf=false read-tree -m -u 000000070c5f496fcf1a97cf654d5e81f0d2685a error: git failed with exit code: (128). fatal: failed to unpack tree object 000000070c5f496fcf1a97cf654d5e81f0d2685a note: while checking out port bad-git-tree with git tree 000000070c5f496fcf1a97cf654d5e81f0d2685a note: while validating version: 1.1 -$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: failed to execute: `"$git`" `"--git-dir=$TestingRoot/ci-verify-versions-registry/.git`" `"--work-tree=$buildtreesRoot/versioning_/versions/bad-git-tree/00000005fb6b76058ce09252f521847363c6b266_82336.tmp`" -c core.autocrlf=false read-tree -m -u 00000005fb6b76058ce09252f521847363c6b266 +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: failed to execute: `"C:\Program Files\Git\cmd\git.exe`" `"--git-dir=$TestingRoot/ci-verify-versions-registry/.git`" `"--work-tree=$buildtreesRoot/versioning_/versions/bad-git-tree/00000005fb6b76058ce09252f521847363c6b266_82336.tmp`" -c core.autocrlf=false read-tree -m -u 00000005fb6b76058ce09252f521847363c6b266 error: git failed with exit code: (128). fatal: failed to unpack tree object 00000005fb6b76058ce09252f521847363c6b266 note: while checking out port bad-git-tree with git tree 00000005fb6b76058ce09252f521847363c6b266 @@ -140,7 +139,7 @@ note: versions must be unique, even if they are declared with different schemes $actual = Run-VcpkgAndCaptureOutput x-ci-verify-versions @directoryArgs "--x-builtin-ports-root=$TestingRoot/ci-verify-versions-registry/ports" "--x-builtin-registry-versions-dir=$TestingRoot/ci-verify-versions-registry/versions" --verbose --verify-git-trees Throw-IfNotFailed -$workTreeRegex = '"--work-tree=[^"]+\.tmp' # This has an unpredictable PID inside +$workTreeRegex = 'error: failed to execute:[^\r\n]+' # Git command line has an unpredictable PID inside $expected = $expected.Replace('\', '/') $expected = [System.Text.RegularExpressions.Regex]::Replace($expected, $workTreeRegex, '') $actual = $actual.Replace('\', '/') From 78c4aaf693d948aed5d5ee01e8b74f2329c31fe2 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 2 Oct 2023 11:13:08 -0700 Subject: [PATCH 30/48] Try to sanitize whitespace --- .../end-to-end-tests-dir/ci-verify-versions.ps1 | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 index 2d08fa2805..19769129e8 100644 --- a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 @@ -133,17 +133,20 @@ note: versions must be unique, even if they are declared with different schemes $TestingRoot/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json: error: 1.0 is declared version-string, but version-scheme-mismatch@89c88798a9fa17ea6753da87887a1fec48c421b0 is declared with version $buildtreesRoot/versioning_/versions/version-scheme-mismatch/89c88798a9fa17ea6753da87887a1fec48c421b0/vcpkg.json: note: version-scheme-mismatch is declared here note: versions must be unique, even if they are declared with different schemes - "@ $actual = Run-VcpkgAndCaptureOutput x-ci-verify-versions @directoryArgs "--x-builtin-ports-root=$TestingRoot/ci-verify-versions-registry/ports" "--x-builtin-registry-versions-dir=$TestingRoot/ci-verify-versions-registry/versions" --verbose --verify-git-trees Throw-IfNotFailed -$workTreeRegex = 'error: failed to execute:[^\r\n]+' # Git command line has an unpredictable PID inside -$expected = $expected.Replace('\', '/') -$expected = [System.Text.RegularExpressions.Regex]::Replace($expected, $workTreeRegex, '') -$actual = $actual.Replace('\', '/') -$actual = [System.Text.RegularExpressions.Regex]::Replace($actual, $workTreeRegex, '') +function Sanitize() { + Param([string]$text) + $workTreeRegex = 'error: failed to execute:[^\r\n]+' # Git command line has an unpredictable PID inside + $text = $text.Replace('\', '/').Replace('`r`n', '`n').Trim() + $text = [System.Text.RegularExpressions.Regex]::Replace($text, $workTreeRegex, '') +} + +$expected = Sanitize $expected +$actual = Sanitize $actual if ($actual -ne $expected) { Write-Host "Expected:" Write-Host $expected From 0dd96eec2308f31edf5b2c8f227c17d469e4cf72 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 2 Oct 2023 11:45:07 -0700 Subject: [PATCH 31/48] clang-format --- src/vcpkg/commands.portsdiff.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vcpkg/commands.portsdiff.cpp b/src/vcpkg/commands.portsdiff.cpp index af2b6f5400..10ab505417 100644 --- a/src/vcpkg/commands.portsdiff.cpp +++ b/src/vcpkg/commands.portsdiff.cpp @@ -82,7 +82,7 @@ namespace auto& fs = paths.get_filesystem(); const auto dot_git_dir = fs.try_find_file_recursively_up(paths.builtin_ports_directory().parent_path(), ".git") .map([](Path&& dot_git_parent) { return std::move(dot_git_parent) / ".git"; }) - .value_or_exit(VCPKG_LINE_INFO);; + .value_or_exit(VCPKG_LINE_INFO); const auto ports_dir_name = paths.builtin_ports_directory().filename(); const auto temp_checkout_path = paths.buildtrees() / fmt::format("{}-{}", ports_dir_name, git_commit_id); fs.create_directory(temp_checkout_path, IgnoreErrors{}); From 70e914bc584a825e642bf00a1bdbe699510b54c4 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 9 Oct 2023 23:18:12 -0700 Subject: [PATCH 32/48] Collapse out a few more maybe_maybes and respond to comments of https://github.com/microsoft/vcpkg-tool/pull/1203 after merge --- include/vcpkg/base/message-data.inc.h | 4 + locales/messages.json | 2 + src/vcpkg/paragraphs.cpp | 8 +- src/vcpkg/portfileprovider.cpp | 22 ++- src/vcpkg/registries.cpp | 211 +++++++++++--------------- 5 files changed, 110 insertions(+), 137 deletions(-) diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index f38cad05a6..445ca369c8 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -3158,6 +3158,10 @@ DECLARE_MESSAGE(WhileCheckingOutPortTreeIsh, "while checking out port {package_name} with git tree {commit_sha}") DECLARE_MESSAGE(WhileGettingLocalTreeIshObjectsForPorts, (), "", "while getting local treeish objects for ports") DECLARE_MESSAGE(WhileLookingForSpec, (msg::spec), "", "while looking for {spec}:") +DECLARE_MESSAGE(WhileLoadingBaselineVersionForPort, + (msg::package_name), + "", + "while loading baseline version for {package_name}") DECLARE_MESSAGE(WhileLoadingPortVersion, (msg::version_spec), "", "while loading {version_spec}") DECLARE_MESSAGE(WhileParsingVersionsForPort, (msg::package_name, msg::path), diff --git a/locales/messages.json b/locales/messages.json index dbf874d77c..f8fdc7cc1b 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -1726,6 +1726,8 @@ "WhileCheckingOutPortTreeIsh": "while checking out port {package_name} with git tree {commit_sha}", "_WhileCheckingOutPortTreeIsh.comment": "An example of {package_name} is zlib. An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "WhileGettingLocalTreeIshObjectsForPorts": "while getting local treeish objects for ports", + "WhileLoadingBaselineVersionForPort": "while loading baseline version for {package_name}", + "_WhileLoadingBaselineVersionForPort.comment": "An example of {package_name} is zlib.", "WhileLoadingPortVersion": "while loading {version_spec}", "_WhileLoadingPortVersion.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0.", "WhileLookingForSpec": "while looking for {spec}:", diff --git a/src/vcpkg/paragraphs.cpp b/src/vcpkg/paragraphs.cpp index 108c4ba8a7..5c8f92c87e 100644 --- a/src/vcpkg/paragraphs.cpp +++ b/src/vcpkg/paragraphs.cpp @@ -535,18 +535,18 @@ namespace vcpkg::Paragraphs StringView port_name, const PortLocation& port_location) { - auto maybe_maybe_res = try_load_port(fs, port_name, port_location); - auto maybe_res = maybe_maybe_res.maybe_scfl.get(); + auto load_result = try_load_port(fs, port_name, port_location); + auto maybe_res = load_result.maybe_scfl.get(); if (maybe_res) { auto res = maybe_res->source_control_file.get(); if (!res) { - maybe_maybe_res.maybe_scfl = msg::format_error(msgPortDoesNotExist, msg::package_name = port_name); + load_result.maybe_scfl = msg::format_error(msgPortDoesNotExist, msg::package_name = port_name); } } - return maybe_maybe_res; + return load_result; } ExpectedL try_load_cached_package(const ReadOnlyFilesystem& fs, diff --git a/src/vcpkg/portfileprovider.cpp b/src/vcpkg/portfileprovider.cpp index b46b0bd4cc..6b8e8c27b1 100644 --- a/src/vcpkg/portfileprovider.cpp +++ b/src/vcpkg/portfileprovider.cpp @@ -110,20 +110,16 @@ namespace vcpkg virtual ExpectedL get_baseline_version(StringView port_name) const override { return m_baseline_cache.get_lazy(port_name, [this, port_name]() -> ExpectedL { - auto maybe_maybe_version = registry_set.baseline_for_port(port_name); - auto maybe_version = maybe_maybe_version.get(); - if (!maybe_version) - { - return std::move(maybe_maybe_version).error(); - } - - auto version = maybe_version->get(); - if (!version) - { - return msg::format_error(msgPortNotInBaseline, msg::package_name = port_name); - } + return registry_set.baseline_for_port(port_name).then( + [&](Optional&& maybe_version) -> ExpectedL { + auto version = maybe_version.get(); + if (!version) + { + return msg::format_error(msgPortNotInBaseline, msg::package_name = port_name); + } - return std::move(*version); + return std::move(*version); + }); }); } diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index 69e4352495..0275a95533 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -709,48 +709,40 @@ namespace ExpectedL> BuiltinFilesRegistry::get_port_entry(StringView port_name) const { auto port_directory = m_builtin_ports_directory / port_name; - const auto& maybe_maybe_scf = get_scf(port_name, port_directory); - const auto maybe_scf = maybe_maybe_scf.get(); - if (!maybe_scf) - { - return maybe_maybe_scf.error(); - } - - auto scf = maybe_scf->source_control_file.get(); - if (!scf) - { - return std::unique_ptr(); - } + return get_scf(port_name, port_directory) + .then([&](const SourceControlFileAndLocation& scfl) -> ExpectedL> { + auto scf = scfl.source_control_file.get(); + if (!scf) + { + return std::unique_ptr(); + } - if (scf->core_paragraph->name == port_name) - { - return std::make_unique( - scf->core_paragraph->name, port_directory, scf->to_version()); - } + if (scf->core_paragraph->name == port_name) + { + return std::make_unique( + scf->core_paragraph->name, port_directory, scf->to_version()); + } - return msg::format_error(msgUnexpectedPortName, - msg::expected = scf->core_paragraph->name, - msg::actual = port_name, - msg::path = port_directory); + return msg::format_error(msgUnexpectedPortName, + msg::expected = scf->core_paragraph->name, + msg::actual = port_name, + msg::path = port_directory); + }); } ExpectedL> BuiltinFilesRegistry::get_baseline_version(StringView port_name) const { // if a baseline is not specified, use the ports directory version - const auto& maybe_maybe_scf = get_scf(port_name, m_builtin_ports_directory / port_name); - auto maybe_scf = maybe_maybe_scf.get(); - if (!maybe_scf) - { - return maybe_maybe_scf.error(); - } - - auto scf = maybe_scf->source_control_file.get(); - if (!scf) - { - return Optional(); - } + return get_scf(port_name, m_builtin_ports_directory / port_name) + .then([&](const SourceControlFileAndLocation& scfl) -> ExpectedL> { + auto scf = scfl.source_control_file.get(); + if (!scf) + { + return Optional(); + } - return scf->to_version(); + return scf->to_version(); + }); } ExpectedL BuiltinFilesRegistry::append_all_port_names(std::vector& out) const @@ -784,41 +776,31 @@ namespace const auto& fs = m_paths.get_filesystem(); auto versions_path = m_paths.builtin_registry_versions / relative_path_to_versions(port_name); - auto maybe_maybe_version_entries = - load_git_versions_file(fs, m_paths.builtin_registry_versions, port_name).entries; - auto maybe_version_entries = maybe_maybe_version_entries.get(); - if (!maybe_version_entries) - { - return std::move(maybe_maybe_version_entries).error(); - } - - auto version_entries = maybe_version_entries->get(); - if (!version_entries) - { - return m_files_impl->get_port_entry(port_name); - } + return load_git_versions_file(fs, m_paths.builtin_registry_versions, port_name) + .entries.then([this, &port_name](Optional>&& maybe_version_entries) + -> ExpectedL> { + auto version_entries = maybe_version_entries.get(); + if (!version_entries) + { + return m_files_impl->get_port_entry(port_name); + } - auto res = std::make_unique(m_paths); - res->port_name.assign(port_name.data(), port_name.size()); - res->port_versions_soa.assign(std::move(*version_entries)); - return res; + auto res = std::make_unique(m_paths); + res->port_name.assign(port_name.data(), port_name.size()); + res->port_versions_soa.assign(std::move(*version_entries)); + return res; + }); } - ExpectedL> BuiltinGitRegistry::get_baseline_version(StringView port_name) const + ExpectedL> lookup_in_maybe_baseline(const ExpectedL& maybe_baseline, + StringView port_name) { - const auto& maybe_baseline = m_baseline.get([this]() -> ExpectedL { - return git_checkout_baseline(m_paths, m_baseline_identifier) - .then([&](Path&& path) { return load_baseline_versions(m_paths.get_filesystem(), path); }) - .map_error([&](LocalizedString&& error) { - return std::move(error).append(msgWhileCheckingOutBaseline, - msg::commit_sha = m_baseline_identifier); - }); - }); - auto baseline = maybe_baseline.get(); if (!baseline) { - return maybe_baseline.error(); + return LocalizedString(maybe_baseline.error()) + .append_raw('\n') + .append(msgWhileLoadingBaselineVersionForPort, msg::package_name = port_name); } auto it = baseline->find(port_name); @@ -830,6 +812,19 @@ namespace return Optional(); } + ExpectedL> BuiltinGitRegistry::get_baseline_version(StringView port_name) const + { + return lookup_in_maybe_baseline(m_baseline.get([this]() -> ExpectedL { + return git_checkout_baseline(m_paths, m_baseline_identifier) + .then([&](Path&& path) { return load_baseline_versions(m_paths.get_filesystem(), path); }) + .map_error([&](LocalizedString&& error) { + return std::move(error).append(msgWhileCheckingOutBaseline, + msg::commit_sha = m_baseline_identifier); + }); + }), + port_name); + } + ExpectedL BuiltinGitRegistry::append_all_port_names(std::vector& out) const { const auto& fs = m_paths.get_filesystem(); @@ -853,46 +848,33 @@ namespace // { FilesystemRegistry::RegistryImplementation ExpectedL> FilesystemRegistry::get_baseline_version(StringView port_name) const { - return m_baseline - .get([this]() { - return load_baseline_versions( - m_fs, m_path / registry_versions_dir_name / "baseline.json", m_baseline_identifier); - }) - .then([&](const Baseline& baseline) -> ExpectedL> { - auto it = baseline.find(port_name); - if (it != baseline.end()) - { - return it->second; - } - - return Optional(); - }); + return lookup_in_maybe_baseline(m_baseline.get([this]() { + return load_baseline_versions( + m_fs, m_path / registry_versions_dir_name / "baseline.json", m_baseline_identifier); + }), + port_name); } ExpectedL> FilesystemRegistry::get_port_entry(StringView port_name) const { - auto maybe_maybe_version_entries = - load_filesystem_versions_file(m_fs, m_path / registry_versions_dir_name, port_name, m_path); - auto maybe_version_entries = maybe_maybe_version_entries.get(); - if (!maybe_version_entries) - { - return std::move(maybe_maybe_version_entries).error(); - } - - auto version_entries = maybe_version_entries->get(); - if (!version_entries) - { - return std::unique_ptr{}; - } + return load_filesystem_versions_file(m_fs, m_path / registry_versions_dir_name, port_name, m_path) + .then([this, &port_name](Optional>&& maybe_version_entries) + -> ExpectedL> { + auto version_entries = maybe_version_entries.get(); + if (!version_entries) + { + return std::unique_ptr{}; + } - auto res = std::make_unique(port_name.to_string()); - for (auto&& version_entry : *version_entries) - { - res->port_versions.push_back(std::move(version_entry.version.version)); - res->version_paths.push_back(std::move(version_entry.p)); - } + auto res = std::make_unique(port_name.to_string()); + for (auto&& version_entry : *version_entries) + { + res->port_versions.push_back(std::move(version_entry.version.version)); + res->version_paths.push_back(std::move(version_entry.p)); + } - return res; + return res; + }); } ExpectedL FilesystemRegistry::append_all_port_names(std::vector& out) const @@ -940,31 +922,20 @@ namespace return std::unique_ptr(); } - auto maybe_live_vdb = get_versions_tree_path(); - auto live_vcb = maybe_live_vdb.get(); - if (!live_vcb) - { - return std::move(maybe_live_vdb).error(); - } + return get_versions_tree_path().then([this, &port_name](const Path& live_vcb) { + return load_git_versions_file(m_paths.get_filesystem(), live_vcb, port_name) + .entries.then([this, &port_name](Optional>&& maybe_version_entries) + -> ExpectedL> { + auto version_entries = maybe_version_entries.get(); + if (!version_entries) + { + // data is already live but we don't know of this port + return std::unique_ptr(); + } - { - auto maybe_maybe_version_entries = - load_git_versions_file(m_paths.get_filesystem(), *live_vcb, port_name).entries; - auto maybe_version_entries = maybe_maybe_version_entries.get(); - if (!maybe_version_entries) - { - return std::move(maybe_maybe_version_entries).error(); - } - - auto version_entries = maybe_version_entries->get(); - if (!version_entries) - { - // data is already live but we don't know of this port - return std::unique_ptr(); - } - - return std::make_unique(port_name, *this, false, std::move(*version_entries)); - } + return std::make_unique(port_name, *this, false, std::move(*version_entries)); + }); + }); } GitRegistryEntry::GitRegistryEntry(StringView port_name, From 57340d0beec9ffae957c4e0f61c30731337bf7ee Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 9 Oct 2023 23:52:53 -0700 Subject: [PATCH 33/48] Reduce join() code size after discussion with @JavierMatosD --- include/vcpkg/base/strings.h | 16 ++++++++++------ src/vcpkg/base/downloads.cpp | 4 +--- src/vcpkg/base/json.cpp | 15 ++++++++++----- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/include/vcpkg/base/strings.h b/include/vcpkg/base/strings.h index 284f6e480d..aae5888d97 100644 --- a/include/vcpkg/base/strings.h +++ b/include/vcpkg/base/strings.h @@ -107,17 +107,21 @@ namespace vcpkg::Strings Transformer transformer) { std::string output; - if (first != last) + if (first == last) + { + return output; + } + + for (;;) { Strings::append(output, transformer(*first)); - while (++first != last) + if (++first == last) { - output.append(delimiter.data(), delimiter.size()); - Strings::append(output, transformer(*first)); + return output; } - } - return output; + output.append(delimiter.data(), delimiter.size()); + } } template diff --git a/src/vcpkg/base/downloads.cpp b/src/vcpkg/base/downloads.cpp index 32be45258c..6f5b498e92 100644 --- a/src/vcpkg/base/downloads.cpp +++ b/src/vcpkg/base/downloads.cpp @@ -637,9 +637,7 @@ namespace vcpkg return url; } - std::string query = Strings::join("&", query_params); - - return url + "?" + query; + return url + "?" + Strings::join("&", query_params); } ExpectedL invoke_http_request(StringView method, diff --git a/src/vcpkg/base/json.cpp b/src/vcpkg/base/json.cpp index 5b865a00c0..e2d9af7dca 100644 --- a/src/vcpkg/base/json.cpp +++ b/src/vcpkg/base/json.cpp @@ -1398,16 +1398,21 @@ namespace vcpkg::Json LocalizedString result; auto first = messages.begin(); const auto last = messages.end(); - if (first != last) + if (first == last) + { + return result; + } + + for (;;) { result.append(first->message); - while (++first != last) + if (++first == last) { - result.append_raw('\n').append(first->message); + return result; } - } - return result; + result.append_raw('\n'); + } } LocalizedString flatten_reader_messages(const std::vector& messages, MessageSink& warningsSink) From 251334baac84eac859ad792a5b7bf3dd8ab977b5 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 10 Oct 2023 00:16:26 -0700 Subject: [PATCH 34/48] Fix macos error and use lookup_in_maybe_baseline in one more place. --- src/vcpkg/registries.cpp | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index 0275a95533..8e44168fe4 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -858,7 +858,7 @@ namespace ExpectedL> FilesystemRegistry::get_port_entry(StringView port_name) const { return load_filesystem_versions_file(m_fs, m_path / registry_versions_dir_name, port_name, m_path) - .then([this, &port_name](Optional>&& maybe_version_entries) + .then([&](Optional>&& maybe_version_entries) -> ExpectedL> { auto version_entries = maybe_version_entries.get(); if (!version_entries) @@ -951,7 +951,7 @@ namespace ExpectedL> GitRegistry::get_baseline_version(StringView port_name) const { - const auto& maybe_baseline = m_baseline.get([this, port_name]() -> ExpectedL { + return lookup_in_maybe_baseline(m_baseline.get([this, port_name]() -> ExpectedL { // We delay baseline validation until here to give better error messages and suggestions if (!is_git_commit_sha(m_baseline_identifier)) { @@ -1028,21 +1028,8 @@ namespace .append_raw('\n') .append(error); }); - }); - - auto baseline = maybe_baseline.get(); - if (!baseline) - { - return maybe_baseline.error(); - } - - auto it = baseline->find(port_name); - if (it != baseline->end()) - { - return it->second; - } - - return Optional(); + }), + port_name); } ExpectedL GitRegistry::append_all_port_names(std::vector& out) const From d5e40423200929ef6f6fa324c41a9bb38a298e60 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 10 Oct 2023 00:47:24 -0700 Subject: [PATCH 35/48] Fix output nitpicks --- azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 | 6 +++--- include/vcpkg/base/message-data.inc.h | 6 +++--- locales/messages.json | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 index 19769129e8..6e79818557 100644 --- a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 @@ -25,7 +25,7 @@ $TestingRoot/ci-verify-versions-registry/ports/bad-history-name: message: bad-hi $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: bad-history-name@1.1 matches the current baseline $TestingRoot/ci-verify-versions-registry/ports/bad-history-name/vcpkg.json: All version constraints are consistent with the version database $TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch: message: baseline-version-mismatch@1.1 is correctly in the version database (cf8a1faa9f94f7ceb9513d65093d407e11ac1402) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: baseline-version-mismatch is declared at version 1.0, but the local port is 1.1 +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: baseline-version-mismatch is assigned 1.0, but the local port is 1.1 $TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json: note: baseline-version-mismatch is declared here note: you can run the following commands to add the current version of baseline-version-mismatch automatically: vcpkg x-add-version baseline-version-mismatch @@ -33,7 +33,7 @@ note: you can run the following commands to add the current version of baseline- git commit -m `"Update version database`" $TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json: All version constraints are consistent with the version database $TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing: message: baseline-version-missing@1.0 is correctly in the version database (a5c21769008f52ed66afa344f13b786dde4b8d7d) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: no version of baseline-version-missing is set +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: baseline-version-missing is not assigned a version $TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json: note: baseline-version-missing is declared here note: you can run the following commands to add the current version of baseline-version-missing automatically: vcpkg x-add-version baseline-version-missing @@ -58,7 +58,7 @@ $TestingRoot/ci-verify-versions-registry/ports/good: message: good@1.0 is correc $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: good@1.0 matches the current baseline $TestingRoot/ci-verify-versions-registry/ports/good/vcpkg.json: All version constraints are consistent with the version database $TestingRoot/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json: error: mismatch-git-tree@1.0 is declared to have git tree 41d20d2a02d75343b0933b624faf9f061b112dad, but the local port $TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree has git tree 34b3289caaa7a97950828905d354dc971c3c15a7 -note: If mismatch-git-tree@1.0 is already published, update the mismatch-git-tree manifest with a new version or port-version, then add the new version by running: +note: if mismatch-git-tree@1.0 is already published, update the mismatch-git-tree manifest with a new version or port-version, then add the new version by running: vcpkg x-add-version mismatch-git-tree git add versions git commit -m `"Update version database`" diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 445ca369c8..371e066544 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -291,7 +291,7 @@ DECLARE_MESSAGE(BaselineGitShowFailed, "", "while checking out baseline from commit '{commit_sha}', failed to `git show` " "versions/baseline.json. This may be fixed by fetching commits with `git fetch`.") -DECLARE_MESSAGE(BaselineMissing, (msg::package_name), "", "no version of {package_name} is set") +DECLARE_MESSAGE(BaselineMissing, (msg::package_name), "", "{package_name} is not assigned a version") DECLARE_MESSAGE(BinaryCacheVendorHTTP, (), "", "HTTP servers") DECLARE_MESSAGE(BinarySourcesArg, (), @@ -2951,7 +2951,7 @@ DECLARE_MESSAGE(VersionBaselineMatch, (msg::version_spec), "", "message: {versio DECLARE_MESSAGE(VersionBaselineMismatch, (msg::expected, msg::actual, msg::package_name), "{actual} and {expected} are versions", - "{package_name} is declared at version {actual}, but the local port is {expected}") + "{package_name} is assigned {actual}, but the local port is {expected}") DECLARE_MESSAGE(VersionBuiltinPortTreeEntryMissing, (msg::package_name, msg::expected, msg::actual), "{expected} and {actual} are versions like 1.0.", @@ -3100,7 +3100,7 @@ DECLARE_MESSAGE( "https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish", "{version_spec} is declared to have git tree {expected}, but the local port {path} has git tree " "{actual}\n" - "note: If {version_spec} is already published, update the {package_name} manifest with a new version or " + "note: if {version_spec} is already published, update the {package_name} manifest with a new version or " "port-version, then add the new version by running:") DECLARE_MESSAGE(VersionShaMismatch2, (msg::version_spec), diff --git a/locales/messages.json b/locales/messages.json index f8fdc7cc1b..b20a0b6ff2 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -194,7 +194,7 @@ "_BaselineFileNoDefaultField.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "BaselineGitShowFailed": "while checking out baseline from commit '{commit_sha}', failed to `git show` versions/baseline.json. This may be fixed by fetching commits with `git fetch`.", "_BaselineGitShowFailed.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", - "BaselineMissing": "no version of {package_name} is set", + "BaselineMissing": "{package_name} is not assigned a version", "_BaselineMissing.comment": "An example of {package_name} is zlib.", "BinaryCacheVendorHTTP": "HTTP servers", "BinarySourcesArg": "Binary caching sources. See 'vcpkg help binarycaching'", @@ -1637,7 +1637,7 @@ "_VcvarsRunFailedExitCode.comment": "An example of {exit_code} is 127.", "VersionBaselineMatch": "message: {version_spec} matches the current baseline", "_VersionBaselineMatch.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0.", - "VersionBaselineMismatch": "{package_name} is declared at version {actual}, but the local port is {expected}", + "VersionBaselineMismatch": "{package_name} is assigned {actual}, but the local port is {expected}", "_VersionBaselineMismatch.comment": "{actual} and {expected} are versions An example of {package_name} is zlib.", "VersionBuiltinPortTreeEntryMissing": "no version database entry for {package_name} at {expected}; using the checked out ports tree version ({actual}).", "_VersionBuiltinPortTreeEntryMissing.comment": "{expected} and {actual} are versions like 1.0. An example of {package_name} is zlib.", @@ -1700,7 +1700,7 @@ "VersionSchemeMismatch1Old": "{version} is declared {expected}, but {package_name}@{commit_sha} is declared with {actual}", "_VersionSchemeMismatch1Old.comment": "{expected} and {actual} are version schemes; it here refers to the {version} An example of {version} is 1.3.8. An example of {package_name} is zlib. An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "VersionSchemeMismatch2": "versions must be unique, even if they are declared with different schemes", - "VersionShaMismatch1": "{version_spec} is declared to have git tree {expected}, but the local port {path} has git tree {actual}\nnote: If {version_spec} is already published, update the {package_name} manifest with a new version or port-version, then add the new version by running:", + "VersionShaMismatch1": "{version_spec} is declared to have git tree {expected}, but the local port {path} has git tree {actual}\nnote: if {version_spec} is already published, update the {package_name} manifest with a new version or port-version, then add the new version by running:", "_VersionShaMismatch1.comment": "{expected} and {actual} are git tree SHAs. Console commands the user can run are printed after. 'git tree' is https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {package_name} is zlib. An example of {path} is /foo/bar.", "VersionShaMismatch2": "note: if {version_spec} is not yet published, overwrite the previous git tree by running:", "_VersionShaMismatch2.comment": "Console commands the user can run are printed after. 'git tree' is https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish An example of {version_spec} is zlib:x64-windows@1.0.0.", From 95936ec60cb8ab534ea1910e2be9137ddb7ab343 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 10 Oct 2023 02:08:38 -0700 Subject: [PATCH 36/48] Change all errors to always print paths at the beginning of a line --- .../has-local-edits/portfile.cmake | 1 + .../has-local-edits/vcpkg.json | 4 + .../versions/baseline.json | 4 + .../versions/h-/has-local-edits.json | 9 ++ .../ci-verify-versions.ps1 | 73 +++++++---- include/vcpkg/base/message-args.inc.h | 4 + include/vcpkg/base/message-data.inc.h | 115 ++++++++++-------- include/vcpkg/base/messages.h | 10 -- locales/messages.json | 65 ++++++---- src/vcpkg/base/checks.cpp | 10 +- src/vcpkg/base/hash.cpp | 4 +- src/vcpkg/base/message_sinks.cpp | 4 +- src/vcpkg/base/messages.cpp | 11 -- src/vcpkg/base/parse.cpp | 4 +- src/vcpkg/binarycaching.cpp | 12 +- src/vcpkg/commands.add.cpp | 2 +- src/vcpkg/commands.build.cpp | 4 +- src/vcpkg/commands.ci-verify-versions.cpp | 104 +++++++++++----- src/vcpkg/commands.install.cpp | 2 +- src/vcpkg/portfileprovider.cpp | 2 +- src/vcpkg/registries.cpp | 16 +-- src/vcpkg/tools.cpp | 6 +- src/vcpkg/vcpkgpaths.cpp | 8 +- src/vcpkg/versions.cpp | 2 +- 24 files changed, 287 insertions(+), 189 deletions(-) create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/has-local-edits/portfile.cmake create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/has-local-edits/vcpkg.json create mode 100644 azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/h-/has-local-edits.json diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/has-local-edits/portfile.cmake b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/has-local-edits/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/has-local-edits/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/has-local-edits/vcpkg.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/has-local-edits/vcpkg.json new file mode 100644 index 0000000000..5adb003ec5 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/old-port-versions/has-local-edits/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "has-local-edits", + "version": "1.0.0" +} diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/baseline.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/baseline.json index 96a69166a1..39be2d26a7 100644 --- a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/baseline.json +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/baseline.json @@ -36,6 +36,10 @@ "baseline": "1.0", "port-version": 0 }, + "has-local-edits": { + "baseline": "1.0.0", + "port-version": 0 + }, "malformed": { "baseline": "1.0", "port-version": 0 diff --git a/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/h-/has-local-edits.json b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/h-/has-local-edits.json new file mode 100644 index 0000000000..794d49fb59 --- /dev/null +++ b/azure-pipelines/e2e-assets/ci-verify-versions-registry/versions/h-/has-local-edits.json @@ -0,0 +1,9 @@ +{ + "versions": [ + { + "git-tree": "b1d7f6030942b329a200f16c931c01e2ec9e1e79", + "version": "1.0.0", + "port-version": 0 + } + ] +} diff --git a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 index 6e79818557..2140cddaec 100644 --- a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 @@ -6,12 +6,15 @@ Copy-Item -Recurse "$PSScriptRoot/../e2e-assets/ci-verify-versions-registry" "$T git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions init git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions add -A git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions commit -m testing +Move-Item "$TestingRoot/ci-verify-versions-registry/old-port-versions/has-local-edits" "$TestingRoot/ci-verify-versions-registry/ports" + $expected = @" $TestingRoot/ci-verify-versions-registry/ports/malformed/vcpkg.json:4:3: error: Unexpected character; expected property name on expression: ~broken ^ -$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: bad-git-tree@1.1 is declared to have git tree 000000070c5f496fcf1a97cf654d5e81f0d2685a, but the local port $TestingRoot/ci-verify-versions-registry/ports/bad-git-tree has git tree 6528b2c70c5f496fcf1a97cf654d5e81f0d2685a -note: If bad-git-tree@1.1 is already published, update the bad-git-tree manifest with a new version or port-version, then add the new version by running: +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: bad-git-tree@1.1 git tree 000000070c5f496fcf1a97cf654d5e81f0d2685a does not match the port directory +$TestingRoot/ci-verify-versions-registry/ports/bad-git-tree: note: the port directory has git tree 6528b2c70c5f496fcf1a97cf654d5e81f0d2685a +$TestingRoot/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json: note: if bad-git-tree@1.1 is already published, update this file with a new version or port-version, commit it, then add the new version by running: vcpkg x-add-version bad-git-tree git add versions git commit -m `"Update version database`" @@ -20,10 +23,10 @@ note: if bad-git-tree@1.1 is not yet published, overwrite the previous git tree git add versions git commit -m `"Update version database`" $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: bad-git-tree@1.1 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json: message: all version constraints are consistent with the version database $TestingRoot/ci-verify-versions-registry/ports/bad-history-name: message: bad-history-name@1.1 is correctly in the version database (f34f4ad3dfcc4d46d467d7b6aa04f9732a7951d6) $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: bad-history-name@1.1 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/bad-history-name/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/bad-history-name/vcpkg.json: message: all version constraints are consistent with the version database $TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch: message: baseline-version-mismatch@1.1 is correctly in the version database (cf8a1faa9f94f7ceb9513d65093d407e11ac1402) $TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: baseline-version-mismatch is assigned 1.0, but the local port is 1.1 $TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json: note: baseline-version-mismatch is declared here @@ -31,7 +34,7 @@ note: you can run the following commands to add the current version of baseline- vcpkg x-add-version baseline-version-mismatch git add versions git commit -m `"Update version database`" -$TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json: message: all version constraints are consistent with the version database $TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing: message: baseline-version-missing@1.0 is correctly in the version database (a5c21769008f52ed66afa344f13b786dde4b8d7d) $TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: baseline-version-missing is not assigned a version $TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json: note: baseline-version-missing is declared here @@ -39,7 +42,7 @@ note: you can run the following commands to add the current version of baseline- vcpkg x-add-version baseline-version-missing git add versions git commit -m `"Update version database`" -$TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json: message: all version constraints are consistent with the version database $TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database: message: dependency-not-in-versions-database@1.0 is correctly in the version database (321c8b400526dc412a987285ef469eec6221a4b4) $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-not-in-versions-database@1.0 matches the current baseline $TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database/vcpkg.json: error: the dependency no-versions does not exist in the version database; does that port exist? @@ -49,16 +52,28 @@ $TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-databa note: the dependency is in the feature named add-things $TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database: message: dependency-version-not-in-versions-database@1.0 is correctly in the version database (f0d44555fe7714929e432ab9e12a436e28ffef9e) $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-version-not-in-versions-database@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/vcpkg.json: error: the "version>=" constraint to good names version 0.9 which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. Consider removing the version constraint or choosing a value declared in $TestingRoot/ci-verify-versions-registry/versions/g-/good.json. +$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/vcpkg.json: error: the "version>=" constraint to good names version 0.9 which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. +$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: note: consider removing the version constraint or choosing a value declared here $TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature: message: dependency-version-not-in-versions-database-feature@1.0 is correctly in the version database (ba3008bb2d42c61f172b7d9592de0212edf20fc6) $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-version-not-in-versions-database-feature@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/vcpkg.json: error: the "version>=" constraint to good names version 0.9 which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. Consider removing the version constraint or choosing a value declared in $TestingRoot/ci-verify-versions-registry/versions/g-/good.json. +$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/vcpkg.json: error: the "version>=" constraint to good names version 0.9 which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. +$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: note: consider removing the version constraint or choosing a value declared here note: the dependency is in the feature named add-things $TestingRoot/ci-verify-versions-registry/ports/good: message: good@1.0 is correctly in the version database (0f3d67db0dbb6aa5499bc09367a606b495e16d35) $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: good@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/good/vcpkg.json: All version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json: error: mismatch-git-tree@1.0 is declared to have git tree 41d20d2a02d75343b0933b624faf9f061b112dad, but the local port $TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree has git tree 34b3289caaa7a97950828905d354dc971c3c15a7 -note: if mismatch-git-tree@1.0 is already published, update the mismatch-git-tree manifest with a new version or port-version, then add the new version by running: +$TestingRoot/ci-verify-versions-registry/ports/good/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/has-local-edits/vcpkg.json: error: the git tree of the port directory could not be determined. This is usually caused by uncommitted changes. +note: you can commit your changes and add them to the version database by running: + git add "$TestingRoot/ci-verify-versions-registry/ports/has-local-edits" + git commit -m wip + vcpkg x-add-version has-local-edits + git add versions + git commit --amend -m "[has-local-edits] Add new port" +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: has-local-edits@1.0.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/has-local-edits/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json: error: mismatch-git-tree@1.0 git tree 41d20d2a02d75343b0933b624faf9f061b112dad does not match the port directory +$TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree: note: the port directory has git tree 34b3289caaa7a97950828905d354dc971c3c15a7 +$TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json: note: if mismatch-git-tree@1.0 is already published, update this file with a new version or port-version, commit it, then add the new version by running: vcpkg x-add-version mismatch-git-tree git add versions git commit -m `"Update version database`" @@ -67,32 +82,36 @@ note: if mismatch-git-tree@1.0 is not yet published, overwrite the previous git git add versions git commit -m `"Update version database`" $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: mismatch-git-tree@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json: All version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/ports/no-versions/vcpkg.json: error: missing a version database file at $TestingRoot/ci-verify-versions-registry/versions/n-/no-versions.json -note: run 'vcpkg x-add-version no-versions' to create the version database file. +$TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/no-versions/vcpkg.json: error: this port is not in the version database +$TestingRoot/ci-verify-versions-registry/versions/n-/no-versions.json: note: the version database file should be here +note: run 'vcpkg x-add-version no-versions' to create the version database file $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: no-versions@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/no-versions/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/no-versions/vcpkg.json: message: all version constraints are consistent with the version database $TestingRoot/ci-verify-versions-registry/ports/override-not-in-versions-database: message: override-not-in-versions-database@1.0 is correctly in the version database (0ff80cd22d5ca881efab3329ce596566a8642bec) $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: override-not-in-versions-database@1.0 matches the current baseline $TestingRoot/ci-verify-versions-registry/ports/override-not-in-versions-database/vcpkg.json: error: the version override no-versions does not exist in the version database; does that port exist? $TestingRoot/ci-verify-versions-registry/ports/override-version-not-in-versions-database: message: override-version-not-in-versions-database@1.0 is correctly in the version database (49fafaad46408296e50e9d0fd1a3d531bf97d420) $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: override-version-not-in-versions-database@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/override-version-not-in-versions-database/vcpkg.json: error: the override of good names version 0.9 which does not exist in the version database. Installing this port at the top level will fail as that version will be unresolvable. Consider removing the version override or choosing a value declared in $TestingRoot/ci-verify-versions-registry/versions/g-/good.json. -$TestingRoot/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json: error: version-mismatch@1.1 was not found in versions database $TestingRoot/ci-verify-versions-registry/versions/v-/version-mismatch.json. -note: run 'vcpkg x-add-version version-mismatch' to add the new port version. +$TestingRoot/ci-verify-versions-registry/ports/override-version-not-in-versions-database/vcpkg.json: error: the override of good names version 0.9 which does not exist in the version database. Installing this port at the top level will fail as that version will be unresolvable. +$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: note: consider removing the version override or choosing a value declared here +$TestingRoot/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json: error: version-mismatch@1.1 was not found in versions database +$TestingRoot/ci-verify-versions-registry/versions/v-/version-mismatch.json: note: the version should be in this file +note: run 'vcpkg x-add-version version-mismatch' to add the new port version $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-mismatch@1.1 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json: All version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/ports/version-missing/vcpkg.json: error: version-missing@1.1 was not found in versions database $TestingRoot/ci-verify-versions-registry/versions/v-/version-missing.json. -note: run 'vcpkg x-add-version version-missing' to add the new port version. +$TestingRoot/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/version-missing/vcpkg.json: error: version-missing@1.1 was not found in versions database +$TestingRoot/ci-verify-versions-registry/versions/v-/version-missing.json: note: the version should be in this file +note: run 'vcpkg x-add-version version-missing' to add the new port version $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-missing@1.1 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/version-missing/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/version-missing/vcpkg.json: message: all version constraints are consistent with the version database $TestingRoot/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json: error: 1.1 is declared version-string, but version-scheme-mismatch is declared with version $TestingRoot/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json: note: version-scheme-mismatch is declared here note: versions must be unique, even if they are declared with different schemes note: you can overwrite version-scheme-mismatch@1.1 with correct local values by running: vcpkg x-add-version version-scheme-mismatch --overwrite-version $TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-scheme-mismatch@1.1 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json: All version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json: message: all version constraints are consistent with the version database $TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: failed to execute: `"C:\Program Files\Git\cmd\git.exe`" `"--git-dir=$TestingRoot/ci-verify-versions-registry/.git`" `"--work-tree=$buildtreesRoot/versioning_/versions/bad-git-tree/000000070c5f496fcf1a97cf654d5e81f0d2685a_82336.tmp`" -c core.autocrlf=false read-tree -m -u 000000070c5f496fcf1a97cf654d5e81f0d2685a error: git failed with exit code: (128). fatal: failed to unpack tree object 000000070c5f496fcf1a97cf654d5e81f0d2685a @@ -113,6 +132,7 @@ $TestingRoot/ci-verify-versions-registry/versions/d-/dependency-not-in-versions- $TestingRoot/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database.json: message: dependency-version-not-in-versions-database@1.0 is correctly in the version database (f0d44555fe7714929e432ab9e12a436e28ffef9e) $TestingRoot/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database-feature.json: message: dependency-version-not-in-versions-database-feature@1.0 is correctly in the version database (ba3008bb2d42c61f172b7d9592de0212edf20fc6) $TestingRoot/ci-verify-versions-registry/versions/g-/good.json: message: good@1.0 is correctly in the version database (0f3d67db0dbb6aa5499bc09367a606b495e16d35) +$TestingRoot/ci-verify-versions-registry/versions/h-/has-local-edits.json: message: has-local-edits@1.0.0 is correctly in the version database (b1d7f6030942b329a200f16c931c01e2ec9e1e79) $TestingRoot/ci-verify-versions-registry/versions/m-/malformed.json: $buildtreesRoot/versioning_/versions/malformed/a1f22424b0fb1460200c12e1b7933f309f9c8373/vcpkg.json:4:3: error: Unexpected character; expected property name on expression: ~broken ^ @@ -143,14 +163,17 @@ function Sanitize() { $workTreeRegex = 'error: failed to execute:[^\r\n]+' # Git command line has an unpredictable PID inside $text = $text.Replace('\', '/').Replace('`r`n', '`n').Trim() $text = [System.Text.RegularExpressions.Regex]::Replace($text, $workTreeRegex, '') + return $text } $expected = Sanitize $expected $actual = Sanitize $actual if ($actual -ne $expected) { - Write-Host "Expected:" + Write-Host "========= Expected =========" Write-Host $expected - Write-Host "Actual:" + Set-Content -Value $expected -LiteralPath "$TestingRoot/expected.txt" + Write-Host "========= Actual =========" Write-Host $actual + Set-Content -Value $actual -LiteralPath "$TestingRoot/actual.txt" throw "Bad x-ci-verify-versions output." } diff --git a/include/vcpkg/base/message-args.inc.h b/include/vcpkg/base/message-args.inc.h index 317f19853b..e761c21861 100644 --- a/include/vcpkg/base/message-args.inc.h +++ b/include/vcpkg/base/message-args.inc.h @@ -29,6 +29,10 @@ DECLARE_MSG_ARG(exit_code, "127") DECLARE_MSG_ARG(expected_version, "1.3.8") DECLARE_MSG_ARG(extension, ".exe") DECLARE_MSG_ARG(feature, "avisynthplus") +DECLARE_MSG_ARG( + git_tree_sha, + "7cfad47ae9f68b183983090afd6337cd60fd4949 (see " + "https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish )") DECLARE_MSG_ARG(json_field, "identifer") DECLARE_MSG_ARG(json_type, "an array of identifiers") DECLARE_MSG_ARG(lower, "42") diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 371e066544..4d825b8a43 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -282,10 +282,6 @@ DECLARE_MESSAGE(BaselineConflict, "", "Specifying vcpkg-configuration.default-registry in a manifest file conflicts with built-in " "baseline.\nPlease remove one of these conflicting settings.") -DECLARE_MESSAGE(BaselineFileNoDefaultField, - (msg::commit_sha), - "", - "The baseline file at commit {commit_sha} was invalid (no \"default\" field).") DECLARE_MESSAGE(BaselineGitShowFailed, (msg::commit_sha), "", @@ -2063,6 +2059,10 @@ DECLARE_MESSAGE(LocalPortfileVersion, "Using local portfile versions. To update the local portfiles, use `git pull`.") DECLARE_MESSAGE(ManifestConflict2, (), "", "Found both a manifest and CONTROL files; please rename one or the other") DECLARE_MESSAGE(ManifestFormatCompleted, (), "", "Succeeded in formatting the manifest files.") +DECLARE_MESSAGE(MessageMessage, + (), + "printed after a path and before an informational message on the terminal", + "message: ") DECLARE_MESSAGE(MismatchedBinParagraphs, (), "", @@ -2966,13 +2966,16 @@ DECLARE_MESSAGE( (msg::path, msg::expected_version, msg::actual_version), "", "Expected {path} version: [{expected_version}], but was [{actual_version}]. Please re-run bootstrap-vcpkg.") -DECLARE_MESSAGE(VersionConstraintNotInDatabase, - (msg::package_name, msg::version, msg::path), +DECLARE_MESSAGE(VersionConstraintNotInDatabase1, + (msg::package_name, msg::version), "", "the \"version>=\" constraint to {package_name} names version {version} which does not exist in the " - "version database. All versions must exist in the version database to be interpreted by vcpkg. " - "Consider removing the version constraint or choosing a value declared in {path}.") -DECLARE_MESSAGE(VersionConstraintOk, (), "", "All version constraints are consistent with the version database") + "version database. All versions must exist in the version database to be interpreted by vcpkg.") +DECLARE_MESSAGE(VersionConstraintNotInDatabase2, + (), + "", + "consider removing the version constraint or choosing a value declared here") +DECLARE_MESSAGE(VersionConstraintOk, (), "", "all version constraints are consistent with the version database") DECLARE_MESSAGE(VersionConstraintPortVersionMustBePositiveInteger, (), "", @@ -2989,11 +2992,12 @@ DECLARE_MESSAGE(VersionConstraintViolated, "", "dependency {spec} was expected to be at least version " "{expected_version}, but is currently {actual_version}.") -DECLARE_MESSAGE(VersionDatabaseFileMissing, - (msg::package_name, msg::path), +DECLARE_MESSAGE(VersionDatabaseFileMissing, (), "", "this port is not in the version database") +DECLARE_MESSAGE(VersionDatabaseFileMissing2, (), "", "the version database file should be here") +DECLARE_MESSAGE(VersionDatabaseFileMissing3, + (msg::command_line), "", - "missing a version database file at {path}\n" - "note: run 'vcpkg x-add-version {package_name}' to create the version database file.") + "run '{command_line}' to create the version database file") DECLARE_MESSAGE(VersionDatabaseEntryMissing, (msg::package_name, msg::version), "", @@ -3019,9 +3023,9 @@ DECLARE_MESSAGE(VersionIncomparable3, "This can be resolved by adding an explicit override to the preferred version. For example:") DECLARE_MESSAGE(VersionIncomparable4, (msg::url), "", "See `vcpkg help versioning` or {url} for more information.") DECLARE_MESSAGE(VersionInDeclarationDoesNotMatch, - (msg::commit_sha, msg::expected, msg::actual), + (msg::git_tree_sha, msg::expected, msg::actual), "{expected} and {actual} are version specs", - "{commit_sha} is declared to contain {expected}, but appears to contain {actual}") + "{git_tree_sha} is declared to contain {expected}, but appears to contain {actual}") DECLARE_MESSAGE( VersionInvalidDate, (msg::version), @@ -3050,21 +3054,28 @@ DECLARE_MESSAGE(VersionNotFound, "{expected} and {actual} are versions", "{expected} not available, only {actual} is available") DECLARE_MESSAGE(VersionNotFoundInVersionsFile2, - (msg::version_spec, msg::package_name, msg::path), + (msg::version_spec), "", - "{version_spec} was not found in versions database {path}.\n" - "note: run 'vcpkg x-add-version {package_name}' to add the new port version.") + "{version_spec} was not found in versions database") +DECLARE_MESSAGE(VersionNotFoundInVersionsFile3, (), "", "the version should be in this file") +DECLARE_MESSAGE(VersionNotFoundInVersionsFile4, + (msg::command_line), + "", + "run '{command_line}' to add the new port version") DECLARE_MESSAGE(VersionOverrideNotInVersionDatabase, (msg::package_name), "", "the version override {package_name} does not exist in the version database; does that port exist?") DECLARE_MESSAGE( - VersionOverrideVersionNotInVersionDatabase, - (msg::package_name, msg::version, msg::path), + VersionOverrideVersionNotInVersionDatabase1, + (msg::package_name, msg::version), "", "the override of {package_name} names version {version} which does not exist in the " - "version database. Installing this port at the top level will fail as that version will be unresolvable. " - "Consider removing the version override or choosing a value declared in {path}.") + "version database. Installing this port at the top level will fail as that version will be unresolvable.") +DECLARE_MESSAGE(VersionOverrideVersionNotInVersionDatabase2, + (), + "", + "consider removing the version override or choosing a value declared here") DECLARE_MESSAGE(VersionOverwriteVersion, (msg::version_spec), "", @@ -3086,37 +3097,41 @@ DECLARE_MESSAGE(VersionSchemeMismatch1, "{expected} and {actual} are version schemes; it here refers to the {version}", "{version} is declared {expected}, but {package_name} is declared with {actual}") DECLARE_MESSAGE(VersionSchemeMismatch1Old, - (msg::version, msg::expected, msg::actual, msg::package_name, msg::commit_sha), + (msg::version, msg::expected, msg::actual, msg::package_name, msg::git_tree_sha), "{expected} and {actual} are version schemes; it here refers to the {version}", - "{version} is declared {expected}, but {package_name}@{commit_sha} is declared with {actual}") + "{version} is declared {expected}, but {package_name}@{git_tree_sha} is declared with {actual}") DECLARE_MESSAGE(VersionSchemeMismatch2, (), "", "versions must be unique, even if they are declared with different schemes") -DECLARE_MESSAGE( - VersionShaMismatch1, - (msg::version_spec, msg::expected, msg::actual, msg::package_name, msg::path), - "{expected} and {actual} are git tree SHAs. Console commands the user can run are printed after. 'git tree' is " - "https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish", - "{version_spec} is declared to have git tree {expected}, but the local port {path} has git tree " - "{actual}\n" - "note: if {version_spec} is already published, update the {package_name} manifest with a new version or " - "port-version, then add the new version by running:") -DECLARE_MESSAGE(VersionShaMismatch2, +DECLARE_MESSAGE(VersionShaMismatch1, + (msg::version_spec, msg::git_tree_sha), + "'git tree' is ", + "{version_spec} git tree {git_tree_sha} does not match the port directory") +DECLARE_MESSAGE(VersionShaMismatch2, (msg::git_tree_sha), "", "the port directory has git tree {git_tree_sha}") +DECLARE_MESSAGE(VersionShaMismatch3, (msg::version_spec), - "Console commands the user can run are printed after. 'git tree' is " - "https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish", - "note: if {version_spec} is not yet published, overwrite the previous git tree by running:") -DECLARE_MESSAGE(VersionShaMissing, - (msg::package_name, msg::path), "", - "Unknown git tree. This is usually caused by uncommitted changes.\n" - "note: You can commit your changes and add them to the version database by running:\n" - "git add \"{path}\"\n" - "git commit -m wip\n" - "vcpkg x-add-version {package_name}\n" - "git add versions\n" - "git commit --amend -m \"[{package_name}] Add new port\"") + "if {version_spec} is already published, update this file with a new version or port-version, commit " + "it, then add the new version by running:") +DECLARE_MESSAGE(VersionShaMismatch4, + (msg::version_spec), + "", + "if {version_spec} is not yet published, overwrite the previous git tree by running:") +DECLARE_MESSAGE( + VersionShaMissing1, + (), + "", + "the git tree of the port directory could not be determined. This is usually caused by uncommitted changes.") +DECLARE_MESSAGE(VersionShaMissing2, + (), + "", + "you can commit your changes and add them to the version database by running:") +DECLARE_MESSAGE(VersionShaMissing3, + (), + "This is short for 'work in progress' and must be enclosed in \" quotes if it is more than 1 word", + "wip") +DECLARE_MESSAGE(VersionShaMissing4, (msg::package_name), "", "[{package_name}] Add new port") DECLARE_MESSAGE(VersionSharpMustBeFollowedByPortVersion, (), "", @@ -3132,9 +3147,9 @@ DECLARE_MESSAGE(VersionSpecMismatch, "{actual_version}, but the version database indicates that it should be {expected_version}.") DECLARE_MESSAGE(VersionTableHeader, (), "", "Version") DECLARE_MESSAGE(VersionVerifiedOK2, - (msg::version_spec, msg::commit_sha), + (msg::version_spec, msg::git_tree_sha), "", - "message: {version_spec} is correctly in the version database ({commit_sha})") + "message: {version_spec} is correctly in the version database ({git_tree_sha})") DECLARE_MESSAGE(VSExaminedInstances, (), "", "The following Visual Studio instances were considered:") DECLARE_MESSAGE(VSExaminedPaths, (), "", "The following paths were examined for Visual Studio instances:") DECLARE_MESSAGE(VSNoInstances, (), "", "Could not locate a complete Visual Studio instance") @@ -3153,9 +3168,9 @@ DECLARE_MESSAGE(WarningMessageMustUsePrintWarning, DECLARE_MESSAGE(WarningsTreatedAsErrors, (), "", "previous warnings being interpreted as errors") DECLARE_MESSAGE(WhileCheckingOutBaseline, (msg::commit_sha), "", "while checking out baseline {commit_sha}") DECLARE_MESSAGE(WhileCheckingOutPortTreeIsh, - (msg::package_name, msg::commit_sha), + (msg::package_name, msg::git_tree_sha), "", - "while checking out port {package_name} with git tree {commit_sha}") + "while checking out port {package_name} with git tree {git_tree_sha}") DECLARE_MESSAGE(WhileGettingLocalTreeIshObjectsForPorts, (), "", "while getting local treeish objects for ports") DECLARE_MESSAGE(WhileLookingForSpec, (msg::spec), "", "while looking for {spec}:") DECLARE_MESSAGE(WhileLoadingBaselineVersionForPort, diff --git a/include/vcpkg/base/messages.h b/include/vcpkg/base/messages.h index 980df1b6d7..767784602b 100644 --- a/include/vcpkg/base/messages.h +++ b/include/vcpkg/base/messages.h @@ -267,14 +267,4 @@ namespace vcpkg #include #undef DECLARE_MESSAGE - - namespace msg - { - extern const decltype(vcpkg::msgErrorMessage) msgErrorMessage; - extern const decltype(vcpkg::msgWarningMessage) msgWarningMessage; - extern const decltype(vcpkg::msgNoteMessage) msgNoteMessage; - extern const decltype(vcpkg::msgSeeURL) msgSeeURL; - extern const decltype(vcpkg::msgInternalErrorMessage) msgInternalErrorMessage; - extern const decltype(vcpkg::msgInternalErrorMessageContact) msgInternalErrorMessageContact; - } } diff --git a/locales/messages.json b/locales/messages.json index b20a0b6ff2..58d185f8c0 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -190,8 +190,6 @@ "AzUrlAssetCacheRequiresBaseUrl": "unexpected arguments: asset config 'azurl' requires a base url", "AzUrlAssetCacheRequiresLessThanFour": "unexpected arguments: asset config 'azurl' requires fewer than 4 arguments", "BaselineConflict": "Specifying vcpkg-configuration.default-registry in a manifest file conflicts with built-in baseline.\nPlease remove one of these conflicting settings.", - "BaselineFileNoDefaultField": "The baseline file at commit {commit_sha} was invalid (no \"default\" field).", - "_BaselineFileNoDefaultField.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "BaselineGitShowFailed": "while checking out baseline from commit '{commit_sha}', failed to `git show` versions/baseline.json. This may be fixed by fetching commits with `git fetch`.", "_BaselineGitShowFailed.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", "BaselineMissing": "{package_name} is not assigned a version", @@ -1154,6 +1152,8 @@ "_LocalizedMessageMustNotEndWithNewline.comment": "{value} is a localized message name like LocalizedMessageMustNotEndWithNewline", "ManifestConflict2": "Found both a manifest and CONTROL files; please rename one or the other", "ManifestFormatCompleted": "Succeeded in formatting the manifest files.", + "MessageMessage": "message: ", + "_MessageMessage.comment": "printed after a path and before an informational message on the terminal", "MismatchedBinParagraphs": "The serialized binary paragraph was different from the original binary paragraph. Please open an issue at https://github.com/microsoft/vcpkg with the following output:", "MismatchedFiles": "file to store does not match hash", "MismatchedManifestAfterReserialize": "The serialized manifest was different from the original manifest. Please open an issue at https://github.com/microsoft/vcpkg, with the following output:", @@ -1645,9 +1645,10 @@ "_VersionCommandHeader.comment": "An example of {version} is 1.3.8.", "VersionConflictXML": "Expected {path} version: [{expected_version}], but was [{actual_version}]. Please re-run bootstrap-vcpkg.", "_VersionConflictXML.comment": "An example of {path} is /foo/bar. An example of {expected_version} is 1.3.8. An example of {actual_version} is 1.3.8.", - "VersionConstraintNotInDatabase": "the \"version>=\" constraint to {package_name} names version {version} which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. Consider removing the version constraint or choosing a value declared in {path}.", - "_VersionConstraintNotInDatabase.comment": "An example of {package_name} is zlib. An example of {version} is 1.3.8. An example of {path} is /foo/bar.", - "VersionConstraintOk": "All version constraints are consistent with the version database", + "VersionConstraintNotInDatabase1": "the \"version>=\" constraint to {package_name} names version {version} which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg.", + "_VersionConstraintNotInDatabase1.comment": "An example of {package_name} is zlib. An example of {version} is 1.3.8.", + "VersionConstraintNotInDatabase2": "consider removing the version constraint or choosing a value declared here", + "VersionConstraintOk": "all version constraints are consistent with the version database", "VersionConstraintPortVersionMustBePositiveInteger": "port-version (after the '#') in \"version>=\" must be a non-negative integer", "VersionConstraintUnresolvable": "Cannot resolve a minimum constraint for dependency {package_name} from {spec}.\nThe dependency was not found in the baseline, indicating that the package did not exist at that time. This may be fixed by providing an explicit override version via the \"overrides\" field or by updating the baseline.\nSee `vcpkg help versioning` for more information.", "_VersionConstraintUnresolvable.comment": "An example of {package_name} is zlib. An example of {spec} is zlib:x64-windows.", @@ -1655,12 +1656,14 @@ "_VersionConstraintViolated.comment": "An example of {spec} is zlib:x64-windows. An example of {expected_version} is 1.3.8. An example of {actual_version} is 1.3.8.", "VersionDatabaseEntryMissing": "no version entry for {package_name} at {version}.", "_VersionDatabaseEntryMissing.comment": "An example of {package_name} is zlib. An example of {version} is 1.3.8.", - "VersionDatabaseFileMissing": "missing a version database file at {path}\nnote: run 'vcpkg x-add-version {package_name}' to create the version database file.", - "_VersionDatabaseFileMissing.comment": "An example of {package_name} is zlib. An example of {path} is /foo/bar.", + "VersionDatabaseFileMissing": "this port is not in the version database", + "VersionDatabaseFileMissing2": "the version database file should be here", + "VersionDatabaseFileMissing3": "run '{command_line}' to create the version database file", + "_VersionDatabaseFileMissing3.comment": "An example of {command_line} is vcpkg install zlib.", "VersionGitEntryMissing": "no version database entry for {package_name} at {version}.\nAvailable versions:", "_VersionGitEntryMissing.comment": "A list of versions, 1 per line, are printed after this message. An example of {package_name} is zlib. An example of {version} is 1.3.8.", - "VersionInDeclarationDoesNotMatch": "{commit_sha} is declared to contain {expected}, but appears to contain {actual}", - "_VersionInDeclarationDoesNotMatch.comment": "{expected} and {actual} are version specs An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", + "VersionInDeclarationDoesNotMatch": "{git_tree_sha} is declared to contain {expected}, but appears to contain {actual}", + "_VersionInDeclarationDoesNotMatch.comment": "{expected} and {actual} are version specs An example of {git_tree_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949 (see https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish ).", "VersionIncomparable1": "version conflict on {spec}: {constraint_origin} required {expected}, which cannot be compared with the baseline version {actual}.", "_VersionIncomparable1.comment": "{expected} and {actual} are versions like 1.0 An example of {spec} is zlib:x64-windows. An example of {constraint_origin} is zlib:x64-windows@1.0.0.", "VersionIncomparable2": "{version_spec} has scheme {new_scheme}", @@ -1683,12 +1686,16 @@ "_VersionMissingRequiredFeature.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {feature} is avisynthplus. An example of {constraint_origin} is zlib:x64-windows@1.0.0.", "VersionNotFound": "{expected} not available, only {actual} is available", "_VersionNotFound.comment": "{expected} and {actual} are versions", - "VersionNotFoundInVersionsFile2": "{version_spec} was not found in versions database {path}.\nnote: run 'vcpkg x-add-version {package_name}' to add the new port version.", - "_VersionNotFoundInVersionsFile2.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {package_name} is zlib. An example of {path} is /foo/bar.", + "VersionNotFoundInVersionsFile2": "{version_spec} was not found in versions database", + "_VersionNotFoundInVersionsFile2.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0.", + "VersionNotFoundInVersionsFile3": "the version should be in this file", + "VersionNotFoundInVersionsFile4": "run '{command_line}' to add the new port version", + "_VersionNotFoundInVersionsFile4.comment": "An example of {command_line} is vcpkg install zlib.", "VersionOverrideNotInVersionDatabase": "the version override {package_name} does not exist in the version database; does that port exist?", "_VersionOverrideNotInVersionDatabase.comment": "An example of {package_name} is zlib.", - "VersionOverrideVersionNotInVersionDatabase": "the override of {package_name} names version {version} which does not exist in the version database. Installing this port at the top level will fail as that version will be unresolvable. Consider removing the version override or choosing a value declared in {path}.", - "_VersionOverrideVersionNotInVersionDatabase.comment": "An example of {package_name} is zlib. An example of {version} is 1.3.8. An example of {path} is /foo/bar.", + "VersionOverrideVersionNotInVersionDatabase1": "the override of {package_name} names version {version} which does not exist in the version database. Installing this port at the top level will fail as that version will be unresolvable.", + "_VersionOverrideVersionNotInVersionDatabase1.comment": "An example of {package_name} is zlib. An example of {version} is 1.3.8.", + "VersionOverrideVersionNotInVersionDatabase2": "consider removing the version override or choosing a value declared here", "VersionOverwriteVersion": "you can overwrite {version_spec} with correct local values by running:", "_VersionOverwriteVersion.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0.", "VersionRejectedDueToBaselineMissing": "{path} was rejected because it uses \"{json_field}\" and does not have a \"builtin-baseline\". This can be fixed by removing the uses of \"{json_field}\" or adding a \"builtin-baseline\".\nSee `vcpkg help versioning` for more information.", @@ -1697,22 +1704,30 @@ "_VersionRejectedDueToFeatureFlagOff.comment": "An example of {path} is /foo/bar. An example of {json_field} is identifer.", "VersionSchemeMismatch1": "{version} is declared {expected}, but {package_name} is declared with {actual}", "_VersionSchemeMismatch1.comment": "{expected} and {actual} are version schemes; it here refers to the {version} An example of {version} is 1.3.8. An example of {package_name} is zlib.", - "VersionSchemeMismatch1Old": "{version} is declared {expected}, but {package_name}@{commit_sha} is declared with {actual}", - "_VersionSchemeMismatch1Old.comment": "{expected} and {actual} are version schemes; it here refers to the {version} An example of {version} is 1.3.8. An example of {package_name} is zlib. An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", + "VersionSchemeMismatch1Old": "{version} is declared {expected}, but {package_name}@{git_tree_sha} is declared with {actual}", + "_VersionSchemeMismatch1Old.comment": "{expected} and {actual} are version schemes; it here refers to the {version} An example of {version} is 1.3.8. An example of {package_name} is zlib. An example of {git_tree_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949 (see https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish ).", "VersionSchemeMismatch2": "versions must be unique, even if they are declared with different schemes", - "VersionShaMismatch1": "{version_spec} is declared to have git tree {expected}, but the local port {path} has git tree {actual}\nnote: if {version_spec} is already published, update the {package_name} manifest with a new version or port-version, then add the new version by running:", - "_VersionShaMismatch1.comment": "{expected} and {actual} are git tree SHAs. Console commands the user can run are printed after. 'git tree' is https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {package_name} is zlib. An example of {path} is /foo/bar.", - "VersionShaMismatch2": "note: if {version_spec} is not yet published, overwrite the previous git tree by running:", - "_VersionShaMismatch2.comment": "Console commands the user can run are printed after. 'git tree' is https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish An example of {version_spec} is zlib:x64-windows@1.0.0.", - "VersionShaMissing": "Unknown git tree. This is usually caused by uncommitted changes.\nnote: You can commit your changes and add them to the version database by running:\ngit add \"{path}\"\ngit commit -m wip\nvcpkg x-add-version {package_name}\ngit add versions\ngit commit --amend -m \"[{package_name}] Add new port\"", - "_VersionShaMissing.comment": "An example of {package_name} is zlib. An example of {path} is /foo/bar.", + "VersionShaMismatch1": "{version_spec} git tree {git_tree_sha} does not match the port directory", + "_VersionShaMismatch1.comment": "'git tree' is An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {git_tree_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949 (see https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish ).", + "VersionShaMismatch2": "the port directory has git tree {git_tree_sha}", + "_VersionShaMismatch2.comment": "An example of {git_tree_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949 (see https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish ).", + "VersionShaMismatch3": "if {version_spec} is already published, update this file with a new version or port-version, commit it, then add the new version by running:", + "_VersionShaMismatch3.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0.", + "VersionShaMismatch4": "if {version_spec} is not yet published, overwrite the previous git tree by running:", + "_VersionShaMismatch4.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0.", + "VersionShaMissing1": "the git tree of the port directory could not be determined. This is usually caused by uncommitted changes.", + "VersionShaMissing2": "you can commit your changes and add them to the version database by running:", + "VersionShaMissing3": "wip", + "_VersionShaMissing3.comment": "This is short for 'work in progress' and must be enclosed in \" quotes if it is more than 1 word", + "VersionShaMissing4": "[{package_name}] Add new port", + "_VersionShaMissing4.comment": "An example of {package_name} is zlib.", "VersionSharpMustBeFollowedByPortVersion": "'#' in version text must be followed by a port version", "VersionSharpMustBeFollowedByPortVersionNonNegativeInteger": "'#' in version text must be followed by a port version (a non-negative integer)", "VersionSpecMismatch": "Failed to load port because versions are inconsistent. The file \"{path}\" contains the version {actual_version}, but the version database indicates that it should be {expected_version}.", "_VersionSpecMismatch.comment": "An example of {path} is /foo/bar. An example of {expected_version} is 1.3.8. An example of {actual_version} is 1.3.8.", "VersionTableHeader": "Version", - "VersionVerifiedOK2": "message: {version_spec} is correctly in the version database ({commit_sha})", - "_VersionVerifiedOK2.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", + "VersionVerifiedOK2": "message: {version_spec} is correctly in the version database ({git_tree_sha})", + "_VersionVerifiedOK2.comment": "An example of {version_spec} is zlib:x64-windows@1.0.0. An example of {git_tree_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949 (see https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish ).", "WaitingForChildrenToExit": "Waiting for child processes to exit...", "WaitingToTakeFilesystemLock": "waiting to take filesystem lock on {path}...", "_WaitingToTakeFilesystemLock.comment": "An example of {path} is /foo/bar.", @@ -1723,8 +1738,8 @@ "WarningsTreatedAsErrors": "previous warnings being interpreted as errors", "WhileCheckingOutBaseline": "while checking out baseline {commit_sha}", "_WhileCheckingOutBaseline.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", - "WhileCheckingOutPortTreeIsh": "while checking out port {package_name} with git tree {commit_sha}", - "_WhileCheckingOutPortTreeIsh.comment": "An example of {package_name} is zlib. An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", + "WhileCheckingOutPortTreeIsh": "while checking out port {package_name} with git tree {git_tree_sha}", + "_WhileCheckingOutPortTreeIsh.comment": "An example of {package_name} is zlib. An example of {git_tree_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949 (see https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish ).", "WhileGettingLocalTreeIshObjectsForPorts": "while getting local treeish objects for ports", "WhileLoadingBaselineVersionForPort": "while loading baseline version for {package_name}", "_WhileLoadingBaselineVersionForPort.comment": "An example of {package_name} is zlib.", diff --git a/src/vcpkg/base/checks.cpp b/src/vcpkg/base/checks.cpp index 020e45e1bb..6e7c5fc7b5 100644 --- a/src/vcpkg/base/checks.cpp +++ b/src/vcpkg/base/checks.cpp @@ -89,11 +89,11 @@ namespace vcpkg if (!expression) { msg::println(Color::error, - msg::format(msg::msgInternalErrorMessage) + msg::format(msgInternalErrorMessage) .append(locale_invariant_lineinfo(line_info)) .append(msgChecksFailedCheck) .append_raw('\n') - .append(msg::msgInternalErrorMessageContact)); + .append(msgInternalErrorMessageContact)); exit_fail(line_info); } } @@ -103,11 +103,11 @@ namespace vcpkg if (!expression) { msg::println(Color::error, - msg::format(msg::msgInternalErrorMessage) + msg::format(msgInternalErrorMessage) .append(locale_invariant_lineinfo(line_info)) .append_raw(error_message) .append_raw('\n') - .append(msg::msgInternalErrorMessageContact)); + .append(msgInternalErrorMessageContact)); exit_fail(line_info); } } @@ -122,7 +122,7 @@ namespace vcpkg static void display_upgrade_message() { - msg::println(Color::error, msg::format(msg::msgNoteMessage).append(msgChecksUpdateVcpkg)); + msg::println(Color::error, msg::format(msgNoteMessage).append(msgChecksUpdateVcpkg)); } [[noreturn]] void Checks::exit_maybe_upgrade(const LineInfo& line_info) diff --git a/src/vcpkg/base/hash.cpp b/src/vcpkg/base/hash.cpp index 81608efe6a..c0103db4ec 100644 --- a/src/vcpkg/base/hash.cpp +++ b/src/vcpkg/base/hash.cpp @@ -565,7 +565,7 @@ namespace vcpkg::Hash auto file = fs.open_for_read(path, ec); if (ec) { - return msg::format(msg::msgErrorMessage) + return msg::format(msgErrorMessage) .append(msgHashFileFailureToRead, msg::path = path) .append_raw(ec.message()); } @@ -582,7 +582,7 @@ namespace vcpkg::Hash } else if ((ec = file.error())) { - return msg::format(msg::msgErrorMessage) + return msg::format(msgErrorMessage) .append(msgHashFileFailureToRead, msg::path = path) .append_raw(ec.message()); } diff --git a/src/vcpkg/base/message_sinks.cpp b/src/vcpkg/base/message_sinks.cpp index 62ffcebed2..c1f92349d0 100644 --- a/src/vcpkg/base/message_sinks.cpp +++ b/src/vcpkg/base/message_sinks.cpp @@ -32,12 +32,12 @@ namespace vcpkg void MessageSink::println_warning(const LocalizedString& s) { - println(Color::warning, format(msg::msgWarningMessage).append(s)); + println(Color::warning, format(msgWarningMessage).append(s)); } void MessageSink::println_error(const LocalizedString& s) { - println(Color::error, format(msg::msgErrorMessage).append(s)); + println(Color::error, format(msgErrorMessage).append(s)); } MessageSink& null_sink = null_sink_instance; diff --git a/src/vcpkg/base/messages.cpp b/src/vcpkg/base/messages.cpp index c2ca00e5d3..374cae96da 100644 --- a/src/vcpkg/base/messages.cpp +++ b/src/vcpkg/base/messages.cpp @@ -276,17 +276,6 @@ namespace vcpkg #include #undef DECLARE_MESSAGE - - namespace msg - { - const decltype(vcpkg::msgErrorMessage) msgErrorMessage = vcpkg::msgErrorMessage; - const decltype(vcpkg::msgWarningMessage) msgWarningMessage = vcpkg::msgWarningMessage; - const decltype(vcpkg::msgNoteMessage) msgNoteMessage = vcpkg::msgNoteMessage; - const decltype(vcpkg::msgSeeURL) msgSeeURL = vcpkg::msgSeeURL; - const decltype(vcpkg::msgInternalErrorMessage) msgInternalErrorMessage = vcpkg::msgInternalErrorMessage; - const decltype(vcpkg::msgInternalErrorMessageContact) msgInternalErrorMessageContact = - vcpkg::msgInternalErrorMessageContact; - } } namespace vcpkg::msg { diff --git a/src/vcpkg/base/parse.cpp b/src/vcpkg/base/parse.cpp index 2b1bedc5d3..363ab554c7 100644 --- a/src/vcpkg/base/parse.cpp +++ b/src/vcpkg/base/parse.cpp @@ -38,11 +38,11 @@ namespace vcpkg res = LocalizedString::from_raw(fmt::format("{}:{}:{}: ", origin, location.row, location.column)); if (kind == MessageKind::Warning) { - res.append(msg::msgWarningMessage); + res.append(msgWarningMessage); } else { - res.append(msg::msgErrorMessage); + res.append(msgErrorMessage); } res.append(message); diff --git a/src/vcpkg/binarycaching.cpp b/src/vcpkg/binarycaching.cpp index fcb035a278..ad78d9c761 100644 --- a/src/vcpkg/binarycaching.cpp +++ b/src/vcpkg/binarycaching.cpp @@ -2307,23 +2307,23 @@ ExpectedL vcpkg::parse_download_configuration(const Optio { return LocalizedString::from_raw(err->to_string()) // note that this already contains error: .append_raw('\n') - .append(msg::msgNoteMessage) - .append(msg::msgSeeURL, msg::url = docs::assetcaching_url); + .append(msgNoteMessage) + .append(msgSeeURL, msg::url = docs::assetcaching_url); } if (s.azblob_templates_to_put.size() > 1) { return msg::format_error(msgAMaximumOfOneAssetWriteUrlCanBeSpecified) .append_raw('\n') - .append(msg::msgNoteMessage) - .append(msg::msgSeeURL, msg::url = docs::assetcaching_url); + .append(msgNoteMessage) + .append(msgSeeURL, msg::url = docs::assetcaching_url); } if (s.url_templates_to_get.size() > 1) { return msg::format_error(msgAMaximumOfOneAssetReadUrlCanBeSpecified) .append_raw('\n') - .append(msg::msgNoteMessage) - .append(msg::msgSeeURL, msg::url = docs::assetcaching_url); + .append(msgNoteMessage) + .append(msgSeeURL, msg::url = docs::assetcaching_url); } Optional get_url; diff --git a/src/vcpkg/commands.add.cpp b/src/vcpkg/commands.add.cpp index 1635541564..ae28abdffb 100644 --- a/src/vcpkg/commands.add.cpp +++ b/src/vcpkg/commands.add.cpp @@ -104,7 +104,7 @@ namespace vcpkg .error() .append_raw('\n') .append(msgNoteMessage) - .append(msg::msgSeeURL, msg::url = docs::manifests_url) + .append(msgSeeURL, msg::url = docs::manifests_url) .append_raw('\n')); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/src/vcpkg/commands.build.cpp b/src/vcpkg/commands.build.cpp index 27cc3f7a68..0c4d91d073 100644 --- a/src/vcpkg/commands.build.cpp +++ b/src/vcpkg/commands.build.cpp @@ -166,7 +166,7 @@ namespace vcpkg msg::print(msgElapsedForPackage, msg::spec = spec, msg::elapsed = build_timer); if (result.code == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES) { - LocalizedString errorMsg = msg::format(msg::msgErrorMessage).append(msgBuildDependenciesMissing); + LocalizedString errorMsg = msg::format(msgErrorMessage).append(msgBuildDependenciesMissing); for (const auto& p : result.unmet_dependencies) { errorMsg.append_raw('\n').append_indent().append_raw(p.to_string()); @@ -339,7 +339,7 @@ namespace vcpkg msg::arch = target_architecture, msg::path = toolset.visual_studio_root_path, msg::list = toolset_list); - msg::println(msg::msgSeeURL, msg::url = docs::vcpkg_visual_studio_path_url); + msg::println(msgSeeURL, msg::url = docs::vcpkg_visual_studio_path_url); Checks::exit_maybe_upgrade(VCPKG_LINE_INFO); } #endif diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index e6a3304566..4a7faee0a4 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -92,7 +92,7 @@ namespace .append_raw(": ") .append(msgErrorMessage) .append(msgVersionInDeclarationDoesNotMatch, - msg::commit_sha = version_entry.git_tree, + msg::git_tree_sha = version_entry.git_tree, msg::expected = version_entry_spec, msg::actual = scfl_spec) .append_raw('\n')); @@ -110,7 +110,7 @@ namespace msg::expected = get_scheme_name(version_entry.version.scheme), msg::actual = get_scheme_name(git_tree_version.scheme), msg::package_name = port_name, - msg::commit_sha = version_entry.git_tree) + msg::git_tree_sha = version_entry.git_tree) .append_raw('\n') .append_raw(scfl->control_location) .append_raw(": ") @@ -128,7 +128,7 @@ namespace .append_raw(": ") .append(msgVersionVerifiedOK2, msg::version_spec = VersionSpec{port_name, version_entry.version.version}, - msg::commit_sha = version_entry.git_tree) + msg::git_tree_sha = version_entry.git_tree) .append_raw('\n')); } @@ -159,14 +159,22 @@ namespace LocalizedString::from_raw(scfl.control_location) .append_raw(": ") .append(msgErrorMessage) - .append(msgVersionDatabaseFileMissing, - msg::package_name = port_name, - msg::path = versions_database_entry.versions_file_path) + .append(msgVersionDatabaseFileMissing) + .append_raw('\n') + .append_raw(versions_database_entry.versions_file_path) + .append_raw(": ") + .append(msgNoteMessage) + .append(msgVersionDatabaseFileMissing2) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgVersionDatabaseFileMissing3, + msg::command_line = fmt::format("vcpkg x-add-version {}", port_name)) .append_raw('\n')); return success; } const auto local_port_version = scfl.source_control_file->to_schemed_version(); + const auto local_version_spec = VersionSpec{port_name, local_port_version.version}; auto versions_end = entries->end(); auto it = std::find_if(entries->begin(), versions_end, [&](const GitVersionDbEntry& entry) { @@ -181,9 +189,16 @@ namespace .append_raw(": ") .append(msgErrorMessage) .append(msgVersionNotFoundInVersionsFile2, - msg::version_spec = VersionSpec{port_name, local_port_version.version}, - msg::package_name = port_name, - msg::path = versions_database_entry.versions_file_path) + msg::version_spec = VersionSpec{port_name, local_port_version.version}) + .append_raw('\n') + .append_raw(versions_database_entry.versions_file_path) + .append_raw(": ") + .append(msgNoteMessage) + .append(msgVersionNotFoundInVersionsFile3) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgVersionNotFoundInVersionsFile4, + msg::command_line = fmt::format("vcpkg x-add-version {}", port_name)) .append_raw('\n')); return success; } @@ -213,8 +228,7 @@ namespace .append(msgVersionSchemeMismatch2) .append_raw('\n') .append(msgNoteMessage) - .append(msgVersionOverwriteVersion, - msg::version_spec = VersionSpec{port_name, local_port_version.version}) + .append(msgVersionOverwriteVersion, msg::version_spec = local_version_spec) .append_raw(fmt::format("\nvcpkg x-add-version {} --overwrite-version\n", port_name))); } @@ -226,24 +240,31 @@ namespace .append_raw(": ") .append(msgErrorMessage) .append(msgVersionShaMismatch1, - msg::version_spec = VersionSpec{port_name, local_port_version.version}, - msg::expected = version_entry.git_tree, - msg::actual = local_git_tree, - msg::package_name = port_name, - msg::path = scfl.port_directory()) + msg::version_spec = local_version_spec, + msg::git_tree_sha = version_entry.git_tree) + .append_raw('\n') + .append_raw(scfl.port_directory()) + .append_raw(": ") + .append(msgNoteMessage) + .append(msgVersionShaMismatch2, msg::git_tree_sha = local_git_tree) + .append_raw('\n') + .append_raw(scfl.control_location) + .append_raw(": ") + .append(msgNoteMessage) + .append(msgVersionShaMismatch3, msg::version_spec = local_version_spec) .append_raw('\n') .append_indent() - .append_raw("vcpkg x-add-version " + port_name + "\n") + .append_raw(fmt::format("vcpkg x-add-version {}\n", port_name)) .append_indent() .append_raw("git add versions\n") .append_indent() .append(msgGitCommitUpdateVersionDatabase) .append_raw('\n') - .append(msgVersionShaMismatch2, - msg::version_spec = VersionSpec{port_name, local_port_version.version}) + .append(msgNoteMessage) + .append(msgVersionShaMismatch4, msg::version_spec = local_version_spec) .append_raw('\n') .append_indent() - .append_raw("vcpkg x-add-version " + port_name + " --overwrite-version\n") + .append_raw(fmt::format("vcpkg x-add-version {} --overwrite-version\n", port_name)) .append_indent() .append_raw("git add versions\n") .append_indent() @@ -256,8 +277,8 @@ namespace success_sink.print(LocalizedString::from_raw(scfl.port_directory()) .append_raw(": ") .append(msgVersionVerifiedOK2, - msg::version_spec = VersionSpec{port_name, local_port_version.version}, - msg::commit_sha = version_entry.git_tree) + msg::version_spec = local_version_spec, + msg::git_tree_sha = version_entry.git_tree) .append_raw('\n')); } @@ -380,10 +401,14 @@ namespace auto this_error = LocalizedString::from_raw(scfl.control_location) .append_raw(": ") .append(msgErrorMessage) - .append(msgVersionConstraintNotInDatabase, + .append(msgVersionConstraintNotInDatabase1, msg::package_name = dependency.name, - msg::version = *minimum_version, - msg::path = dependent_versions_db_entry.versions_file_path) + msg::version = *minimum_version) + .append_raw('\n') + .append_raw(dependent_versions_db_entry.versions_file_path) + .append_raw(": ") + .append(msgNoteMessage) + .append(msgVersionConstraintNotInDatabase2) .append_raw('\n'); if (feature_name) { @@ -454,10 +479,14 @@ namespace LocalizedString::from_raw(scfl.control_location) .append_raw(": ") .append(msgErrorMessage) - .append(msgVersionOverrideVersionNotInVersionDatabase, + .append(msgVersionOverrideVersionNotInVersionDatabase1, msg::package_name = override_.name, - msg::version = override_.version.version, - msg::path = override_versions_db_entry.versions_file_path) + msg::version = override_.version.version) + .append_raw('\n') + .append_raw(override_versions_db_entry.versions_file_path) + .append_raw(": ") + .append(msgNoteMessage) + .append(msgVersionOverrideVersionNotInVersionDatabase2) .append_raw('\n')); } } @@ -466,6 +495,7 @@ namespace { success_sink.print(LocalizedString::from_raw(scfl.control_location) .append_raw(": ") + .append(msgMessageMessage) .append(msgVersionConstraintOk) .append_raw('\n')); } @@ -543,8 +573,22 @@ namespace vcpkg LocalizedString::from_raw(scfl.control_location) .append_raw(": ") .append(msgErrorMessage) - .append(msgVersionShaMissing, msg::package_name = port_name, msg::path = scfl.port_directory()) - .append_raw('\n')); + .append(msgVersionShaMissing1) + .append_raw('\n') + .append(msgNoteMessage) + .append(msgVersionShaMissing2) + .append_raw('\n') + .append_indent() + .append_raw(fmt::format("git add \"{}\"\n", scfl.port_directory())) + .append_indent() + .append_raw(fmt::format("git commit -m {}\n", msg::format(msgVersionShaMissing3))) + .append_indent() + .append_raw(fmt::format("vcpkg x-add-version {}\n", port_name)) + .append_indent() + .append_raw("git add versions\n") + .append_indent() + .append_raw(fmt::format("git commit --amend -m \"{}\"\n", + msg::format(msgVersionShaMissing4, msg::package_name = port_name)))); } else { diff --git a/src/vcpkg/commands.install.cpp b/src/vcpkg/commands.install.cpp index 6df1105de2..c20342bc12 100644 --- a/src/vcpkg/commands.install.cpp +++ b/src/vcpkg/commands.install.cpp @@ -1026,7 +1026,7 @@ namespace vcpkg if (!options.command_arguments.empty()) { msg::println_error(msgErrorIndividualPackagesUnsupported); - msg::println(Color::error, msg::msgSeeURL, msg::url = docs::manifests_url); + msg::println(Color::error, msgSeeURL, msg::url = docs::manifests_url); failure = true; } if (use_head_version) diff --git a/src/vcpkg/portfileprovider.cpp b/src/vcpkg/portfileprovider.cpp index 6b8e8c27b1..56871b9f74 100644 --- a/src/vcpkg/portfileprovider.cpp +++ b/src/vcpkg/portfileprovider.cpp @@ -194,7 +194,7 @@ namespace vcpkg } else { - return msg::format(msg::msgErrorMessage) + return msg::format(msgErrorMessage) .append(msgVersionSpecMismatch, msg::path = path->port_directory, msg::expected_version = version_spec, diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index 8e44168fe4..6727456057 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -663,30 +663,30 @@ namespace fs.create_directories(destination_parent, ec); if (ec) { - return {msg::format(msg::msgErrorMessage) + return {msg::format(msgErrorMessage) .append(format_filesystem_call_error(ec, "create_directories", {destination_parent})) .append_raw('\n') - .append(msg::msgNoteMessage) + .append(msgNoteMessage) .append(msgWhileCheckingOutBaseline, msg::commit_sha = commit_sha), expected_right_tag}; } fs.write_contents(destination_tmp, *contents, ec); if (ec) { - return {msg::format(msg::msgErrorMessage) + return {msg::format(msgErrorMessage) .append(format_filesystem_call_error(ec, "write_contents", {destination_tmp})) .append_raw('\n') - .append(msg::msgNoteMessage) + .append(msgNoteMessage) .append(msgWhileCheckingOutBaseline, msg::commit_sha = commit_sha), expected_right_tag}; } fs.rename(destination_tmp, destination, ec); if (ec) { - return {msg::format(msg::msgErrorMessage) + return {msg::format(msgErrorMessage) .append(format_filesystem_call_error(ec, "rename", {destination_tmp, destination})) .append_raw('\n') - .append(msg::msgNoteMessage) + .append(msgNoteMessage) .append(msgWhileCheckingOutBaseline, msg::commit_sha = commit_sha), expected_right_tag}; } @@ -1082,7 +1082,7 @@ namespace { return format_version_git_entry_missing(port_name, version, port_versions) .append_raw('\n') - .append(msg::msgNoteMessage) + .append(msgNoteMessage) .append(msgChecksUpdateVcpkg); } @@ -1401,7 +1401,7 @@ namespace vcpkg ExpectedL> RegistrySet::baseline_for_port(StringView port_name) const { auto impl = registry_for_port(port_name); - if (!impl) return msg::format(msg::msgErrorMessage).append(msgNoRegistryForPort, msg::package_name = port_name); + if (!impl) return msg::format(msgErrorMessage).append(msgNoRegistryForPort, msg::package_name = port_name); return impl->get_baseline_version(port_name); } diff --git a/src/vcpkg/tools.cpp b/src/vcpkg/tools.cpp index 8b0762a752..c4cd4a2c62 100644 --- a/src/vcpkg/tools.cpp +++ b/src/vcpkg/tools.cpp @@ -839,7 +839,7 @@ namespace vcpkg } // If no acceptable tool was found and downloading was unavailable, emit an error message - LocalizedString s = msg::format(msg::msgErrorMessage); + LocalizedString s = msg::format(msgErrorMessage); s.append(msgToolFetchFailed, msg::tool_name = tool.tool_data_name()); if (env_force_system_binaries && download_available) { @@ -908,7 +908,7 @@ namespace vcpkg const auto tools = fs.find_from_PATH(Tools::TAR); if (tools.empty()) { - return msg::format(msg::msgErrorMessage) + return msg::format(msgErrorMessage) .append(msgToolFetchFailed, msg::tool_name = Tools::TAR) #if defined(_WIN32) .append(msgToolInWin10) @@ -948,7 +948,7 @@ namespace vcpkg } #endif - return msg::format(msg::msgErrorMessage) + return msg::format(msgErrorMessage) .append(msgToolFetchFailed, msg::tool_name = Tools::CMAKE) #if !defined(_WIN32) .append(msgInstallWithSystemManager) diff --git a/src/vcpkg/vcpkgpaths.cpp b/src/vcpkg/vcpkgpaths.cpp index da20f4d875..b1ec72a491 100644 --- a/src/vcpkg/vcpkgpaths.cpp +++ b/src/vcpkg/vcpkgpaths.cpp @@ -944,8 +944,8 @@ namespace vcpkg return std::move(maybe_tree) .error() - .append(msg::msgNoteMessage) - .append(msgWhileCheckingOutPortTreeIsh, msg::package_name = port_name, msg::commit_sha = git_tree); + .append(msgNoteMessage) + .append(msgWhileCheckingOutPortTreeIsh, msg::package_name = port_name, msg::git_tree_sha = git_tree); } ExpectedL VcpkgPaths::git_show(StringView treeish, const Path& dot_git_dir) const @@ -1005,7 +1005,7 @@ namespace vcpkg .append_raw('\n') .append(std::move(maybe_output).error()) .append_raw('\n') - .append(msg::msgNoteMessage) + .append(msgNoteMessage) .append(msgWhileGettingLocalTreeIshObjectsForPorts); } @@ -1190,7 +1190,7 @@ namespace vcpkg fs.rename_with_retry(git_tree_temp, destination, ec); if (ec) { - return msg::format(msg::msgErrorMessage) + return msg::format(msgErrorMessage) .append(format_filesystem_call_error(ec, "rename_with_retry", {git_tree_temp, destination})); } diff --git a/src/vcpkg/versions.cpp b/src/vcpkg/versions.cpp index de10ebfd7d..c02d3aa597 100644 --- a/src/vcpkg/versions.cpp +++ b/src/vcpkg/versions.cpp @@ -303,7 +303,7 @@ namespace vcpkg static LocalizedString format_invalid_date_version(StringView version) { - return msg::format(msg::msgErrorMessage).append(msg::format(msgVersionInvalidDate, msg::version = version)); + return msg::format(msgErrorMessage).append(msg::format(msgVersionInvalidDate, msg::version = version)); } ExpectedL DateVersion::try_parse(StringView version) From 1cfa496d006787b9d8185320e2dd7f960f8abf07 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 10 Oct 2023 02:29:02 -0700 Subject: [PATCH 37/48] Fixed 2 missing then patterns --- src/vcpkg/registries.cpp | 78 ++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index 6727456057..a8824d5668 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -1523,29 +1523,25 @@ namespace return format_filesystem_call_error(ec, "read_contents", {versions_file_path}); } - auto maybe_versions_json = Json::parse_object(contents, versions_file_path); - auto versions_json = maybe_versions_json.get(); - if (!versions_json) - { - return std::move(maybe_versions_json).error(); - } - - auto maybe_versions_array = versions_json->get("versions"); - if (!maybe_versions_array || !maybe_versions_array->is_array()) - { - return msg::format_error(msgFailedToParseNoVersionsArray, msg::path = versions_file_path); - } + return Json::parse_object(contents, versions_file_path) + .then([&](Json::Object&& versions_json) -> ExpectedL>> { + auto maybe_versions_array = versions_json.get("versions"); + if (!maybe_versions_array || !maybe_versions_array->is_array()) + { + return msg::format_error(msgFailedToParseNoVersionsArray, msg::path = versions_file_path); + } - std::vector db_entries; - GitVersionDbEntryArrayDeserializer deserializer{}; - Json::Reader r{versions_file_path}; - r.visit_in_key(*maybe_versions_array, "versions", db_entries, deserializer); - if (r.error_count() != 0) - { - return join(r.messages()); - } + std::vector db_entries; + GitVersionDbEntryArrayDeserializer deserializer{}; + Json::Reader r{versions_file_path}; + r.visit_in_key(*maybe_versions_array, "versions", db_entries, deserializer); + if (r.error_count() != 0) + { + return join(r.messages()); + } - return db_entries; + return db_entries; + }); } ExpectedL>> load_filesystem_versions_file_impl( @@ -1557,35 +1553,31 @@ namespace { if (ec == std::errc::no_such_file_or_directory) { - return Optional>{}; + return nullopt; } return format_filesystem_call_error(ec, "read_contents", {versions_file_path}); } - auto maybe_versions_json = Json::parse_object(contents, versions_file_path); - auto versions_json = maybe_versions_json.get(); - if (!versions_json) - { - return std::move(maybe_versions_json).error(); - } - - auto maybe_versions_array = versions_json->get("versions"); - if (!maybe_versions_array || !maybe_versions_array->is_array()) - { - return msg::format_error(msgFailedToParseNoVersionsArray, msg::path = versions_file_path); - } + return Json::parse_object(contents, versions_file_path) + .then([&](Json::Object&& versions_json) -> ExpectedL>> { + auto maybe_versions_array = versions_json.get("versions"); + if (!maybe_versions_array || !maybe_versions_array->is_array()) + { + return msg::format_error(msgFailedToParseNoVersionsArray, msg::path = versions_file_path); + } - std::vector db_entries; - FilesystemVersionDbEntryArrayDeserializer deserializer{registry_root}; - Json::Reader r{versions_file_path}; - r.visit_in_key(*maybe_versions_array, "versions", db_entries, deserializer); - if (r.error_count() != 0) - { - return join(r.messages()); - } + std::vector db_entries; + FilesystemVersionDbEntryArrayDeserializer deserializer{registry_root}; + Json::Reader r{versions_file_path}; + r.visit_in_key(*maybe_versions_array, "versions", db_entries, deserializer); + if (r.error_count() != 0) + { + return join(r.messages()); + } - return db_entries; + return db_entries; + }); } } // unnamed namespace From f7a9589ded8defca53218618c11ac0241483eb71 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 10 Oct 2023 10:00:40 -0700 Subject: [PATCH 38/48] Add diff output on test failure --- azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 index 2140cddaec..6372b48184 100644 --- a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 @@ -169,11 +169,8 @@ function Sanitize() { $expected = Sanitize $expected $actual = Sanitize $actual if ($actual -ne $expected) { - Write-Host "========= Expected =========" - Write-Host $expected Set-Content -Value $expected -LiteralPath "$TestingRoot/expected.txt" - Write-Host "========= Actual =========" - Write-Host $actual Set-Content -Value $actual -LiteralPath "$TestingRoot/actual.txt" + git diff --no-index -- "$TestingRoot/expected.txt" "$TestingRoot/actual.txt" throw "Bad x-ci-verify-versions output." } From 392a47c595d52e6e9177093f65adec91ccab8d56 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 10 Oct 2023 10:42:39 -0700 Subject: [PATCH 39/48] Try to fix linux and macos diffing --- .../ci-verify-versions.ps1 | 352 +++++++++--------- 1 file changed, 176 insertions(+), 176 deletions(-) diff --git a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 index 6372b48184..6ff05dc086 100644 --- a/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/ci-verify-versions.ps1 @@ -1,176 +1,176 @@ -. "$PSScriptRoot/../end-to-end-tests-prelude.ps1" - -Refresh-TestRoot - -Copy-Item -Recurse "$PSScriptRoot/../e2e-assets/ci-verify-versions-registry" "$TestingRoot/ci-verify-versions-registry" -git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions init -git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions add -A -git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions commit -m testing -Move-Item "$TestingRoot/ci-verify-versions-registry/old-port-versions/has-local-edits" "$TestingRoot/ci-verify-versions-registry/ports" - -$expected = @" -$TestingRoot/ci-verify-versions-registry/ports/malformed/vcpkg.json:4:3: error: Unexpected character; expected property name - on expression: ~broken - ^ -$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: bad-git-tree@1.1 git tree 000000070c5f496fcf1a97cf654d5e81f0d2685a does not match the port directory -$TestingRoot/ci-verify-versions-registry/ports/bad-git-tree: note: the port directory has git tree 6528b2c70c5f496fcf1a97cf654d5e81f0d2685a -$TestingRoot/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json: note: if bad-git-tree@1.1 is already published, update this file with a new version or port-version, commit it, then add the new version by running: - vcpkg x-add-version bad-git-tree - git add versions - git commit -m `"Update version database`" -note: if bad-git-tree@1.1 is not yet published, overwrite the previous git tree by running: - vcpkg x-add-version bad-git-tree --overwrite-version - git add versions - git commit -m `"Update version database`" -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: bad-git-tree@1.1 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json: message: all version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/ports/bad-history-name: message: bad-history-name@1.1 is correctly in the version database (f34f4ad3dfcc4d46d467d7b6aa04f9732a7951d6) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: bad-history-name@1.1 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/bad-history-name/vcpkg.json: message: all version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch: message: baseline-version-mismatch@1.1 is correctly in the version database (cf8a1faa9f94f7ceb9513d65093d407e11ac1402) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: baseline-version-mismatch is assigned 1.0, but the local port is 1.1 -$TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json: note: baseline-version-mismatch is declared here -note: you can run the following commands to add the current version of baseline-version-mismatch automatically: - vcpkg x-add-version baseline-version-mismatch - git add versions - git commit -m `"Update version database`" -$TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json: message: all version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing: message: baseline-version-missing@1.0 is correctly in the version database (a5c21769008f52ed66afa344f13b786dde4b8d7d) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: baseline-version-missing is not assigned a version -$TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json: note: baseline-version-missing is declared here -note: you can run the following commands to add the current version of baseline-version-missing automatically: - vcpkg x-add-version baseline-version-missing - git add versions - git commit -m `"Update version database`" -$TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json: message: all version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database: message: dependency-not-in-versions-database@1.0 is correctly in the version database (321c8b400526dc412a987285ef469eec6221a4b4) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-not-in-versions-database@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database/vcpkg.json: error: the dependency no-versions does not exist in the version database; does that port exist? -$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature: message: dependency-not-in-versions-database-feature@1.0 is correctly in the version database (2298ee25ea54ed92595250a2be07d01bdd76f47c) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-not-in-versions-database-feature@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature/vcpkg.json: error: the dependency no-versions does not exist in the version database; does that port exist? -note: the dependency is in the feature named add-things -$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database: message: dependency-version-not-in-versions-database@1.0 is correctly in the version database (f0d44555fe7714929e432ab9e12a436e28ffef9e) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-version-not-in-versions-database@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/vcpkg.json: error: the "version>=" constraint to good names version 0.9 which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. -$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: note: consider removing the version constraint or choosing a value declared here -$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature: message: dependency-version-not-in-versions-database-feature@1.0 is correctly in the version database (ba3008bb2d42c61f172b7d9592de0212edf20fc6) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-version-not-in-versions-database-feature@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/vcpkg.json: error: the "version>=" constraint to good names version 0.9 which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. -$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: note: consider removing the version constraint or choosing a value declared here -note: the dependency is in the feature named add-things -$TestingRoot/ci-verify-versions-registry/ports/good: message: good@1.0 is correctly in the version database (0f3d67db0dbb6aa5499bc09367a606b495e16d35) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: good@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/good/vcpkg.json: message: all version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/ports/has-local-edits/vcpkg.json: error: the git tree of the port directory could not be determined. This is usually caused by uncommitted changes. -note: you can commit your changes and add them to the version database by running: - git add "$TestingRoot/ci-verify-versions-registry/ports/has-local-edits" - git commit -m wip - vcpkg x-add-version has-local-edits - git add versions - git commit --amend -m "[has-local-edits] Add new port" -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: has-local-edits@1.0.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/has-local-edits/vcpkg.json: message: all version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json: error: mismatch-git-tree@1.0 git tree 41d20d2a02d75343b0933b624faf9f061b112dad does not match the port directory -$TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree: note: the port directory has git tree 34b3289caaa7a97950828905d354dc971c3c15a7 -$TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json: note: if mismatch-git-tree@1.0 is already published, update this file with a new version or port-version, commit it, then add the new version by running: - vcpkg x-add-version mismatch-git-tree - git add versions - git commit -m `"Update version database`" -note: if mismatch-git-tree@1.0 is not yet published, overwrite the previous git tree by running: - vcpkg x-add-version mismatch-git-tree --overwrite-version - git add versions - git commit -m `"Update version database`" -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: mismatch-git-tree@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json: message: all version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/ports/no-versions/vcpkg.json: error: this port is not in the version database -$TestingRoot/ci-verify-versions-registry/versions/n-/no-versions.json: note: the version database file should be here -note: run 'vcpkg x-add-version no-versions' to create the version database file -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: no-versions@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/no-versions/vcpkg.json: message: all version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/ports/override-not-in-versions-database: message: override-not-in-versions-database@1.0 is correctly in the version database (0ff80cd22d5ca881efab3329ce596566a8642bec) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: override-not-in-versions-database@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/override-not-in-versions-database/vcpkg.json: error: the version override no-versions does not exist in the version database; does that port exist? -$TestingRoot/ci-verify-versions-registry/ports/override-version-not-in-versions-database: message: override-version-not-in-versions-database@1.0 is correctly in the version database (49fafaad46408296e50e9d0fd1a3d531bf97d420) -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: override-version-not-in-versions-database@1.0 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/override-version-not-in-versions-database/vcpkg.json: error: the override of good names version 0.9 which does not exist in the version database. Installing this port at the top level will fail as that version will be unresolvable. -$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: note: consider removing the version override or choosing a value declared here -$TestingRoot/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json: error: version-mismatch@1.1 was not found in versions database -$TestingRoot/ci-verify-versions-registry/versions/v-/version-mismatch.json: note: the version should be in this file -note: run 'vcpkg x-add-version version-mismatch' to add the new port version -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-mismatch@1.1 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json: message: all version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/ports/version-missing/vcpkg.json: error: version-missing@1.1 was not found in versions database -$TestingRoot/ci-verify-versions-registry/versions/v-/version-missing.json: note: the version should be in this file -note: run 'vcpkg x-add-version version-missing' to add the new port version -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-missing@1.1 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/version-missing/vcpkg.json: message: all version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json: error: 1.1 is declared version-string, but version-scheme-mismatch is declared with version -$TestingRoot/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json: note: version-scheme-mismatch is declared here -note: versions must be unique, even if they are declared with different schemes -note: you can overwrite version-scheme-mismatch@1.1 with correct local values by running: -vcpkg x-add-version version-scheme-mismatch --overwrite-version -$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-scheme-mismatch@1.1 matches the current baseline -$TestingRoot/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json: message: all version constraints are consistent with the version database -$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: failed to execute: `"C:\Program Files\Git\cmd\git.exe`" `"--git-dir=$TestingRoot/ci-verify-versions-registry/.git`" `"--work-tree=$buildtreesRoot/versioning_/versions/bad-git-tree/000000070c5f496fcf1a97cf654d5e81f0d2685a_82336.tmp`" -c core.autocrlf=false read-tree -m -u 000000070c5f496fcf1a97cf654d5e81f0d2685a -error: git failed with exit code: (128). -fatal: failed to unpack tree object 000000070c5f496fcf1a97cf654d5e81f0d2685a -note: while checking out port bad-git-tree with git tree 000000070c5f496fcf1a97cf654d5e81f0d2685a -note: while validating version: 1.1 -$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: failed to execute: `"C:\Program Files\Git\cmd\git.exe`" `"--git-dir=$TestingRoot/ci-verify-versions-registry/.git`" `"--work-tree=$buildtreesRoot/versioning_/versions/bad-git-tree/00000005fb6b76058ce09252f521847363c6b266_82336.tmp`" -c core.autocrlf=false read-tree -m -u 00000005fb6b76058ce09252f521847363c6b266 -error: git failed with exit code: (128). -fatal: failed to unpack tree object 00000005fb6b76058ce09252f521847363c6b266 -note: while checking out port bad-git-tree with git tree 00000005fb6b76058ce09252f521847363c6b266 -note: while validating version: 1.0 -$TestingRoot/ci-verify-versions-registry/versions/b-/bad-history-name.json: message: bad-history-name@1.1 is correctly in the version database (f34f4ad3dfcc4d46d467d7b6aa04f9732a7951d6) -$TestingRoot/ci-verify-versions-registry/versions/b-/bad-history-name.json: error: db9d98300e7daeb2c0652bae94a0283a1b1a13d1 is declared to contain bad-history-name@1.0, but appears to contain bad-history-name-is-bad@1.0 -$TestingRoot/ci-verify-versions-registry/versions/b-/baseline-version-mismatch.json: message: baseline-version-mismatch@1.1 is correctly in the version database (cf8a1faa9f94f7ceb9513d65093d407e11ac1402) -$TestingRoot/ci-verify-versions-registry/versions/b-/baseline-version-mismatch.json: message: baseline-version-mismatch@1.0 is correctly in the version database (a6d7dde2f5a9ea80db16c7f73c43556a7e21e5cf) -$TestingRoot/ci-verify-versions-registry/versions/b-/baseline-version-missing.json: message: baseline-version-missing@1.0 is correctly in the version database (a5c21769008f52ed66afa344f13b786dde4b8d7d) -$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database.json: message: dependency-not-in-versions-database@1.0 is correctly in the version database (321c8b400526dc412a987285ef469eec6221a4b4) -$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database-feature.json: message: dependency-not-in-versions-database-feature@1.0 is correctly in the version database (2298ee25ea54ed92595250a2be07d01bdd76f47c) -$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database.json: message: dependency-version-not-in-versions-database@1.0 is correctly in the version database (f0d44555fe7714929e432ab9e12a436e28ffef9e) -$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database-feature.json: message: dependency-version-not-in-versions-database-feature@1.0 is correctly in the version database (ba3008bb2d42c61f172b7d9592de0212edf20fc6) -$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: message: good@1.0 is correctly in the version database (0f3d67db0dbb6aa5499bc09367a606b495e16d35) -$TestingRoot/ci-verify-versions-registry/versions/h-/has-local-edits.json: message: has-local-edits@1.0.0 is correctly in the version database (b1d7f6030942b329a200f16c931c01e2ec9e1e79) -$TestingRoot/ci-verify-versions-registry/versions/m-/malformed.json: $buildtreesRoot/versioning_/versions/malformed/a1f22424b0fb1460200c12e1b7933f309f9c8373/vcpkg.json:4:3: error: Unexpected character; expected property name - on expression: ~broken - ^ -note: while validating version: 1.1 -$TestingRoot/ci-verify-versions-registry/versions/m-/malformed.json: $buildtreesRoot/versioning_/versions/malformed/72b37802dbdc176ce20b718ce4a332ac38bd0116/vcpkg.json:4:3: error: Unexpected character; expected property name - on expression: ~broken - ^ -note: while validating version: 1.0 -$TestingRoot/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json: message: mismatch-git-tree@1.0 is correctly in the version database (41d20d2a02d75343b0933b624faf9f061b112dad) -$TestingRoot/ci-verify-versions-registry/versions/o-/override-not-in-versions-database.json: message: override-not-in-versions-database@1.0 is correctly in the version database (0ff80cd22d5ca881efab3329ce596566a8642bec) -$TestingRoot/ci-verify-versions-registry/versions/o-/override-version-not-in-versions-database.json: message: override-version-not-in-versions-database@1.0 is correctly in the version database (49fafaad46408296e50e9d0fd1a3d531bf97d420) -$TestingRoot/ci-verify-versions-registry/versions/v-/version-mismatch.json: error: 220bdcf2d4836ec9fe867eaff2945b58c08f5618 is declared to contain version-mismatch@1.1-a, but appears to contain version-mismatch@1.1 -$TestingRoot/ci-verify-versions-registry/versions/v-/version-mismatch.json: error: 5c1a69be3303fcd085d473d10e311b85202ee93c is declared to contain version-mismatch@1.0-a, but appears to contain version-mismatch@1.0 -$TestingRoot/ci-verify-versions-registry/versions/v-/version-missing.json: message: version-missing@1.0 is correctly in the version database (d3b4c8bf4bee7654f63b223a442741bb16f45957) -$TestingRoot/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json: error: 1.1 is declared version-string, but version-scheme-mismatch@ea2006a1188b81f1f2f6e0aba9bef236d1fb2725 is declared with version -$buildtreesRoot/versioning_/versions/version-scheme-mismatch/ea2006a1188b81f1f2f6e0aba9bef236d1fb2725/vcpkg.json: note: version-scheme-mismatch is declared here -note: versions must be unique, even if they are declared with different schemes -$TestingRoot/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json: error: 1.0 is declared version-string, but version-scheme-mismatch@89c88798a9fa17ea6753da87887a1fec48c421b0 is declared with version -$buildtreesRoot/versioning_/versions/version-scheme-mismatch/89c88798a9fa17ea6753da87887a1fec48c421b0/vcpkg.json: note: version-scheme-mismatch is declared here -note: versions must be unique, even if they are declared with different schemes -"@ - -$actual = Run-VcpkgAndCaptureOutput x-ci-verify-versions @directoryArgs "--x-builtin-ports-root=$TestingRoot/ci-verify-versions-registry/ports" "--x-builtin-registry-versions-dir=$TestingRoot/ci-verify-versions-registry/versions" --verbose --verify-git-trees -Throw-IfNotFailed - -function Sanitize() { - Param([string]$text) - $workTreeRegex = 'error: failed to execute:[^\r\n]+' # Git command line has an unpredictable PID inside - $text = $text.Replace('\', '/').Replace('`r`n', '`n').Trim() - $text = [System.Text.RegularExpressions.Regex]::Replace($text, $workTreeRegex, '') - return $text -} - -$expected = Sanitize $expected -$actual = Sanitize $actual -if ($actual -ne $expected) { - Set-Content -Value $expected -LiteralPath "$TestingRoot/expected.txt" - Set-Content -Value $actual -LiteralPath "$TestingRoot/actual.txt" - git diff --no-index -- "$TestingRoot/expected.txt" "$TestingRoot/actual.txt" - throw "Bad x-ci-verify-versions output." -} +. "$PSScriptRoot/../end-to-end-tests-prelude.ps1" + +Refresh-TestRoot + +Copy-Item -Recurse "$PSScriptRoot/../e2e-assets/ci-verify-versions-registry" "$TestingRoot/ci-verify-versions-registry" +git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions init +git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions add -A +git -C "$TestingRoot/ci-verify-versions-registry" @gitConfigOptions commit -m testing +Move-Item "$TestingRoot/ci-verify-versions-registry/old-port-versions/has-local-edits" "$TestingRoot/ci-verify-versions-registry/ports" + +$expected = @" +$TestingRoot/ci-verify-versions-registry/ports/malformed/vcpkg.json:4:3: error: Unexpected character; expected property name + on expression: ~broken + ^ +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: bad-git-tree@1.1 git tree 000000070c5f496fcf1a97cf654d5e81f0d2685a does not match the port directory +$TestingRoot/ci-verify-versions-registry/ports/bad-git-tree: note: the port directory has git tree 6528b2c70c5f496fcf1a97cf654d5e81f0d2685a +$TestingRoot/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json: note: if bad-git-tree@1.1 is already published, update this file with a new version or port-version, commit it, then add the new version by running: + vcpkg x-add-version bad-git-tree + git add versions + git commit -m `"Update version database`" +note: if bad-git-tree@1.1 is not yet published, overwrite the previous git tree by running: + vcpkg x-add-version bad-git-tree --overwrite-version + git add versions + git commit -m `"Update version database`" +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: bad-git-tree@1.1 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/bad-git-tree/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/bad-history-name: message: bad-history-name@1.1 is correctly in the version database (f34f4ad3dfcc4d46d467d7b6aa04f9732a7951d6) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: bad-history-name@1.1 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/bad-history-name/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch: message: baseline-version-mismatch@1.1 is correctly in the version database (cf8a1faa9f94f7ceb9513d65093d407e11ac1402) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: baseline-version-mismatch is assigned 1.0, but the local port is 1.1 +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json: note: baseline-version-mismatch is declared here +note: you can run the following commands to add the current version of baseline-version-mismatch automatically: + vcpkg x-add-version baseline-version-mismatch + git add versions + git commit -m `"Update version database`" +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-mismatch/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing: message: baseline-version-missing@1.0 is correctly in the version database (a5c21769008f52ed66afa344f13b786dde4b8d7d) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: error: baseline-version-missing is not assigned a version +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json: note: baseline-version-missing is declared here +note: you can run the following commands to add the current version of baseline-version-missing automatically: + vcpkg x-add-version baseline-version-missing + git add versions + git commit -m `"Update version database`" +$TestingRoot/ci-verify-versions-registry/ports/baseline-version-missing/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database: message: dependency-not-in-versions-database@1.0 is correctly in the version database (321c8b400526dc412a987285ef469eec6221a4b4) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-not-in-versions-database@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database/vcpkg.json: error: the dependency no-versions does not exist in the version database; does that port exist? +$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature: message: dependency-not-in-versions-database-feature@1.0 is correctly in the version database (2298ee25ea54ed92595250a2be07d01bdd76f47c) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-not-in-versions-database-feature@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/dependency-not-in-versions-database-feature/vcpkg.json: error: the dependency no-versions does not exist in the version database; does that port exist? +note: the dependency is in the feature named add-things +$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database: message: dependency-version-not-in-versions-database@1.0 is correctly in the version database (f0d44555fe7714929e432ab9e12a436e28ffef9e) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-version-not-in-versions-database@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database/vcpkg.json: error: the "version>=" constraint to good names version 0.9 which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. +$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: note: consider removing the version constraint or choosing a value declared here +$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature: message: dependency-version-not-in-versions-database-feature@1.0 is correctly in the version database (ba3008bb2d42c61f172b7d9592de0212edf20fc6) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: dependency-version-not-in-versions-database-feature@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/dependency-version-not-in-versions-database-feature/vcpkg.json: error: the "version>=" constraint to good names version 0.9 which does not exist in the version database. All versions must exist in the version database to be interpreted by vcpkg. +$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: note: consider removing the version constraint or choosing a value declared here +note: the dependency is in the feature named add-things +$TestingRoot/ci-verify-versions-registry/ports/good: message: good@1.0 is correctly in the version database (0f3d67db0dbb6aa5499bc09367a606b495e16d35) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: good@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/good/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/has-local-edits/vcpkg.json: error: the git tree of the port directory could not be determined. This is usually caused by uncommitted changes. +note: you can commit your changes and add them to the version database by running: + git add "$TestingRoot/ci-verify-versions-registry/ports/has-local-edits" + git commit -m wip + vcpkg x-add-version has-local-edits + git add versions + git commit --amend -m "[has-local-edits] Add new port" +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: has-local-edits@1.0.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/has-local-edits/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json: error: mismatch-git-tree@1.0 git tree 41d20d2a02d75343b0933b624faf9f061b112dad does not match the port directory +$TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree: note: the port directory has git tree 34b3289caaa7a97950828905d354dc971c3c15a7 +$TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json: note: if mismatch-git-tree@1.0 is already published, update this file with a new version or port-version, commit it, then add the new version by running: + vcpkg x-add-version mismatch-git-tree + git add versions + git commit -m `"Update version database`" +note: if mismatch-git-tree@1.0 is not yet published, overwrite the previous git tree by running: + vcpkg x-add-version mismatch-git-tree --overwrite-version + git add versions + git commit -m `"Update version database`" +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: mismatch-git-tree@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/mismatch-git-tree/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/no-versions/vcpkg.json: error: this port is not in the version database +$TestingRoot/ci-verify-versions-registry/versions/n-/no-versions.json: note: the version database file should be here +note: run 'vcpkg x-add-version no-versions' to create the version database file +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: no-versions@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/no-versions/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/override-not-in-versions-database: message: override-not-in-versions-database@1.0 is correctly in the version database (0ff80cd22d5ca881efab3329ce596566a8642bec) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: override-not-in-versions-database@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/override-not-in-versions-database/vcpkg.json: error: the version override no-versions does not exist in the version database; does that port exist? +$TestingRoot/ci-verify-versions-registry/ports/override-version-not-in-versions-database: message: override-version-not-in-versions-database@1.0 is correctly in the version database (49fafaad46408296e50e9d0fd1a3d531bf97d420) +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: override-version-not-in-versions-database@1.0 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/override-version-not-in-versions-database/vcpkg.json: error: the override of good names version 0.9 which does not exist in the version database. Installing this port at the top level will fail as that version will be unresolvable. +$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: note: consider removing the version override or choosing a value declared here +$TestingRoot/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json: error: version-mismatch@1.1 was not found in versions database +$TestingRoot/ci-verify-versions-registry/versions/v-/version-mismatch.json: note: the version should be in this file +note: run 'vcpkg x-add-version version-mismatch' to add the new port version +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-mismatch@1.1 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/version-mismatch/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/ports/version-missing/vcpkg.json: error: version-missing@1.1 was not found in versions database +$TestingRoot/ci-verify-versions-registry/versions/v-/version-missing.json: note: the version should be in this file +note: run 'vcpkg x-add-version version-missing' to add the new port version +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-missing@1.1 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/version-missing/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json: error: 1.1 is declared version-string, but version-scheme-mismatch is declared with version +$TestingRoot/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json: note: version-scheme-mismatch is declared here +note: versions must be unique, even if they are declared with different schemes +note: you can overwrite version-scheme-mismatch@1.1 with correct local values by running: +vcpkg x-add-version version-scheme-mismatch --overwrite-version +$TestingRoot/ci-verify-versions-registry/versions/baseline.json: message: version-scheme-mismatch@1.1 matches the current baseline +$TestingRoot/ci-verify-versions-registry/ports/version-scheme-mismatch/vcpkg.json: message: all version constraints are consistent with the version database +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: failed to execute: `"C:\Program Files\Git\cmd\git.exe`" `"--git-dir=$TestingRoot/ci-verify-versions-registry/.git`" `"--work-tree=$buildtreesRoot/versioning_/versions/bad-git-tree/000000070c5f496fcf1a97cf654d5e81f0d2685a_82336.tmp`" -c core.autocrlf=false read-tree -m -u 000000070c5f496fcf1a97cf654d5e81f0d2685a +error: git failed with exit code: (128). +fatal: failed to unpack tree object 000000070c5f496fcf1a97cf654d5e81f0d2685a +note: while checking out port bad-git-tree with git tree 000000070c5f496fcf1a97cf654d5e81f0d2685a +note: while validating version: 1.1 +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-git-tree.json: error: failed to execute: `"C:\Program Files\Git\cmd\git.exe`" `"--git-dir=$TestingRoot/ci-verify-versions-registry/.git`" `"--work-tree=$buildtreesRoot/versioning_/versions/bad-git-tree/00000005fb6b76058ce09252f521847363c6b266_82336.tmp`" -c core.autocrlf=false read-tree -m -u 00000005fb6b76058ce09252f521847363c6b266 +error: git failed with exit code: (128). +fatal: failed to unpack tree object 00000005fb6b76058ce09252f521847363c6b266 +note: while checking out port bad-git-tree with git tree 00000005fb6b76058ce09252f521847363c6b266 +note: while validating version: 1.0 +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-history-name.json: message: bad-history-name@1.1 is correctly in the version database (f34f4ad3dfcc4d46d467d7b6aa04f9732a7951d6) +$TestingRoot/ci-verify-versions-registry/versions/b-/bad-history-name.json: error: db9d98300e7daeb2c0652bae94a0283a1b1a13d1 is declared to contain bad-history-name@1.0, but appears to contain bad-history-name-is-bad@1.0 +$TestingRoot/ci-verify-versions-registry/versions/b-/baseline-version-mismatch.json: message: baseline-version-mismatch@1.1 is correctly in the version database (cf8a1faa9f94f7ceb9513d65093d407e11ac1402) +$TestingRoot/ci-verify-versions-registry/versions/b-/baseline-version-mismatch.json: message: baseline-version-mismatch@1.0 is correctly in the version database (a6d7dde2f5a9ea80db16c7f73c43556a7e21e5cf) +$TestingRoot/ci-verify-versions-registry/versions/b-/baseline-version-missing.json: message: baseline-version-missing@1.0 is correctly in the version database (a5c21769008f52ed66afa344f13b786dde4b8d7d) +$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database.json: message: dependency-not-in-versions-database@1.0 is correctly in the version database (321c8b400526dc412a987285ef469eec6221a4b4) +$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-not-in-versions-database-feature.json: message: dependency-not-in-versions-database-feature@1.0 is correctly in the version database (2298ee25ea54ed92595250a2be07d01bdd76f47c) +$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database.json: message: dependency-version-not-in-versions-database@1.0 is correctly in the version database (f0d44555fe7714929e432ab9e12a436e28ffef9e) +$TestingRoot/ci-verify-versions-registry/versions/d-/dependency-version-not-in-versions-database-feature.json: message: dependency-version-not-in-versions-database-feature@1.0 is correctly in the version database (ba3008bb2d42c61f172b7d9592de0212edf20fc6) +$TestingRoot/ci-verify-versions-registry/versions/g-/good.json: message: good@1.0 is correctly in the version database (0f3d67db0dbb6aa5499bc09367a606b495e16d35) +$TestingRoot/ci-verify-versions-registry/versions/h-/has-local-edits.json: message: has-local-edits@1.0.0 is correctly in the version database (b1d7f6030942b329a200f16c931c01e2ec9e1e79) +$TestingRoot/ci-verify-versions-registry/versions/m-/malformed.json: $buildtreesRoot/versioning_/versions/malformed/a1f22424b0fb1460200c12e1b7933f309f9c8373/vcpkg.json:4:3: error: Unexpected character; expected property name + on expression: ~broken + ^ +note: while validating version: 1.1 +$TestingRoot/ci-verify-versions-registry/versions/m-/malformed.json: $buildtreesRoot/versioning_/versions/malformed/72b37802dbdc176ce20b718ce4a332ac38bd0116/vcpkg.json:4:3: error: Unexpected character; expected property name + on expression: ~broken + ^ +note: while validating version: 1.0 +$TestingRoot/ci-verify-versions-registry/versions/m-/mismatch-git-tree.json: message: mismatch-git-tree@1.0 is correctly in the version database (41d20d2a02d75343b0933b624faf9f061b112dad) +$TestingRoot/ci-verify-versions-registry/versions/o-/override-not-in-versions-database.json: message: override-not-in-versions-database@1.0 is correctly in the version database (0ff80cd22d5ca881efab3329ce596566a8642bec) +$TestingRoot/ci-verify-versions-registry/versions/o-/override-version-not-in-versions-database.json: message: override-version-not-in-versions-database@1.0 is correctly in the version database (49fafaad46408296e50e9d0fd1a3d531bf97d420) +$TestingRoot/ci-verify-versions-registry/versions/v-/version-mismatch.json: error: 220bdcf2d4836ec9fe867eaff2945b58c08f5618 is declared to contain version-mismatch@1.1-a, but appears to contain version-mismatch@1.1 +$TestingRoot/ci-verify-versions-registry/versions/v-/version-mismatch.json: error: 5c1a69be3303fcd085d473d10e311b85202ee93c is declared to contain version-mismatch@1.0-a, but appears to contain version-mismatch@1.0 +$TestingRoot/ci-verify-versions-registry/versions/v-/version-missing.json: message: version-missing@1.0 is correctly in the version database (d3b4c8bf4bee7654f63b223a442741bb16f45957) +$TestingRoot/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json: error: 1.1 is declared version-string, but version-scheme-mismatch@ea2006a1188b81f1f2f6e0aba9bef236d1fb2725 is declared with version +$buildtreesRoot/versioning_/versions/version-scheme-mismatch/ea2006a1188b81f1f2f6e0aba9bef236d1fb2725/vcpkg.json: note: version-scheme-mismatch is declared here +note: versions must be unique, even if they are declared with different schemes +$TestingRoot/ci-verify-versions-registry/versions/v-/version-scheme-mismatch.json: error: 1.0 is declared version-string, but version-scheme-mismatch@89c88798a9fa17ea6753da87887a1fec48c421b0 is declared with version +$buildtreesRoot/versioning_/versions/version-scheme-mismatch/89c88798a9fa17ea6753da87887a1fec48c421b0/vcpkg.json: note: version-scheme-mismatch is declared here +note: versions must be unique, even if they are declared with different schemes +"@ + +$actual = Run-VcpkgAndCaptureOutput x-ci-verify-versions @directoryArgs "--x-builtin-ports-root=$TestingRoot/ci-verify-versions-registry/ports" "--x-builtin-registry-versions-dir=$TestingRoot/ci-verify-versions-registry/versions" --verbose --verify-git-trees +Throw-IfNotFailed + +function Sanitize() { + Param([string]$text) + $workTreeRegex = 'error: failed to execute:[^\r\n]+' # Git command line has an unpredictable PID inside + $text = $text.Replace('\', '/').Replace("`r`n", "`n").Trim() + $text = [System.Text.RegularExpressions.Regex]::Replace($text, $workTreeRegex, '') + return $text +} + +$expected = Sanitize $expected +$actual = Sanitize $actual +if ($actual -ne $expected) { + Set-Content -Value $expected -LiteralPath "$TestingRoot/expected.txt" + Set-Content -Value $actual -LiteralPath "$TestingRoot/actual.txt" + git diff --no-index -- "$TestingRoot/expected.txt" "$TestingRoot/actual.txt" + throw "Bad x-ci-verify-versions output." +} From 903cb748cd0d7527327748fdd2847a4a0d9968b3 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 17 Oct 2023 21:17:59 -0700 Subject: [PATCH 40/48] Ensure spdx_location is not dropped when loading ports. 1. Change try_load_port and friends to accept the spdx location and return SourceControlFileAndLocation rather than requiring all callers to staple that on. 2. PathAndLocation => PortLocation 3. Fix confusion in SourceControlFileAndLocation due to some parts of the codebase using source_location as the port_directory. 4. Rename all "registry_location"s to "spdx_location" to avoid it sounding like this is the spdx location of the registry. 5. Require origin to be provided in all the places. --- include/vcpkg/fwd/sourceparagraph.h | 7 ++ include/vcpkg/paragraphs.h | 34 +++--- include/vcpkg/registries.h | 13 +-- include/vcpkg/sourceparagraph.h | 17 ++- src/vcpkg-test/spdx.cpp | 2 +- src/vcpkg-test/versionplan.cpp | 7 +- src/vcpkg/cmakevars.cpp | 2 +- src/vcpkg/commands.add-version.cpp | 26 ++--- src/vcpkg/commands.autocomplete.cpp | 2 +- src/vcpkg/commands.build.cpp | 14 +-- src/vcpkg/commands.ci-verify-versions.cpp | 26 ++--- src/vcpkg/dependencies.cpp | 4 +- src/vcpkg/paragraphs.cpp | 121 +++++++++++++--------- src/vcpkg/portfileprovider.cpp | 79 +++++++------- src/vcpkg/registries.cpp | 53 +++++----- src/vcpkg/spdx.cpp | 2 +- 16 files changed, 215 insertions(+), 194 deletions(-) diff --git a/include/vcpkg/fwd/sourceparagraph.h b/include/vcpkg/fwd/sourceparagraph.h index 78fe57cdc5..7388ee570a 100644 --- a/include/vcpkg/fwd/sourceparagraph.h +++ b/include/vcpkg/fwd/sourceparagraph.h @@ -3,6 +3,13 @@ namespace vcpkg { struct ManifestAndPath; + struct DependencyConstraint; + struct DependencyRequestedFeature; + struct Dependency; + struct DependencyOverride; + struct FeatureParagraph; + struct SourceParagraph; + struct PortLocation; struct SourceControlFile; struct SourceControlFileAndLocation; } \ No newline at end of file diff --git a/include/vcpkg/paragraphs.h b/include/vcpkg/paragraphs.h index c1f7e69d22..21a614b79c 100644 --- a/include/vcpkg/paragraphs.h +++ b/include/vcpkg/paragraphs.h @@ -27,22 +27,26 @@ namespace vcpkg::Paragraphs bool is_port_directory(const ReadOnlyFilesystem& fs, const Path& maybe_directory); // If an error occurs, the Expected will be in the error state. - // Otherwise, if the port is known, the unique_ptr contains the loaded port information. - // Otherwise, the unique_ptr is nullptr. - ExpectedL> try_load_port(const ReadOnlyFilesystem& fs, - StringView port_name, - const Path& port_directory); + // Otherwise, if the port is known, result->source_control_file contains the loaded port information. + // Otherwise, result->source_control_file is nullptr. + ExpectedL try_load_port(const ReadOnlyFilesystem& fs, + StringView port_name, + const PortLocation& port_location); // Identical to try_load_port, but the port unknown condition is mapped to an error. - ExpectedL> try_load_port_required(const ReadOnlyFilesystem& fs, - StringView port_name, - const Path& port_directory); - ExpectedL> try_load_project_manifest_text(StringView text, - StringView origin, - MessageSink& warning_sink); - ExpectedL> try_load_port_manifest_text(StringView text, - StringView origin, - MessageSink& warning_sink); - ExpectedL> try_load_control_file_text(StringView text, StringView origin); + ExpectedL try_load_port_required(const ReadOnlyFilesystem& fs, + StringView port_name, + const PortLocation& port_location); + ExpectedL try_load_project_manifest_text(StringView text, + StringView origin, + StringView spdx_location, + MessageSink& warning_sink); + ExpectedL try_load_port_manifest_text(StringView text, + StringView origin, + StringView spdx_location, + MessageSink& warning_sink); + ExpectedL try_load_control_file_text(StringView text, + StringView origin, + StringView spdx_location); ExpectedL try_load_cached_package(const ReadOnlyFilesystem& fs, const Path& package_dir, diff --git a/include/vcpkg/registries.h b/include/vcpkg/registries.h index 00c4996d90..4cd9924192 100644 --- a/include/vcpkg/registries.h +++ b/include/vcpkg/registries.h @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -18,7 +19,6 @@ #include #include #include -#include #include namespace vcpkg @@ -54,20 +54,11 @@ namespace vcpkg bool modified = false; }; - struct PathAndLocation - { - Path path; - - /// Should model SPDX PackageDownloadLocation. Empty implies NOASSERTION. - /// See https://spdx.github.io/spdx-spec/package-information/#77-package-download-location-field - std::string location; - }; - struct RegistryEntry { virtual ExpectedL> get_port_versions() const = 0; - virtual ExpectedL get_version(const Version& version) const = 0; + virtual ExpectedL get_version(const Version& version) const = 0; virtual ~RegistryEntry() = default; }; diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index 0bd760cc1f..f7000c4166 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -143,6 +143,15 @@ namespace vcpkg friend bool operator!=(const SourceParagraph& lhs, const SourceParagraph& rhs) { return !(lhs == rhs); } }; + struct PortLocation + { + Path port_directory; + + /// Should model SPDX PackageDownloadLocation. Empty implies NOASSERTION. + /// See https://spdx.github.io/spdx-spec/package-information/#77-package-download-location-field + std::string spdx_location; + }; + /// /// Full metadata of a package: core and other features. /// @@ -198,12 +207,14 @@ namespace vcpkg Version to_version() const { return source_control_file->to_version(); } VersionScheme scheme() const { return source_control_file->core_paragraph->version_scheme; } SchemedVersion schemed_version() const { return {scheme(), to_version()}; } + Path port_directory() const { return control_location.parent_path(); } std::unique_ptr source_control_file; - Path source_location; + Path control_location; + /// Should model SPDX PackageDownloadLocation. Empty implies NOASSERTION. /// See https://spdx.github.io/spdx-spec/package-information/#77-package-download-location-field - std::string registry_location; + std::string spdx_location; }; void print_error_message(const LocalizedString& message); @@ -213,6 +224,6 @@ namespace vcpkg // Exposed for testing ExpectedL> parse_dependencies_list(const std::string& str, - StringView origin = "", + StringView origin, TextRowCol textrowcol = {}); } diff --git a/src/vcpkg-test/spdx.cpp b/src/vcpkg-test/spdx.cpp index 937dcda4a8..8b414894e8 100644 --- a/src/vcpkg-test/spdx.cpp +++ b/src/vcpkg-test/spdx.cpp @@ -9,7 +9,7 @@ TEST_CASE ("spdx maximum serialization", "[spdx]") { PackageSpec spec{"zlib", Test::ARM_UWP}; SourceControlFileAndLocation scfl; - scfl.registry_location = "git://some-vcs-url"; + scfl.spdx_location = "git://some-vcs-url"; auto& scf = *(scfl.source_control_file = std::make_unique()); auto& cpgh = *(scf.core_paragraph = std::make_unique()); cpgh.name = "zlib"; diff --git a/src/vcpkg-test/versionplan.cpp b/src/vcpkg-test/versionplan.cpp index a7d2d5fcaf..b237e4d38a 100644 --- a/src/vcpkg-test/versionplan.cpp +++ b/src/vcpkg-test/versionplan.cpp @@ -12,7 +12,7 @@ using namespace vcpkg; TEST_CASE ("parse depends", "[dependencies]") { - auto w = parse_dependencies_list("liba (windows)"); + auto w = parse_dependencies_list("liba (windows)", ""); REQUIRE(w); auto& v = *w.get(); REQUIRE(v.size() == 1); @@ -31,7 +31,7 @@ TEST_CASE ("filter depends", "[dependencies]") const std::unordered_map arm_uwp_cmake_vars{{"VCPKG_TARGET_ARCHITECTURE", "arm"}, {"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}; - auto deps_ = parse_dependencies_list("liba (!uwp), libb, libc (uwp)"); + auto deps_ = parse_dependencies_list("liba (!uwp), libb, libc (uwp)", ""); REQUIRE(deps_); auto& deps = *deps_.get(); SECTION ("x64-windows") @@ -58,7 +58,8 @@ TEST_CASE ("filter depends", "[dependencies]") TEST_CASE ("parse feature depends", "[dependencies]") { auto u_ = parse_dependencies_list("libwebp[anim, gif2webp, img2webp, info, mux, nearlossless, " - "simd, cwebp, dwebp], libwebp[vwebp-sdl, extras] (!osx)"); + "simd, cwebp, dwebp], libwebp[vwebp-sdl, extras] (!osx)", + ""); REQUIRE(u_); auto& v = *u_.get(); REQUIRE(v.size() == 2); diff --git a/src/vcpkg/cmakevars.cpp b/src/vcpkg/cmakevars.cpp index 5d1c199b5e..cb9250e31a 100644 --- a/src/vcpkg/cmakevars.cpp +++ b/src/vcpkg/cmakevars.cpp @@ -367,7 +367,7 @@ endfunction() for (const auto& install_action : action_plan.install_actions) { auto& scfl = install_action.source_control_file_and_location.value_or_exit(VCPKG_LINE_INFO); - const auto override_path = scfl.source_location / "vcpkg-abi-settings.cmake"; + const auto override_path = scfl.port_directory() / "vcpkg-abi-settings.cmake"; spec_abi_settings.emplace_back(FullPackageSpec{install_action.spec, install_action.feature_list}, override_path.generic_u8string()); } diff --git a/src/vcpkg/commands.add-version.cpp b/src/vcpkg/commands.add-version.cpp index 4e5af3c8db..819245448e 100644 --- a/src/vcpkg/commands.add-version.cpp +++ b/src/vcpkg/commands.add-version.cpp @@ -388,7 +388,7 @@ namespace vcpkg auto maybe_git_tree_map = paths.git_get_local_port_treeish_map(); auto& git_tree_map = maybe_git_tree_map.value_or_exit(VCPKG_LINE_INFO); - // Find ports with uncommited changes + // Find ports with uncommitted changes std::set changed_ports; auto git_config = paths.git_builtin_config(); auto maybe_changes = git_ports_with_uncommitted_changes(git_config); @@ -405,15 +405,8 @@ namespace vcpkg { auto port_dir = paths.builtin_ports_directory() / port_name; - if (!fs.exists(port_dir, IgnoreErrors{})) - { - msg::println_error(msgPortDoesNotExist, msg::package_name = port_name); - Checks::check_exit(VCPKG_LINE_INFO, !add_all); - continue; - } - - auto maybe_scf = - Paragraphs::try_load_port_required(fs, port_name, paths.builtin_ports_directory() / port_name); + auto maybe_scf = Paragraphs::try_load_port_required( + fs, port_name, PortLocation{paths.builtin_ports_directory() / port_name}); auto scf = maybe_scf.get(); if (!scf) { @@ -426,15 +419,15 @@ namespace vcpkg if (!skip_formatting_check) { // check if manifest file is property formatted - const auto path_to_manifest = paths.builtin_ports_directory() / port_name / "vcpkg.json"; - if (fs.exists(path_to_manifest, IgnoreErrors{})) + + if (scf->control_location.filename() == "vcpkg.json") { - const auto current_file_content = fs.read_contents(path_to_manifest, VCPKG_LINE_INFO); - const auto json = serialize_manifest(**scf); + const auto current_file_content = fs.read_contents(scf->control_location, VCPKG_LINE_INFO); + const auto json = serialize_manifest(*scf->source_control_file); const auto formatted_content = Json::stringify(json); if (current_file_content != formatted_content) { - auto command_line = fmt::format("vcpkg format-manifest ports/{}/vcpkg.json", port_name); + auto command_line = fmt::format("vcpkg format-manifest {}", scf->control_location); msg::println_error( msg::format(msgAddVersionPortHasImproperFormat, msg::package_name = port_name) .append_raw('\n') @@ -454,8 +447,7 @@ namespace vcpkg msg::println_warning(msgAddVersionUncommittedChanges, msg::package_name = port_name); } - const auto& schemed_version = (*scf)->to_schemed_version(); - + auto schemed_version = scf->source_control_file->to_schemed_version(); auto git_tree_it = git_tree_map.find(port_name); if (git_tree_it == git_tree_map.end()) { diff --git a/src/vcpkg/commands.autocomplete.cpp b/src/vcpkg/commands.autocomplete.cpp index d43c755a25..07bd19805e 100644 --- a/src/vcpkg/commands.autocomplete.cpp +++ b/src/vcpkg/commands.autocomplete.cpp @@ -105,7 +105,7 @@ namespace vcpkg StringView triplet_prefix{colon + 1, last_arg.end()}; // TODO: Support autocomplete for ports in --overlay-ports auto maybe_port = Paragraphs::try_load_port_required( - paths.get_filesystem(), port_name, paths.builtin_ports_directory() / port_name); + paths.get_filesystem(), port_name, PortLocation{paths.builtin_ports_directory() / port_name}); if (!maybe_port) { Checks::exit_success(VCPKG_LINE_INFO); diff --git a/src/vcpkg/commands.build.cpp b/src/vcpkg/commands.build.cpp index 27e7f6b216..0c4d91d073 100644 --- a/src/vcpkg/commands.build.cpp +++ b/src/vcpkg/commands.build.cpp @@ -760,7 +760,7 @@ namespace vcpkg std::vector variables{ {"ALL_FEATURES", all_features}, - {"CURRENT_PORT_DIR", scfl.source_location}, + {"CURRENT_PORT_DIR", scfl.port_directory()}, {"_HOST_TRIPLET", action.host_triplet.canonical_name()}, {"FEATURES", Strings::join(";", action.feature_list)}, {"PORT", scf.core_paragraph->name}, @@ -951,9 +951,9 @@ namespace vcpkg msg::println(msgLoadingOverlayTriplet, msg::path = triplet_file_path); } - if (!Strings::starts_with(scfl.source_location, paths.builtin_ports_directory())) + if (!Strings::starts_with(scfl.control_location, paths.builtin_ports_directory())) { - msg::println(msgInstallingFromLocation, msg::path = scfl.source_location); + msg::println(msgInstallingFromLocation, msg::path = scfl.control_location); } const ElapsedTimer timer; @@ -1030,7 +1030,7 @@ namespace vcpkg FileSink file_sink{fs, stdoutlog, Append::YES}; CombiningSink combo_sink{stdout_sink, file_sink}; error_count = perform_post_build_lint_checks( - action.spec, paths, pre_build_info, build_info, scfl.source_location, combo_sink); + action.spec, paths, pre_build_info, build_info, scfl.port_directory(), combo_sink); }; if (error_count != 0 && action.build_options.backcompat_features == BackcompatFeatures::PROHIBIT) { @@ -1174,7 +1174,8 @@ namespace vcpkg constexpr int max_port_file_count = 100; std::string portfile_cmake_contents; - auto&& port_dir = action.source_control_file_and_location.value_or_exit(VCPKG_LINE_INFO).source_location; + auto&& scfl = action.source_control_file_and_location.value_or_exit(VCPKG_LINE_INFO); + auto port_dir = scfl.port_directory(); auto raw_files = fs.get_regular_files_recursive_lexically_proximate(port_dir, VCPKG_LINE_INFO); if (raw_files.size() > max_port_file_count) { @@ -1273,8 +1274,7 @@ namespace vcpkg abi_file_path /= triplet_canonical_name + ".vcpkg_abi_info.txt"; fs.write_contents(abi_file_path, full_abi_info, VCPKG_LINE_INFO); - auto& scf = action.source_control_file_and_location.value_or_exit(VCPKG_LINE_INFO).source_control_file; - + auto& scf = scfl.source_control_file; abi_info.package_abi = Hash::get_string_sha256(full_abi_info); abi_info.abi_tag_file.emplace(std::move(abi_file_path)); abi_info.relative_port_files = std::move(files); diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index acdbb0f9a4..60891ffa33 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -70,11 +70,12 @@ namespace if (!maybe_file) continue; const auto& file = maybe_file.value_or_exit(VCPKG_LINE_INFO); - auto maybe_scf = control_file == "vcpkg.json" - ? Paragraphs::try_load_port_manifest_text(file, treeish, stdout_sink) - : Paragraphs::try_load_control_file_text(file, treeish); - auto scf = maybe_scf.get(); - if (!scf) + auto maybe_scfl = + control_file == "vcpkg.json" + ? Paragraphs::try_load_port_manifest_text(file, treeish, StringView{}, stdout_sink) + : Paragraphs::try_load_control_file_text(file, treeish, StringView{}); + auto scfl = maybe_scfl.get(); + if (!scfl) { return {msg::format_error(msgWhileParsingVersionsForPort, msg::package_name = port_name, @@ -84,11 +85,11 @@ namespace .append_raw('\n') .append(msgWhileLoadingPortFromGitTree, msg::commit_sha = treeish) .append_raw('\n') - .append(maybe_scf.error()), + .append(maybe_scfl.error()), expected_right_tag}; } - auto&& git_tree_version = (*scf)->to_schemed_version(); + auto&& git_tree_version = scfl->source_control_file->to_schemed_version(); if (version_entry.version.version != git_tree_version.version) { return { @@ -123,17 +124,18 @@ namespace } } - auto maybe_scf = Paragraphs::try_load_port_required(paths.get_filesystem(), port_name, port_path); - auto scf = maybe_scf.get(); - if (!scf) + auto maybe_scfl = + Paragraphs::try_load_port_required(paths.get_filesystem(), port_name, PortLocation{port_path}); + auto scfl = maybe_scfl.get(); + if (!scfl) { return {msg::format_error(msgWhileLoadingLocalPort, msg::package_name = port_name) .append_raw('\n') - .append(maybe_scf.error()), + .append(maybe_scfl.error()), expected_right_tag}; } - const auto local_port_version = (*scf)->to_schemed_version(); + const auto local_port_version = scfl->source_control_file->to_schemed_version(); auto versions_end = versions->end(); auto it = std::find_if(versions->begin(), versions_end, [&](const GitVersionDbEntry& entry) { diff --git a/src/vcpkg/dependencies.cpp b/src/vcpkg/dependencies.cpp index fa7fccd69c..4f640316f3 100644 --- a/src/vcpkg/dependencies.cpp +++ b/src/vcpkg/dependencies.cpp @@ -445,9 +445,9 @@ namespace vcpkg if (auto scfl = action.source_control_file_and_location.get()) { if (!builtin_ports_dir.empty() && - !Strings::case_insensitive_ascii_starts_with(scfl->source_location, builtin_ports_dir)) + !Strings::case_insensitive_ascii_starts_with(scfl->control_location, builtin_ports_dir)) { - out.append_raw(" -- ").append_raw(scfl->source_location); + out.append_raw(" -- ").append_raw(scfl->control_location); } } } diff --git a/src/vcpkg/paragraphs.cpp b/src/vcpkg/paragraphs.cpp index acb836c2c1..f03a57e3dc 100644 --- a/src/vcpkg/paragraphs.cpp +++ b/src/vcpkg/paragraphs.cpp @@ -385,61 +385,85 @@ namespace vcpkg::Paragraphs namespace { - ExpectedL> try_load_any_manifest_text( + ExpectedL try_load_any_manifest_text( StringView text, StringView origin, + StringView spdx_location, MessageSink& warning_sink, ParseExpected (*do_parse)(StringView, const Json::Object&, MessageSink&)) { StatsTimer timer(g_load_ports_stats); - return Json::parse_object(text, origin).then([&](Json::Object&& object) { - return do_parse(origin, std::move(object), warning_sink).map_error(ToLocalizedString); - }); + return Json::parse_object(text, origin) + .then([&](Json::Object&& object) -> ExpectedL { + auto maybe_parsed = do_parse(origin, std::move(object), warning_sink); + if (auto parsed = maybe_parsed.get()) + { + return SourceControlFileAndLocation{ + std::move(*parsed), origin.to_string(), spdx_location.to_string()}; + } + + return ToLocalizedString(std::move(maybe_parsed).error()); + }); } } namespace vcpkg::Paragraphs { - ExpectedL> try_load_project_manifest_text(StringView text, - StringView origin, - MessageSink& warning_sink) + ExpectedL try_load_project_manifest_text(StringView text, + StringView origin, + StringView spdx_location, + MessageSink& warning_sink) { - return try_load_any_manifest_text(text, origin, warning_sink, SourceControlFile::parse_project_manifest_object); + return try_load_any_manifest_text( + text, origin, spdx_location, warning_sink, SourceControlFile::parse_project_manifest_object); } - ExpectedL> try_load_port_manifest_text(StringView text, - StringView origin, - MessageSink& warning_sink) + ExpectedL try_load_port_manifest_text(StringView text, + StringView origin, + StringView spdx_location, + MessageSink& warning_sink) { - return try_load_any_manifest_text(text, origin, warning_sink, SourceControlFile::parse_port_manifest_object); + return try_load_any_manifest_text( + text, origin, spdx_location, warning_sink, SourceControlFile::parse_port_manifest_object); } - ExpectedL> try_load_control_file_text(StringView text, StringView origin) + ExpectedL try_load_control_file_text(StringView text, + StringView origin, + StringView spdx_location) { StatsTimer timer(g_load_ports_stats); - return parse_paragraphs(text, origin).then([&](std::vector&& vector_pghs) { - return SourceControlFile::parse_control_file(origin, std::move(vector_pghs)).map_error(ToLocalizedString); - }); + return parse_paragraphs(text, origin) + .then([&](std::vector&& vector_pghs) -> ExpectedL { + auto maybe_parsed = SourceControlFile::parse_control_file(origin, std::move(vector_pghs)); + if (auto parsed = maybe_parsed.get()) + { + return SourceControlFileAndLocation{ + std::move(*parsed), origin.to_string(), spdx_location.to_string()}; + } + + return ToLocalizedString(std::move(maybe_parsed).error()); + }); } - ExpectedL> try_load_port(const ReadOnlyFilesystem& fs, - StringView port_name, - const Path& port_directory) + ExpectedL try_load_port(const ReadOnlyFilesystem& fs, + StringView port_name, + const PortLocation& port_location) { StatsTimer timer(g_load_ports_stats); - const auto manifest_path = port_directory / "vcpkg.json"; - const auto control_path = port_directory / "CONTROL"; + const auto manifest_path = port_location.port_directory / "vcpkg.json"; + const auto control_path = port_location.port_directory / "CONTROL"; std::error_code ec; auto manifest_contents = fs.read_contents(manifest_path, ec); if (!ec) { if (fs.exists(control_path, IgnoreErrors{})) { - return msg::format_error(msgManifestConflict, msg::path = port_directory); + return msg::format_error(msgManifestConflict, msg::path = port_location.port_directory); } - return try_load_port_manifest_text(manifest_contents, manifest_path, stdout_sink); + return try_load_port_manifest_text( + manifest_contents, manifest_path, port_location.spdx_location, stdout_sink); } auto manifest_exists = ec != std::errc::no_such_file_or_directory; @@ -453,43 +477,46 @@ namespace vcpkg::Paragraphs auto control_contents = fs.read_contents(control_path, ec); if (!ec) { - return try_load_control_file_text(control_contents, control_path); + return try_load_control_file_text(control_contents, control_path, port_location.spdx_location); } if (ec != std::errc::no_such_file_or_directory) { - return LocalizedString::from_raw(port_directory) + return LocalizedString::from_raw(port_location.port_directory) .append_raw(": ") .append(format_filesystem_call_error(ec, "read_contents", {control_path})); } - if (fs.exists(port_directory, IgnoreErrors{})) + if (fs.exists(port_location.port_directory, IgnoreErrors{})) { - return LocalizedString::from_raw(port_directory) + return LocalizedString::from_raw(port_location.port_directory) .append_raw(": ") .append(msgErrorMessage) .append(msgPortMissingManifest2, msg::package_name = port_name); } - return LocalizedString::from_raw(port_directory) + return LocalizedString::from_raw(port_location.port_directory) .append_raw(": ") .append(msgErrorMessage) .append(msgPortDoesNotExist, msg::package_name = port_name); } - ExpectedL> try_load_port_required(const ReadOnlyFilesystem& fs, - StringView port_name, - const Path& port_directory) + ExpectedL try_load_port_required(const ReadOnlyFilesystem& fs, + StringView port_name, + const PortLocation& port_location) { - return try_load_port(fs, port_name, port_directory) - .then([&](std::unique_ptr&& loaded) -> ExpectedL> { - if (!loaded) - { - return msg::format_error(msgPortDoesNotExist, msg::package_name = port_name); - } + auto load_result = try_load_port(fs, port_name, port_location); + auto maybe_res = load_result.get(); + if (maybe_res) + { + auto res = maybe_res->source_control_file.get(); + if (!res) + { + load_result = msg::format_error(msgPortDoesNotExist, msg::package_name = port_name); + } + } - return std::move(loaded); - }); + return load_result; } ExpectedL try_load_cached_package(const ReadOnlyFilesystem& fs, @@ -549,20 +576,16 @@ namespace vcpkg::Paragraphs auto maybe_port_location = (*port_entry)->get_version(*baseline_version); const auto port_location = maybe_port_location.get(); if (!port_location) continue; // baseline version was not in version db (registry consistency issue) - auto maybe_spgh = try_load_port_required(fs, port_name, port_location->path); - if (const auto spgh = maybe_spgh.get()) + auto maybe_scfl = try_load_port_required(fs, port_name, *port_location); + if (const auto scfl = maybe_scfl.get()) { - ret.paragraphs.push_back({ - std::move(*spgh), - std::move(port_location->path), - std::move(port_location->location), - }); + ret.paragraphs.push_back(std::move(*scfl)); } else { ret.errors.emplace_back(std::piecewise_construct, std::forward_as_tuple(port_name.data(), port_name.size()), - std::forward_as_tuple(std::move(maybe_spgh).error())); + std::forward_as_tuple(std::move(maybe_scfl).error())); } } @@ -615,10 +638,10 @@ namespace vcpkg::Paragraphs for (auto&& path : port_dirs) { auto port_name = path.filename(); - auto maybe_spgh = try_load_port_required(fs, port_name, path); + auto maybe_spgh = try_load_port_required(fs, port_name, PortLocation{path}); if (const auto spgh = maybe_spgh.get()) { - ret.paragraphs.push_back({std::move(*spgh), std::move(path)}); + ret.paragraphs.push_back(std::move(*spgh)); } else { diff --git a/src/vcpkg/portfileprovider.cpp b/src/vcpkg/portfileprovider.cpp index 472037ed91..6b427f89ba 100644 --- a/src/vcpkg/portfileprovider.cpp +++ b/src/vcpkg/portfileprovider.cpp @@ -22,11 +22,11 @@ namespace OverlayRegistryEntry(Path&& p, Version&& v) : root(p), version(v) { } ExpectedL> get_port_versions() const override { return View{&version, 1}; } - ExpectedL get_version(const Version& v) const override + ExpectedL get_version(const Version& v) const override { if (v == version) { - return PathAndLocation{root, ""}; + return PortLocation{root}; } return msg::format(msgVersionNotFound, msg::expected = v, msg::actual = version); } @@ -179,8 +179,7 @@ namespace vcpkg .value_or_exit(VCPKG_LINE_INFO); } - ExpectedL> load_control_file( - const VersionSpec& version_spec) const + ExpectedL load_control_file(const VersionSpec& version_spec) const { const auto& maybe_ent = entry(version_spec.port_name); if (auto ent = maybe_ent.get()) @@ -188,24 +187,19 @@ namespace vcpkg auto maybe_path = ent->get()->get_version(version_spec.version); if (auto path = maybe_path.get()) { - auto maybe_control_file = - Paragraphs::try_load_port_required(m_fs, version_spec.port_name, path->path); - if (auto scf = maybe_control_file.get()) + auto maybe_scfl = Paragraphs::try_load_port_required(m_fs, version_spec.port_name, *path); + if (auto scfl = maybe_scfl.get()) { - auto scf_vspec = scf->get()->to_version_spec(); + auto scf_vspec = scfl->source_control_file.get()->to_version_spec(); if (scf_vspec == version_spec) { - return std::make_unique(SourceControlFileAndLocation{ - std::move(*scf), - std::move(path->path), - std::move(path->location), - }); + return std::move(*scfl); } else { return msg::format(msgErrorMessage) .append(msgVersionSpecMismatch, - msg::path = path->path, + msg::path = path->port_directory, msg::expected_version = version_spec, msg::actual_version = scf_vspec); } @@ -213,11 +207,11 @@ namespace vcpkg else { // This should change to a soft error when ParseExpected is eliminated. - print_error_message(maybe_control_file.error()); + print_error_message(maybe_scfl.error()); Checks::msg_exit_maybe_upgrade(VCPKG_LINE_INFO, msgFailedToLoadPort, msg::package_name = version_spec.port_name, - msg::path = path->path); + msg::path = path->port_directory); } } else @@ -238,7 +232,9 @@ namespace vcpkg { it = m_control_cache.emplace(version_spec, load_control_file(version_spec)).first; } - return it->second.map([](const auto& x) -> const SourceControlFileAndLocation& { return *x.get(); }); + + return it->second.map( + [](const SourceControlFileAndLocation& x) -> const SourceControlFileAndLocation& { return x; }); } virtual void load_all_control_files( @@ -249,20 +245,16 @@ namespace vcpkg { auto port_name = scfl.source_control_file->core_paragraph->name; auto version = scfl.source_control_file->core_paragraph->to_version(); - auto it = m_control_cache - .emplace(VersionSpec{port_name, version}, - std::make_unique(std::move(scfl))) - .first; - out.emplace(it->first.port_name, it->second.value_or_exit(VCPKG_LINE_INFO).get()); + auto it = m_control_cache.emplace(VersionSpec{port_name, version}, std::move(scfl)).first; + out.emplace(it->first.port_name, &it->second.value_or_exit(VCPKG_LINE_INFO)); } } private: const ReadOnlyFilesystem& m_fs; const RegistrySet& m_registry_set; - mutable std:: - unordered_map>, VersionSpecHasher> - m_control_cache; + mutable std::unordered_map, VersionSpecHasher> + m_control_cache; mutable std::map>, std::less<>> m_entry_cache; }; @@ -296,18 +288,17 @@ namespace vcpkg // Try loading individual port if (Paragraphs::is_port_directory(m_fs, ports_dir)) { - auto maybe_scf = Paragraphs::try_load_port_required(m_fs, port_name, ports_dir); - if (auto scfp = maybe_scf.get()) + auto maybe_scfl = Paragraphs::try_load_port_required(m_fs, port_name, PortLocation{ports_dir}); + if (auto scfl = maybe_scfl.get()) { - auto& scf = *scfp; - if (scf->core_paragraph->name == port_name) + if (scfl->source_control_file->core_paragraph->name == port_name) { - return SourceControlFileAndLocation{std::move(scf), ports_dir}; + return std::move(*scfl); } } else { - print_error_message(maybe_scf.error()); + print_error_message(maybe_scfl.error()); Checks::msg_exit_maybe_upgrade(VCPKG_LINE_INFO, msgFailedToLoadPort, msg::package_name = port_name, @@ -320,13 +311,12 @@ namespace vcpkg auto ports_spec = ports_dir / port_name; if (Paragraphs::is_port_directory(m_fs, ports_spec)) { - auto found_scf = Paragraphs::try_load_port_required(m_fs, port_name, ports_spec); - if (auto scfp = found_scf.get()) + auto found_scfl = Paragraphs::try_load_port_required(m_fs, port_name, PortLocation{ports_spec}); + if (auto scfl = found_scfl.get()) { - auto& scf = *scfp; - if (scf->core_paragraph->name == port_name) + if (scfl->source_control_file->core_paragraph->name == port_name) { - return SourceControlFileAndLocation{std::move(scf), std::move(ports_spec)}; + return std::move(*scfl); } Checks::msg_exit_maybe_upgrade( @@ -335,11 +325,11 @@ namespace vcpkg .append_raw('\n') .append(msgMismatchedNames, msg::package_name = port_name, - msg::actual = scf->core_paragraph->name)); + msg::actual = scfl->source_control_file->core_paragraph->name)); } else { - print_error_message(found_scf.error()); + print_error_message(found_scfl.error()); Checks::msg_exit_maybe_upgrade(VCPKG_LINE_INFO, msgFailedToLoadPort, msg::package_name = port_name, @@ -371,18 +361,19 @@ namespace vcpkg // Try loading individual port if (Paragraphs::is_port_directory(m_fs, ports_dir)) { - auto maybe_scf = Paragraphs::try_load_port_required(m_fs, ports_dir.filename(), ports_dir); - if (auto scfp = maybe_scf.get()) + auto maybe_scfl = + Paragraphs::try_load_port_required(m_fs, ports_dir.filename(), PortLocation{ports_dir}); + if (auto scfl = maybe_scfl.get()) { - SourceControlFileAndLocation scfl{std::move(*scfp), ports_dir}; - auto name = scfl.source_control_file->core_paragraph->name; - auto it = m_overlay_cache.emplace(std::move(name), std::move(scfl)).first; + // copy name before moving *scfl + auto name = scfl->source_control_file->core_paragraph->name; + auto it = m_overlay_cache.emplace(std::move(name), std::move(*scfl)).first; Checks::check_exit(VCPKG_LINE_INFO, it->second.get()); out.emplace(it->first, it->second.get()); } else { - print_error_message(maybe_scf.error()); + print_error_message(maybe_scfl.error()); Checks::msg_exit_maybe_upgrade( VCPKG_LINE_INFO, msgFailedToLoadUnnamedPortFromPath, msg::path = ports_dir); } diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index 26f464e16c..22b62f065c 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -251,7 +251,7 @@ namespace std::vector&& version_entries); ExpectedL> get_port_versions() const override; - ExpectedL get_version(const Version& version) const override; + ExpectedL get_version(const Version& version) const override; private: ExpectedL ensure_not_stale() const; @@ -412,11 +412,11 @@ namespace } ExpectedL> get_port_versions() const override { return View{&version, 1}; } - ExpectedL get_version(const Version& v) const override + ExpectedL get_version(const Version& v) const override { if (v == version) { - return PathAndLocation{root, "git+https://github.com/Microsoft/vcpkg#ports/" + name}; + return PortLocation{root, "git+https://github.com/Microsoft/vcpkg#ports/" + name}; } return msg::format_error(msgVersionBuiltinPortTreeEntryMissing, @@ -438,7 +438,7 @@ namespace { return View{port_versions_soa.port_versions()}; } - ExpectedL get_version(const Version& version) const override; + ExpectedL get_version(const Version& version) const override; const VcpkgPaths& m_paths; @@ -453,7 +453,7 @@ namespace ExpectedL> get_port_versions() const override { return View{port_versions}; } - ExpectedL get_version(const Version& version) const override; + ExpectedL get_version(const Version& version) const override; std::string port_name; // these two map port versions to paths @@ -488,14 +488,15 @@ namespace DelayedInit m_baseline; private: - const ExpectedL>& get_scf(StringView port_name, const Path& path) const + const ExpectedL& get_scfl(StringView port_name, const Path& path) const { - return m_scfs.get_lazy(path, [&, this]() { return Paragraphs::try_load_port(m_fs, port_name, path); }); + return m_scfls.get_lazy( + path, [&, this]() { return Paragraphs::try_load_port(m_fs, port_name, PortLocation{path}); }); } const ReadOnlyFilesystem& m_fs; const Path m_builtin_ports_directory; - Cache>> m_scfs; + Cache> m_scfls; }; constexpr StringLiteral BuiltinFilesRegistry::s_kind; @@ -711,14 +712,14 @@ namespace ExpectedL> BuiltinFilesRegistry::get_port_entry(StringView port_name) const { auto port_directory = m_builtin_ports_directory / port_name; - const auto& maybe_maybe_scf = get_scf(port_name, port_directory); - const auto maybe_scf = maybe_maybe_scf.get(); - if (!maybe_scf) + const auto& maybe_maybe_scfl = get_scfl(port_name, port_directory); + const auto maybe_scfl = maybe_maybe_scfl.get(); + if (!maybe_scfl) { - return maybe_maybe_scf.error(); + return maybe_maybe_scfl.error(); } - auto scf = maybe_scf->get(); + auto scf = maybe_scfl->source_control_file.get(); if (!scf) { return std::unique_ptr(); @@ -739,14 +740,14 @@ namespace ExpectedL> BuiltinFilesRegistry::get_baseline_version(StringView port_name) const { // if a baseline is not specified, use the ports directory version - const auto& maybe_maybe_scf = get_scf(port_name, m_builtin_ports_directory / port_name); - auto maybe_scf = maybe_maybe_scf.get(); - if (!maybe_scf) + const auto& maybe_maybe_scfl = get_scfl(port_name, m_builtin_ports_directory / port_name); + auto maybe_scfl = maybe_maybe_scfl.get(); + if (!maybe_scfl) { - return maybe_maybe_scf.error(); + return maybe_maybe_scfl.error(); } - auto scf = maybe_scf->get(); + auto scf = maybe_scfl->source_control_file.get(); if (!scf) { return Optional(); @@ -1116,7 +1117,7 @@ namespace // { RegistryEntry // { BuiltinRegistryEntry::RegistryEntry - ExpectedL BuiltinGitRegistryEntry::get_version(const Version& version) const + ExpectedL BuiltinGitRegistryEntry::get_version(const Version& version) const { auto& port_versions = port_versions_soa.port_versions(); auto it = std::find(port_versions.begin(), port_versions.end(), version); @@ -1130,7 +1131,7 @@ namespace const auto& git_tree = port_versions_soa.git_trees()[it - port_versions.begin()]; return m_paths.git_checkout_port(port_name, git_tree, m_paths.root / ".git") - .map([&git_tree](Path&& p) -> PathAndLocation { + .map([&git_tree](Path&& p) -> PortLocation { return { std::move(p), "git+https://github.com/Microsoft/vcpkg@" + git_tree, @@ -1140,7 +1141,7 @@ namespace // } BuiltinRegistryEntry::RegistryEntry // { FilesystemRegistryEntry::RegistryEntry - ExpectedL FilesystemRegistryEntry::get_version(const Version& version) const + ExpectedL FilesystemRegistryEntry::get_version(const Version& version) const { auto it = std::find(port_versions.begin(), port_versions.end(), version); if (it == port_versions.end()) @@ -1148,10 +1149,8 @@ namespace return msg::format_error( msgVersionDatabaseEntryMissing, msg::package_name = port_name, msg::version = version); } - return PathAndLocation{ - version_paths[it - port_versions.begin()], - "", - }; + + return PortLocation{version_paths[it - port_versions.begin()]}; } // } FilesystemRegistryEntry::RegistryEntry @@ -1203,7 +1202,7 @@ namespace return std::move(maybe_not_stale).error(); } - ExpectedL GitRegistryEntry::get_version(const Version& version) const + ExpectedL GitRegistryEntry::get_version(const Version& version) const { auto it = std::find(last_loaded.port_versions().begin(), last_loaded.port_versions().end(), version); if (it == last_loaded.port_versions().end() && stale) @@ -1225,7 +1224,7 @@ namespace const auto& git_tree = last_loaded.git_trees()[it - last_loaded.port_versions().begin()]; return parent.m_paths.git_extract_tree_from_remote_registry(git_tree).map( - [this, &git_tree](Path&& p) -> PathAndLocation { + [this, &git_tree](Path&& p) -> PortLocation { return { std::move(p), Strings::concat("git+", parent.m_repo, "@", git_tree), diff --git a/src/vcpkg/spdx.cpp b/src/vcpkg/spdx.cpp index 374e36a1f6..fe6cd8d5ad 100644 --- a/src/vcpkg/spdx.cpp +++ b/src/vcpkg/spdx.cpp @@ -167,7 +167,7 @@ std::string vcpkg::create_spdx_sbom(const InstallPlanAction& action, obj.insert("name", action.spec.name()); obj.insert("SPDXID", "SPDXRef-port"); obj.insert("versionInfo", cpgh.to_version().to_string()); - obj.insert("downloadLocation", scfl.registry_location.empty() ? noassert : scfl.registry_location); + obj.insert("downloadLocation", scfl.spdx_location.empty() ? noassert : scfl.spdx_location); if (!cpgh.homepage.empty()) { obj.insert("homepage", cpgh.homepage); From a4b7fa174c6b257ef0f45642acfcf575ebf51b2c Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 17 Oct 2023 21:28:51 -0700 Subject: [PATCH 41/48] Use SchemedVersion in DependencyOverride rather than reinventing it. --- include/vcpkg/sourceparagraph.h | 4 +- include/vcpkg/versions.h | 1 + src/vcpkg-test/dependencies.cpp | 126 +++++++++++++++++--------------- src/vcpkg-test/manifests.cpp | 28 +++---- src/vcpkg/dependencies.cpp | 2 +- src/vcpkg/sourceparagraph.cpp | 17 ++--- src/vcpkg/versions.cpp | 2 + 7 files changed, 90 insertions(+), 90 deletions(-) diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index 0bd760cc1f..f32c1cfa84 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -70,9 +70,7 @@ namespace vcpkg struct DependencyOverride { std::string name; - std::string version; - int port_version = 0; - VersionScheme version_scheme = VersionScheme::String; + SchemedVersion version; Json::Object extra_info; diff --git a/include/vcpkg/versions.h b/include/vcpkg/versions.h index c86c0e8ac2..0f9257fb97 100644 --- a/include/vcpkg/versions.h +++ b/include/vcpkg/versions.h @@ -73,6 +73,7 @@ namespace vcpkg Version version; friend bool operator==(const SchemedVersion& lhs, const SchemedVersion& rhs); + friend bool operator!=(const SchemedVersion& lhs, const SchemedVersion& rhs); }; StringLiteral to_string_literal(VersionScheme scheme); diff --git a/src/vcpkg-test/dependencies.cpp b/src/vcpkg-test/dependencies.cpp index 359e4233ae..7cc7975eb0 100644 --- a/src/vcpkg-test/dependencies.cpp +++ b/src/vcpkg-test/dependencies.cpp @@ -1554,15 +1554,13 @@ TEST_CASE ("version install overrides", "[versionplan]") bp.v["b"] = {"2", 0}; bp.v["c"] = {"2", 0}; + DependencyOverride bdo{"b", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; + DependencyOverride cdo{"c", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; SECTION ("string") { - auto install_plan = create_versioned_install_plan(vp, - bp, - var_provider, - {Dependency{"c"}}, - {DependencyOverride{"b", "1"}, DependencyOverride{"c", "1"}}, - toplevel_spec()) - .value_or_exit(VCPKG_LINE_INFO); + auto install_plan = + create_versioned_install_plan(vp, bp, var_provider, {Dependency{"c"}}, {bdo, cdo}, toplevel_spec()) + .value_or_exit(VCPKG_LINE_INFO); REQUIRE(install_plan.size() == 1); check_name_and_version(install_plan.install_actions[0], "c", {"1", 0}); @@ -1570,13 +1568,9 @@ TEST_CASE ("version install overrides", "[versionplan]") SECTION ("relaxed") { - auto install_plan = create_versioned_install_plan(vp, - bp, - var_provider, - {Dependency{"b"}}, - {DependencyOverride{"b", "1"}, DependencyOverride{"c", "1"}}, - toplevel_spec()) - .value_or_exit(VCPKG_LINE_INFO); + auto install_plan = + create_versioned_install_plan(vp, bp, var_provider, {Dependency{"b"}}, {bdo, cdo}, toplevel_spec()) + .value_or_exit(VCPKG_LINE_INFO); REQUIRE(install_plan.size() == 1); check_name_and_version(install_plan.install_actions[0], "b", {"1", 0}); @@ -1600,13 +1594,10 @@ TEST_CASE ("version install transitive overrides", "[versionplan]") bp.v["b"] = {"2", 0}; bp.v["c"] = {"2", 1}; + DependencyOverride bdo{"b", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; + DependencyOverride cdo{"c", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; WITH_EXPECTED(install_plan, - create_versioned_install_plan(vp, - bp, - var_provider, - {Dependency{"b"}}, - {DependencyOverride{"b", "1"}, DependencyOverride{"c", "1"}}, - toplevel_spec())); + create_versioned_install_plan(vp, bp, var_provider, {Dependency{"b"}}, {bdo, cdo}, toplevel_spec())); REQUIRE(install_plan.size() == 2); check_name_and_version(install_plan.install_actions[0], "c", {"1", 0}); @@ -2144,36 +2135,37 @@ TEST_CASE ("version overlay ports", "[versionplan]") } SECTION ("constraint+override") { - auto install_plan = - create_versioned_install_plan(vp, - bp, - oprovider, - var_provider, - { - Dependency{"a", {}, {}, {VersionConstraintKind::Minimum, "1", 1}}, - }, - { - DependencyOverride{"a", "2", 0}, - }, - toplevel_spec()) - .value_or_exit(VCPKG_LINE_INFO); + auto install_plan = create_versioned_install_plan( + vp, + bp, + oprovider, + var_provider, + { + Dependency{"a", {}, {}, {VersionConstraintKind::Minimum, "1", 1}}, + }, + { + DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"2", 0}}}, + }, + toplevel_spec()) + .value_or_exit(VCPKG_LINE_INFO); REQUIRE(install_plan.size() == 1); check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0}); } SECTION ("override") { - auto install_plan = create_versioned_install_plan(vp, - bp, - oprovider, - var_provider, - { - Dependency{"a"}, - }, - { - DependencyOverride{"a", "2", 0}, - }, - toplevel_spec()) + auto install_plan = create_versioned_install_plan( + vp, + bp, + oprovider, + var_provider, + { + Dependency{"a"}, + }, + { + DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"2", 0}}}, + }, + toplevel_spec()) .value_or_exit(VCPKG_LINE_INFO); REQUIRE(install_plan.size() == 1); @@ -2204,12 +2196,24 @@ TEST_CASE ("respect supports expression", "[versionplan]") // override from non supported to supported version MockOverlayProvider oprovider; install_plan = create_versioned_install_plan( - vp, bp, oprovider, var_provider, {Dependency{"a"}}, {DependencyOverride{"a", "1", 1}}, toplevel_spec()); + vp, + bp, + oprovider, + var_provider, + {Dependency{"a"}}, + {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 1}}}}, + toplevel_spec()); CHECK(install_plan.has_value()); // override from supported to non supported version bp.v["a"] = {"1", 1}; install_plan = create_versioned_install_plan( - vp, bp, oprovider, var_provider, {Dependency{"a"}}, {DependencyOverride{"a", "1", 0}}, toplevel_spec()); + vp, + bp, + oprovider, + var_provider, + {Dependency{"a"}}, + {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 0}}}}, + toplevel_spec()); CHECK_FALSE(install_plan.has_value()); } } @@ -2241,23 +2245,25 @@ TEST_CASE ("respect supports expressions of features", "[versionplan]") { // override from non supported to supported version MockOverlayProvider oprovider; - install_plan = create_versioned_install_plan(vp, - bp, - oprovider, - var_provider, - {Dependency{"a", {{"x"}}}}, - {DependencyOverride{"a", "1", 1}}, - toplevel_spec()); + install_plan = create_versioned_install_plan( + vp, + bp, + oprovider, + var_provider, + {Dependency{"a", {{"x"}}}}, + {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 1}}}}, + toplevel_spec()); CHECK(install_plan.has_value()); // override from supported to non supported version bp.v["a"] = {"1", 1}; - install_plan = create_versioned_install_plan(vp, - bp, - oprovider, - var_provider, - {Dependency{"a", {{"x"}}}}, - {DependencyOverride{"a", "1", 0}}, - toplevel_spec()); + install_plan = create_versioned_install_plan( + vp, + bp, + oprovider, + var_provider, + {Dependency{"a", {{"x"}}}}, + {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 0}}}}, + toplevel_spec()); CHECK_FALSE(install_plan.has_value()); } } diff --git a/src/vcpkg-test/manifests.cpp b/src/vcpkg-test/manifests.cpp index 9411dfb071..630585388c 100644 --- a/src/vcpkg-test/manifests.cpp +++ b/src/vcpkg-test/manifests.cpp @@ -390,7 +390,8 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).port_version == 1); + CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == + SchemedVersion{VersionScheme::String, Version{"abcd", 1}}); parsed = test_parse_port_manifest(R"json({ "name": "zlib", @@ -403,7 +404,8 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).port_version == 1); + CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == + SchemedVersion{VersionScheme::Date, Version{"2018-01-01", 1}}); parsed = test_parse_port_manifest(R"json({ "name": "zlib", @@ -416,7 +418,8 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).port_version == 1); + CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == + SchemedVersion{VersionScheme::Relaxed, Version{"1.2", 1}}); parsed = test_parse_port_manifest(R"json({ "name": "zlib", @@ -429,7 +432,8 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).port_version == 1); + CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == + SchemedVersion{VersionScheme::Semver, Version{"1.2.0", 1}}); } TEST_CASE ("manifest constraints", "[manifests]") @@ -565,9 +569,7 @@ TEST_CASE ("manifest builtin-baseline", "[manifests]") REQUIRE(pgh.core_paragraph->dependencies[0].constraint.port_version == 1); REQUIRE(pgh.core_paragraph->dependencies[0].constraint.type == VersionConstraintKind::Minimum); REQUIRE(pgh.core_paragraph->overrides.size() == 1); - REQUIRE(pgh.core_paragraph->overrides[0].version_scheme == VersionScheme::String); - REQUIRE(pgh.core_paragraph->overrides[0].version == "abcd"); - REQUIRE(pgh.core_paragraph->overrides[0].port_version == 0); + REQUIRE(pgh.core_paragraph->overrides[0].version == SchemedVersion{VersionScheme::String, Version{"abcd", 0}}); REQUIRE(pgh.core_paragraph->builtin_baseline.value_or("does not have a value") == "089fa4de7dca22c67dcab631f618d5cd0697c8d4"); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); @@ -602,9 +604,7 @@ TEST_CASE ("manifest builtin-baseline", "[manifests]") REQUIRE(pgh.core_paragraph->dependencies[0].constraint.port_version == 1); REQUIRE(pgh.core_paragraph->dependencies[0].constraint.type == VersionConstraintKind::Minimum); REQUIRE(pgh.core_paragraph->overrides.size() == 1); - REQUIRE(pgh.core_paragraph->overrides[0].version_scheme == VersionScheme::String); - REQUIRE(pgh.core_paragraph->overrides[0].version == "abcd"); - REQUIRE(pgh.core_paragraph->overrides[0].port_version == 0); + REQUIRE(pgh.core_paragraph->overrides[0].version == SchemedVersion{VersionScheme::String, Version{"abcd", 0}}); REQUIRE(!pgh.core_paragraph->builtin_baseline.has_value()); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning)); @@ -679,8 +679,8 @@ TEST_CASE ("manifest overrides", "[manifests]") auto& pgh = **m_pgh.get(); REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == std::get<0>(v)); REQUIRE(pgh.core_paragraph->overrides.size() == 1); - REQUIRE(pgh.core_paragraph->overrides[0].version_scheme == std::get<1>(v)); - REQUIRE(pgh.core_paragraph->overrides[0].version == std::get<2>(v)); + REQUIRE(pgh.core_paragraph->overrides[0].version == + SchemedVersion{std::get<1>(v), Version{std::get<2>(v).to_string(), 0}}); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); REQUIRE(pgh.check_against_feature_flags({}, feature_flags_with_versioning)); } @@ -733,9 +733,9 @@ TEST_CASE ("manifest overrides", "[manifests]") REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == raw); REQUIRE(pgh.core_paragraph->overrides.size() == 2); REQUIRE(pgh.core_paragraph->overrides[0].name == "abc"); - REQUIRE(pgh.core_paragraph->overrides[0].port_version == 5); + REQUIRE(pgh.core_paragraph->overrides[0].version == SchemedVersion{VersionScheme::String, Version{"hello", 5}}); REQUIRE(pgh.core_paragraph->overrides[1].name == "abcd"); - REQUIRE(pgh.core_paragraph->overrides[1].port_version == 7); + REQUIRE(pgh.core_paragraph->overrides[1].version == SchemedVersion{VersionScheme::String, Version{"hello", 7}}); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); REQUIRE(pgh.check_against_feature_flags({}, feature_flags_with_versioning)); diff --git a/src/vcpkg/dependencies.cpp b/src/vcpkg/dependencies.cpp index fa7fccd69c..50cc8a9fe9 100644 --- a/src/vcpkg/dependencies.cpp +++ b/src/vcpkg/dependencies.cpp @@ -2007,7 +2007,7 @@ namespace vcpkg provider, bprovider, oprovider, var_provider, options.host_triplet, options.packages_dir); for (auto&& o : overrides) { - vpg.add_override(o.name, {o.version, o.port_version}); + vpg.add_override(o.name, o.version.version); } vpg.solve_with_roots(deps, toplevel); diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 7ec557738a..eea405a9c8 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -71,8 +71,6 @@ namespace vcpkg bool operator==(const DependencyOverride& lhs, const DependencyOverride& rhs) { - if (lhs.version_scheme != rhs.version_scheme) return false; - if (lhs.port_version != rhs.port_version) return false; if (lhs.name != rhs.name) return false; if (lhs.version != rhs.version) return false; return lhs.extra_info == rhs.extra_info; @@ -762,16 +760,10 @@ namespace vcpkg Json::Reader& r, const Json::Object& obj, std::string& name, - std::string& version, - VersionScheme& version_scheme, - int& port_version) + SchemedVersion& version) { r.required_object_field(type_name, obj, NAME, name, Json::PackageNameDeserializer::instance); - - auto schemed_version = visit_required_schemed_deserializer(type_name, r, obj, true); - version = schemed_version.version.text(); - version_scheme = schemed_version.scheme; - port_version = schemed_version.version.port_version(); + version = visit_required_schemed_deserializer(type_name, r, obj, true); } virtual Optional visit_object(Json::Reader& r, const Json::Object& obj) const override @@ -786,7 +778,7 @@ namespace vcpkg } } - visit_impl(type_name(), r, obj, dep.name, dep.version, dep.version_scheme, dep.port_version); + visit_impl(type_name(), r, obj, dep.name, dep.version); return dep; } @@ -1823,7 +1815,8 @@ namespace vcpkg dep_obj.insert(DependencyOverrideDeserializer::NAME, Json::Value::string(dep.name)); - serialize_schemed_version(dep_obj, dep.version_scheme, dep.version, dep.port_version); + serialize_schemed_version( + dep_obj, dep.version.scheme, dep.version.version.text(), dep.version.version.port_version()); }; auto serialize_license = diff --git a/src/vcpkg/versions.cpp b/src/vcpkg/versions.cpp index 7b09d4df50..c02d3aa597 100644 --- a/src/vcpkg/versions.cpp +++ b/src/vcpkg/versions.cpp @@ -341,6 +341,8 @@ namespace vcpkg return lhs.scheme == rhs.scheme && lhs.version == rhs.version; } + bool operator!=(const SchemedVersion& lhs, const SchemedVersion& rhs) { return !(lhs == rhs); } + StringLiteral to_string_literal(VersionScheme scheme) { static constexpr StringLiteral MISSING = "missing"; From db175088723e4926b2436d0541b8170faac89215 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 19 Oct 2023 16:56:04 -0700 Subject: [PATCH 42/48] Back off to Version given that the scheme is not significant to overrides. --- include/vcpkg/sourceparagraph.h | 3 +- src/vcpkg-test/dependencies.cpp | 120 +++++++++++++++----------------- src/vcpkg-test/manifests.cpp | 55 ++++++++++----- src/vcpkg/dependencies.cpp | 2 +- src/vcpkg/sourceparagraph.cpp | 20 ++---- 5 files changed, 107 insertions(+), 93 deletions(-) diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index f32c1cfa84..3fc06a42d3 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -70,7 +70,8 @@ namespace vcpkg struct DependencyOverride { std::string name; - SchemedVersion version; + Version version; + VersionScheme scheme; Json::Object extra_info; diff --git a/src/vcpkg-test/dependencies.cpp b/src/vcpkg-test/dependencies.cpp index 7cc7975eb0..01a36d6d46 100644 --- a/src/vcpkg-test/dependencies.cpp +++ b/src/vcpkg-test/dependencies.cpp @@ -1554,8 +1554,8 @@ TEST_CASE ("version install overrides", "[versionplan]") bp.v["b"] = {"2", 0}; bp.v["c"] = {"2", 0}; - DependencyOverride bdo{"b", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; - DependencyOverride cdo{"c", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; + DependencyOverride bdo{"b", Version{"1", 0}, VersionScheme::String}; + DependencyOverride cdo{"c", Version{"1", 0}, VersionScheme::String}; SECTION ("string") { auto install_plan = @@ -1594,8 +1594,8 @@ TEST_CASE ("version install transitive overrides", "[versionplan]") bp.v["b"] = {"2", 0}; bp.v["c"] = {"2", 1}; - DependencyOverride bdo{"b", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; - DependencyOverride cdo{"c", SchemedVersion{VersionScheme::String, Version{"1", 0}}}; + DependencyOverride bdo{"b", Version{"1", 0}, VersionScheme::String}; + DependencyOverride cdo{"c", Version{"1", 0}, VersionScheme::String}; WITH_EXPECTED(install_plan, create_versioned_install_plan(vp, bp, var_provider, {Dependency{"b"}}, {bdo, cdo}, toplevel_spec())); @@ -2135,38 +2135,38 @@ TEST_CASE ("version overlay ports", "[versionplan]") } SECTION ("constraint+override") { - auto install_plan = create_versioned_install_plan( - vp, - bp, - oprovider, - var_provider, - { - Dependency{"a", {}, {}, {VersionConstraintKind::Minimum, "1", 1}}, - }, - { - DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"2", 0}}}, - }, - toplevel_spec()) - .value_or_exit(VCPKG_LINE_INFO); + auto install_plan = + create_versioned_install_plan(vp, + bp, + oprovider, + var_provider, + { + Dependency{"a", {}, {}, {VersionConstraintKind::Minimum, "1", 1}}, + }, + { + DependencyOverride{"a", Version{"2", 0}, VersionScheme::String}, + }, + toplevel_spec()) + .value_or_exit(VCPKG_LINE_INFO); REQUIRE(install_plan.size() == 1); check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0}); } SECTION ("override") { - auto install_plan = create_versioned_install_plan( - vp, - bp, - oprovider, - var_provider, - { - Dependency{"a"}, - }, - { - DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"2", 0}}}, - }, - toplevel_spec()) - .value_or_exit(VCPKG_LINE_INFO); + auto install_plan = + create_versioned_install_plan(vp, + bp, + oprovider, + var_provider, + { + Dependency{"a"}, + }, + { + DependencyOverride{"a", Version{"2", 0}, VersionScheme::String}, + }, + toplevel_spec()) + .value_or_exit(VCPKG_LINE_INFO); REQUIRE(install_plan.size() == 1); check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0}); @@ -2195,25 +2195,23 @@ TEST_CASE ("respect supports expression", "[versionplan]") { // override from non supported to supported version MockOverlayProvider oprovider; - install_plan = create_versioned_install_plan( - vp, - bp, - oprovider, - var_provider, - {Dependency{"a"}}, - {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 1}}}}, - toplevel_spec()); + install_plan = create_versioned_install_plan(vp, + bp, + oprovider, + var_provider, + {Dependency{"a"}}, + {DependencyOverride{"a", Version{"1", 1}, VersionScheme::String}}, + toplevel_spec()); CHECK(install_plan.has_value()); // override from supported to non supported version bp.v["a"] = {"1", 1}; - install_plan = create_versioned_install_plan( - vp, - bp, - oprovider, - var_provider, - {Dependency{"a"}}, - {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 0}}}}, - toplevel_spec()); + install_plan = create_versioned_install_plan(vp, + bp, + oprovider, + var_provider, + {Dependency{"a"}}, + {DependencyOverride{"a", Version{"1", 0}, VersionScheme::String}}, + toplevel_spec()); CHECK_FALSE(install_plan.has_value()); } } @@ -2245,25 +2243,23 @@ TEST_CASE ("respect supports expressions of features", "[versionplan]") { // override from non supported to supported version MockOverlayProvider oprovider; - install_plan = create_versioned_install_plan( - vp, - bp, - oprovider, - var_provider, - {Dependency{"a", {{"x"}}}}, - {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 1}}}}, - toplevel_spec()); + install_plan = create_versioned_install_plan(vp, + bp, + oprovider, + var_provider, + {Dependency{"a", {{"x"}}}}, + {DependencyOverride{"a", Version{"1", 1}, VersionScheme::String}}, + toplevel_spec()); CHECK(install_plan.has_value()); // override from supported to non supported version bp.v["a"] = {"1", 1}; - install_plan = create_versioned_install_plan( - vp, - bp, - oprovider, - var_provider, - {Dependency{"a", {{"x"}}}}, - {DependencyOverride{"a", SchemedVersion{VersionScheme::String, Version{"1", 0}}}}, - toplevel_spec()); + install_plan = create_versioned_install_plan(vp, + bp, + oprovider, + var_provider, + {Dependency{"a", {{"x"}}}}, + {DependencyOverride{"a", Version{"1", 0}, VersionScheme::String}}, + toplevel_spec()); CHECK_FALSE(install_plan.has_value()); } } diff --git a/src/vcpkg-test/manifests.cpp b/src/vcpkg-test/manifests.cpp index 630585388c..83f51f8d68 100644 --- a/src/vcpkg-test/manifests.cpp +++ b/src/vcpkg-test/manifests.cpp @@ -390,8 +390,11 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == - SchemedVersion{VersionScheme::String, Version{"abcd", 1}}); + { + const auto& first_override = (*parsed.get())->core_paragraph->overrides.at(0); + CHECK(first_override.version == Version{"abcd", 1}); + CHECK(first_override.scheme == VersionScheme::String); + } parsed = test_parse_port_manifest(R"json({ "name": "zlib", @@ -404,8 +407,11 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == - SchemedVersion{VersionScheme::Date, Version{"2018-01-01", 1}}); + { + const auto& first_override = (*parsed.get())->core_paragraph->overrides.at(0); + CHECK(first_override.version == Version{"2018-01-01", 1}); + CHECK(first_override.scheme == VersionScheme::Date); + } parsed = test_parse_port_manifest(R"json({ "name": "zlib", @@ -418,8 +424,11 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == - SchemedVersion{VersionScheme::Relaxed, Version{"1.2", 1}}); + { + const auto& first_override = (*parsed.get())->core_paragraph->overrides.at(0); + CHECK(first_override.version == Version{"1.2", 1}); + CHECK(first_override.scheme == VersionScheme::Relaxed); + } parsed = test_parse_port_manifest(R"json({ "name": "zlib", @@ -432,8 +441,11 @@ TEST_CASE ("manifest overrides embedded port version", "[manifests]") ] })json"); REQUIRE(parsed.has_value()); - CHECK((*parsed.get())->core_paragraph->overrides.at(0).version == - SchemedVersion{VersionScheme::Semver, Version{"1.2.0", 1}}); + { + const auto& first_override = (*parsed.get())->core_paragraph->overrides.at(0); + CHECK(first_override.version == Version{"1.2.0", 1}); + CHECK(first_override.scheme == VersionScheme::Semver); + } } TEST_CASE ("manifest constraints", "[manifests]") @@ -569,7 +581,9 @@ TEST_CASE ("manifest builtin-baseline", "[manifests]") REQUIRE(pgh.core_paragraph->dependencies[0].constraint.port_version == 1); REQUIRE(pgh.core_paragraph->dependencies[0].constraint.type == VersionConstraintKind::Minimum); REQUIRE(pgh.core_paragraph->overrides.size() == 1); - REQUIRE(pgh.core_paragraph->overrides[0].version == SchemedVersion{VersionScheme::String, Version{"abcd", 0}}); + const auto& first_override = pgh.core_paragraph->overrides[0]; + REQUIRE(first_override.version == Version{"abcd", 0}); + REQUIRE(first_override.scheme == VersionScheme::String); REQUIRE(pgh.core_paragraph->builtin_baseline.value_or("does not have a value") == "089fa4de7dca22c67dcab631f618d5cd0697c8d4"); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); @@ -604,7 +618,9 @@ TEST_CASE ("manifest builtin-baseline", "[manifests]") REQUIRE(pgh.core_paragraph->dependencies[0].constraint.port_version == 1); REQUIRE(pgh.core_paragraph->dependencies[0].constraint.type == VersionConstraintKind::Minimum); REQUIRE(pgh.core_paragraph->overrides.size() == 1); - REQUIRE(pgh.core_paragraph->overrides[0].version == SchemedVersion{VersionScheme::String, Version{"abcd", 0}}); + const auto& first_override = pgh.core_paragraph->overrides[0]; + REQUIRE(first_override.version == Version{"abcd", 0}); + REQUIRE(first_override.scheme == VersionScheme::String); REQUIRE(!pgh.core_paragraph->builtin_baseline.has_value()); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning)); @@ -679,8 +695,9 @@ TEST_CASE ("manifest overrides", "[manifests]") auto& pgh = **m_pgh.get(); REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == std::get<0>(v)); REQUIRE(pgh.core_paragraph->overrides.size() == 1); - REQUIRE(pgh.core_paragraph->overrides[0].version == - SchemedVersion{std::get<1>(v), Version{std::get<2>(v).to_string(), 0}}); + const auto& first_override = pgh.core_paragraph->overrides[0]; + REQUIRE(first_override.version == Version{std::get<2>(v).to_string(), 0}); + REQUIRE(first_override.scheme == std::get<1>(v)); REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); REQUIRE(pgh.check_against_feature_flags({}, feature_flags_with_versioning)); } @@ -732,10 +749,16 @@ TEST_CASE ("manifest overrides", "[manifests]") auto& pgh = **m_pgh.get(); REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == raw); REQUIRE(pgh.core_paragraph->overrides.size() == 2); - REQUIRE(pgh.core_paragraph->overrides[0].name == "abc"); - REQUIRE(pgh.core_paragraph->overrides[0].version == SchemedVersion{VersionScheme::String, Version{"hello", 5}}); - REQUIRE(pgh.core_paragraph->overrides[1].name == "abcd"); - REQUIRE(pgh.core_paragraph->overrides[1].version == SchemedVersion{VersionScheme::String, Version{"hello", 7}}); + { + const auto& first_override = pgh.core_paragraph->overrides[0]; + const auto& second_override = pgh.core_paragraph->overrides[1]; + REQUIRE(first_override.name == "abc"); + REQUIRE(first_override.version == Version{"hello", 5}); + REQUIRE(first_override.scheme == VersionScheme::String); + REQUIRE(second_override.name == "abcd"); + REQUIRE(second_override.version == Version{"hello", 7}); + REQUIRE(second_override.scheme == VersionScheme::String); + } REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning)); REQUIRE(pgh.check_against_feature_flags({}, feature_flags_with_versioning)); diff --git a/src/vcpkg/dependencies.cpp b/src/vcpkg/dependencies.cpp index 50cc8a9fe9..766536ef01 100644 --- a/src/vcpkg/dependencies.cpp +++ b/src/vcpkg/dependencies.cpp @@ -2007,7 +2007,7 @@ namespace vcpkg provider, bprovider, oprovider, var_provider, options.host_triplet, options.packages_dir); for (auto&& o : overrides) { - vpg.add_override(o.name, o.version.version); + vpg.add_override(o.name, o.version); } vpg.solve_with_roots(deps, toplevel); diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index eea405a9c8..11f62606b4 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -73,6 +73,7 @@ namespace vcpkg { if (lhs.name != rhs.name) return false; if (lhs.version != rhs.version) return false; + if (lhs.scheme != rhs.scheme) return false; return lhs.extra_info == rhs.extra_info; } bool operator!=(const DependencyOverride& lhs, const DependencyOverride& rhs); @@ -756,16 +757,6 @@ namespace vcpkg return t; } - static void visit_impl(const LocalizedString& type_name, - Json::Reader& r, - const Json::Object& obj, - std::string& name, - SchemedVersion& version) - { - r.required_object_field(type_name, obj, NAME, name, Json::PackageNameDeserializer::instance); - version = visit_required_schemed_deserializer(type_name, r, obj, true); - } - virtual Optional visit_object(Json::Reader& r, const Json::Object& obj) const override { DependencyOverride dep; @@ -778,7 +769,11 @@ namespace vcpkg } } - visit_impl(type_name(), r, obj, dep.name, dep.version); + const auto type_name = this->type_name(); + r.required_object_field(type_name, obj, NAME, dep.name, Json::PackageNameDeserializer::instance); + auto schemed_version = visit_required_schemed_deserializer(type_name, r, obj, true); + dep.version = std::move(schemed_version.version); + dep.scheme = schemed_version.scheme; return dep; } @@ -1815,8 +1810,7 @@ namespace vcpkg dep_obj.insert(DependencyOverrideDeserializer::NAME, Json::Value::string(dep.name)); - serialize_schemed_version( - dep_obj, dep.version.scheme, dep.version.version.text(), dep.version.version.port_version()); + serialize_schemed_version(dep_obj, dep.scheme, dep.version.text(), dep.version.port_version()); }; auto serialize_license = From a18997b4db09d95ce2c0f443761d95587633b886 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 26 Oct 2023 14:03:23 -0700 Subject: [PATCH 43/48] Persist the correct path. --- src/vcpkg/paragraphs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vcpkg/paragraphs.cpp b/src/vcpkg/paragraphs.cpp index 5a3a1cd3de..081b910576 100644 --- a/src/vcpkg/paragraphs.cpp +++ b/src/vcpkg/paragraphs.cpp @@ -395,7 +395,7 @@ namespace StatsTimer timer(g_load_ports_stats); return Json::parse_object(text, origin).then([&](Json::Object&& object) { return do_parse(origin, std::move(object), warning_sink).map([&](std::unique_ptr&& scf) { - return SourceControlFileAndLocation{std::move(scf), spdx_location.to_string()}; + return SourceControlFileAndLocation{std::move(scf), origin.to_string(), spdx_location.to_string()}; }); }); } From 6e794ec60802673ce9043cb1e78214872d832a7e Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Fri, 27 Oct 2023 19:44:44 -0700 Subject: [PATCH 44/48] Code review feedback from 2023-10-26. --- include/vcpkg/paragraphs.h | 15 ++--- include/vcpkg/sourceparagraph.h | 4 +- src/vcpkg/commands.add-version.cpp | 6 +- src/vcpkg/commands.build.cpp | 4 +- src/vcpkg/commands.ci-verify-versions.cpp | 15 +++-- src/vcpkg/dependencies.cpp | 4 +- src/vcpkg/paragraphs.cpp | 69 ++++++----------------- src/vcpkg/sourceparagraph.cpp | 15 ++--- 8 files changed, 46 insertions(+), 86 deletions(-) diff --git a/include/vcpkg/paragraphs.h b/include/vcpkg/paragraphs.h index 21a614b79c..839e8e2a1d 100644 --- a/include/vcpkg/paragraphs.h +++ b/include/vcpkg/paragraphs.h @@ -36,17 +36,10 @@ namespace vcpkg::Paragraphs ExpectedL try_load_port_required(const ReadOnlyFilesystem& fs, StringView port_name, const PortLocation& port_location); - ExpectedL try_load_project_manifest_text(StringView text, - StringView origin, - StringView spdx_location, - MessageSink& warning_sink); - ExpectedL try_load_port_manifest_text(StringView text, - StringView origin, - StringView spdx_location, - MessageSink& warning_sink); - ExpectedL try_load_control_file_text(StringView text, - StringView origin, - StringView spdx_location); + ExpectedL> try_load_port_manifest_text(StringView text, + StringView control_path, + MessageSink& warning_sink); + ExpectedL> try_load_control_file_text(StringView text, StringView control_path); ExpectedL try_load_cached_package(const ReadOnlyFilesystem& fs, const Path& package_dir, diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index 6ae93b73a0..1feacec79d 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -206,10 +206,10 @@ namespace vcpkg Version to_version() const { return source_control_file->to_version(); } VersionScheme scheme() const { return source_control_file->core_paragraph->version_scheme; } SchemedVersion schemed_version() const { return {scheme(), to_version()}; } - Path port_directory() const { return control_location.parent_path(); } + Path port_directory() const { return control_path.parent_path(); } std::unique_ptr source_control_file; - Path control_location; + Path control_path; /// Should model SPDX PackageDownloadLocation. Empty implies NOASSERTION. /// See https://spdx.github.io/spdx-spec/package-information/#77-package-download-location-field diff --git a/src/vcpkg/commands.add-version.cpp b/src/vcpkg/commands.add-version.cpp index 819245448e..0766d025c2 100644 --- a/src/vcpkg/commands.add-version.cpp +++ b/src/vcpkg/commands.add-version.cpp @@ -420,14 +420,14 @@ namespace vcpkg { // check if manifest file is property formatted - if (scf->control_location.filename() == "vcpkg.json") + if (scf->control_path.filename() == "vcpkg.json") { - const auto current_file_content = fs.read_contents(scf->control_location, VCPKG_LINE_INFO); + const auto current_file_content = fs.read_contents(scf->control_path, VCPKG_LINE_INFO); const auto json = serialize_manifest(*scf->source_control_file); const auto formatted_content = Json::stringify(json); if (current_file_content != formatted_content) { - auto command_line = fmt::format("vcpkg format-manifest {}", scf->control_location); + auto command_line = fmt::format("vcpkg format-manifest {}", scf->control_path); msg::println_error( msg::format(msgAddVersionPortHasImproperFormat, msg::package_name = port_name) .append_raw('\n') diff --git a/src/vcpkg/commands.build.cpp b/src/vcpkg/commands.build.cpp index 0c4d91d073..b17a4fdf3c 100644 --- a/src/vcpkg/commands.build.cpp +++ b/src/vcpkg/commands.build.cpp @@ -951,9 +951,9 @@ namespace vcpkg msg::println(msgLoadingOverlayTriplet, msg::path = triplet_file_path); } - if (!Strings::starts_with(scfl.control_location, paths.builtin_ports_directory())) + if (!Strings::starts_with(scfl.control_path, paths.builtin_ports_directory())) { - msg::println(msgInstallingFromLocation, msg::path = scfl.control_location); + msg::println(msgInstallingFromLocation, msg::path = scfl.control_path); } const ElapsedTimer timer; diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index bb14f031b3..3280ec406a 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -71,12 +71,11 @@ namespace if (!maybe_file) continue; const auto& file = maybe_file.value_or_exit(VCPKG_LINE_INFO); - auto maybe_scfl = - control_file == "vcpkg.json" - ? Paragraphs::try_load_port_manifest_text(file, treeish, StringView{}, stdout_sink) - : Paragraphs::try_load_control_file_text(file, treeish, StringView{}); - auto scfl = maybe_scfl.get(); - if (!scfl) + auto maybe_scf = control_file == "vcpkg.json" + ? Paragraphs::try_load_port_manifest_text(file, treeish, stdout_sink) + : Paragraphs::try_load_control_file_text(file, treeish); + auto scf = maybe_scf.get(); + if (!scf) { return {msg::format_error(msgWhileParsingVersionsForPort, msg::package_name = port_name, @@ -86,11 +85,11 @@ namespace .append_raw('\n') .append(msgWhileLoadingPortFromGitTree, msg::commit_sha = treeish) .append_raw('\n') - .append(maybe_scfl.error()), + .append(maybe_scf.error()), expected_right_tag}; } - auto&& git_tree_version = scfl->source_control_file->to_schemed_version(); + auto&& git_tree_version = (**scf).to_schemed_version(); if (version_entry.version.version != git_tree_version.version) { return { diff --git a/src/vcpkg/dependencies.cpp b/src/vcpkg/dependencies.cpp index 71adfc5230..2d00e10829 100644 --- a/src/vcpkg/dependencies.cpp +++ b/src/vcpkg/dependencies.cpp @@ -445,9 +445,9 @@ namespace vcpkg if (auto scfl = action.source_control_file_and_location.get()) { if (!builtin_ports_dir.empty() && - !Strings::case_insensitive_ascii_starts_with(scfl->control_location, builtin_ports_dir)) + !Strings::case_insensitive_ascii_starts_with(scfl->control_path, builtin_ports_dir)) { - out.append_raw(" -- ").append_raw(scfl->control_location); + out.append_raw(" -- ").append_raw(scfl->control_path); } } } diff --git a/src/vcpkg/paragraphs.cpp b/src/vcpkg/paragraphs.cpp index 081b910576..23c15d2108 100644 --- a/src/vcpkg/paragraphs.cpp +++ b/src/vcpkg/paragraphs.cpp @@ -381,62 +381,24 @@ namespace vcpkg::Paragraphs return fs.exists(maybe_directory / "CONTROL", IgnoreErrors{}) || fs.exists(maybe_directory / "vcpkg.json", IgnoreErrors{}); } -} // namespace vcpkg::Paragraphs -namespace -{ - ExpectedL try_load_any_manifest_text( - StringView text, - StringView origin, - StringView spdx_location, - MessageSink& warning_sink, - ExpectedL> (*do_parse)(StringView, const Json::Object&, MessageSink&)) + ExpectedL> try_load_port_manifest_text(StringView text, + StringView control_path, + MessageSink& warning_sink) { StatsTimer timer(g_load_ports_stats); - return Json::parse_object(text, origin).then([&](Json::Object&& object) { - return do_parse(origin, std::move(object), warning_sink).map([&](std::unique_ptr&& scf) { - return SourceControlFileAndLocation{std::move(scf), origin.to_string(), spdx_location.to_string()}; - }); + return Json::parse_object(text, control_path).then([&](Json::Object&& object) { + return SourceControlFile::parse_port_manifest_object(control_path, std::move(object), warning_sink); }); } -} - -namespace vcpkg::Paragraphs -{ - ExpectedL try_load_project_manifest_text(StringView text, - StringView origin, - StringView spdx_location, - MessageSink& warning_sink) - { - return try_load_any_manifest_text( - text, origin, spdx_location, warning_sink, SourceControlFile::parse_project_manifest_object); - } - ExpectedL try_load_port_manifest_text(StringView text, - StringView origin, - StringView spdx_location, - MessageSink& warning_sink) - { - return try_load_any_manifest_text( - text, origin, spdx_location, warning_sink, SourceControlFile::parse_port_manifest_object); - } - - ExpectedL try_load_control_file_text(StringView text, - StringView origin, - StringView spdx_location) + ExpectedL> try_load_control_file_text(StringView text, StringView control_path) { StatsTimer timer(g_load_ports_stats); - return parse_paragraphs(text, origin) - .then([&](std::vector&& vector_pghs) -> ExpectedL { - auto maybe_parsed = SourceControlFile::parse_control_file(origin, std::move(vector_pghs)); - if (auto parsed = maybe_parsed.get()) - { - return SourceControlFileAndLocation{ - std::move(*parsed), origin.to_string(), spdx_location.to_string()}; - } - - return ToLocalizedString(std::move(maybe_parsed).error()); - }); + return parse_paragraphs(text, control_path).then([&](std::vector&& vector_pghs) { + return SourceControlFile::parse_control_file(control_path, std::move(vector_pghs)) + .map_error(ToLocalizedString); + }); } ExpectedL try_load_port(const ReadOnlyFilesystem& fs, @@ -456,8 +418,10 @@ namespace vcpkg::Paragraphs return msg::format_error(msgManifestConflict, msg::path = port_location.port_directory); } - return try_load_port_manifest_text( - manifest_contents, manifest_path, port_location.spdx_location, stdout_sink); + return try_load_port_manifest_text(manifest_contents, manifest_path, stdout_sink) + .map([&](std::unique_ptr&& scf) { + return SourceControlFileAndLocation{std::move(scf), manifest_path, port_location.spdx_location}; + }); } auto manifest_exists = ec != std::errc::no_such_file_or_directory; @@ -471,7 +435,10 @@ namespace vcpkg::Paragraphs auto control_contents = fs.read_contents(control_path, ec); if (!ec) { - return try_load_control_file_text(control_contents, control_path, port_location.spdx_location); + return try_load_control_file_text(control_contents, control_path) + .map([&](std::unique_ptr&& scf) { + return SourceControlFileAndLocation{std::move(scf), control_path, port_location.spdx_location}; + }); } if (ec != std::errc::no_such_file_or_directory) diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index abc00ef1a4..f22b76db4f 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -1439,7 +1439,7 @@ namespace vcpkg } template - static ExpectedL> parse_manifest_object_impl(StringView origin, + static ExpectedL> parse_manifest_object_impl(StringView control_path, const Json::Object& manifest, MessageSink& warnings_sink) { @@ -1449,13 +1449,14 @@ namespace vcpkg for (auto&& w : reader.warnings()) { - warnings_sink.print(Color::warning, LocalizedString::from_raw(Strings::concat(origin, ": ", w, '\n'))); + warnings_sink.print(Color::warning, + LocalizedString::from_raw(Strings::concat(control_path, ": ", w, '\n'))); } if (!reader.errors().empty()) { ParseControlErrorInfo err; - err.name = origin.to_string(); + err.name = control_path.to_string(); err.other_errors = std::move(reader.errors()); return LocalizedString::from_raw(err.to_string()); } @@ -1470,15 +1471,15 @@ namespace vcpkg } ExpectedL> SourceControlFile::parse_project_manifest_object( - StringView origin, const Json::Object& manifest, MessageSink& warnings_sink) + StringView control_path, const Json::Object& manifest, MessageSink& warnings_sink) { - return parse_manifest_object_impl(origin, manifest, warnings_sink); + return parse_manifest_object_impl(control_path, manifest, warnings_sink); } ExpectedL> SourceControlFile::parse_port_manifest_object( - StringView origin, const Json::Object& manifest, MessageSink& warnings_sink) + StringView control_path, const Json::Object& manifest, MessageSink& warnings_sink) { - return parse_manifest_object_impl(origin, manifest, warnings_sink); + return parse_manifest_object_impl(control_path, manifest, warnings_sink); } ExpectedL SourceControlFile::check_against_feature_flags(const Path& origin, From 570d2f3c311f61ab7c178bbadb70ccb918e06982 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 7 Nov 2023 12:55:04 -0800 Subject: [PATCH 45/48] Merge gore. Not sure if I want to keep format-manifest changes looking like this. --- src/vcpkg/commands.ci-verify-versions.cpp | 2 ++ src/vcpkg/commands.format-manifest.cpp | 36 +++++++++++++++++------ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/vcpkg/commands.ci-verify-versions.cpp b/src/vcpkg/commands.ci-verify-versions.cpp index f555253d4e..88d8d11acc 100644 --- a/src/vcpkg/commands.ci-verify-versions.cpp +++ b/src/vcpkg/commands.ci-verify-versions.cpp @@ -126,6 +126,7 @@ namespace { success_sink.print(LocalizedString::from_raw(versions_file_path) .append_raw(": ") + .append_raw(MessagePrefix) .append(msgVersionVerifiedOK, msg::version_spec = VersionSpec{port_name, version_entry.version.version}, msg::git_tree_sha = version_entry.git_tree) @@ -276,6 +277,7 @@ namespace { success_sink.print(LocalizedString::from_raw(scfl.port_directory()) .append_raw(": ") + .append_raw(MessagePrefix) .append(msgVersionVerifiedOK, msg::version_spec = local_version_spec, msg::git_tree_sha = version_entry.git_tree) diff --git a/src/vcpkg/commands.format-manifest.cpp b/src/vcpkg/commands.format-manifest.cpp index 55213c9c1b..101db2a8e9 100644 --- a/src/vcpkg/commands.format-manifest.cpp +++ b/src/vcpkg/commands.format-manifest.cpp @@ -18,13 +18,14 @@ namespace struct ToWrite { std::string original_source; - SourceControlFileAndLocation scf; + std::unique_ptr scf; + Path control_path; Path file_to_write; }; void open_for_write(const Filesystem& fs, const ToWrite& data) { - const auto& original_path_string = data.scf.control_path.native(); + const auto& original_path_string = data.control_path.native(); const auto& file_to_write_string = data.file_to_write.native(); bool in_place = data.file_to_write == original_path_string; if (in_place) @@ -36,7 +37,7 @@ namespace Debug::println("Converting ", file_to_write_string, " -> ", original_path_string); } - auto res = serialize_manifest(*data.scf.source_control_file); + auto res = serialize_manifest(*data.scf); // reparse res to ensure no semantic changes were made auto maybe_reparsed = @@ -44,7 +45,7 @@ namespace bool reparse_matches; if (auto reparsed = maybe_reparsed.get()) { - reparse_matches = **reparsed == *data.scf.source_control_file; + reparse_matches = **reparsed == *data.scf; } else { @@ -135,8 +136,10 @@ namespace vcpkg auto maybe_control = Paragraphs::try_load_control_file_text(contents->content, contents->origin); if (auto control = maybe_control.get()) { - to_write.push_back( - ToWrite{contents->content, std::move(*control), Path(path.parent_path()) / "vcpkg.json"}); + to_write.push_back(ToWrite{contents->content, + std::move(*control), + std::move(path), + Path(path.parent_path()) / "vcpkg.json"}); } else { @@ -150,7 +153,7 @@ namespace vcpkg Paragraphs::try_load_project_manifest_text(contents->content, contents->origin, stdout_sink); if (auto manifest = maybe_manifest.get()) { - to_write.push_back(ToWrite{contents->content, std::move(*manifest), path}); + to_write.push_back(ToWrite{contents->content, std::move(*manifest), path, path}); } else { @@ -168,8 +171,23 @@ namespace vcpkg if (auto manifest = maybe_manifest.maybe_scfl.get()) { auto original = manifest->control_path; - to_write.push_back( - ToWrite{maybe_manifest.on_disk_contents, std::move(*manifest), std::move(original)}); + if (original.filename() == "CONTROL") + { + if (convert_control) + { + to_write.push_back(ToWrite{maybe_manifest.on_disk_contents, + std::move(manifest->source_control_file), + original, + Path(original.parent_path()) / "vcpkg.json"}); + } + } + else + { + to_write.push_back(ToWrite{maybe_manifest.on_disk_contents, + std::move(manifest->source_control_file), + original, + original}); + } } else { From 696c90d93c2b02ec5acda65dba5ed5090d510cc6 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Fri, 10 Nov 2023 15:39:29 -0800 Subject: [PATCH 46/48] Merge gore --- src/vcpkg/commands.add-version.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vcpkg/commands.add-version.cpp b/src/vcpkg/commands.add-version.cpp index f1d8419c15..b039050e18 100644 --- a/src/vcpkg/commands.add-version.cpp +++ b/src/vcpkg/commands.add-version.cpp @@ -418,7 +418,8 @@ namespace vcpkg const auto formatted_content = Json::stringify(json); if (current_file_content != formatted_content) { - auto command_line = fmt::format("vcpkg format-manifest {}", scfl->control_path); + std::string command_line = "vcpkg format-manifest "; + append_shell_escaped(command_line, scfl->control_path); msg::println_error( msg::format(msgAddVersionPortHasImproperFormat, msg::package_name = port_name) .append_raw('\n') From fa865930119fde8dba6639e8aa53b14b87bea0de Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 6 Jun 2024 20:22:03 -0700 Subject: [PATCH 47/48] Revert the `ReaderMessage` part of the change which became https://github.com/microsoft/vcpkg-tool/pull/1323 as requested by @ras0219-msft --- include/vcpkg/base/jsonreader.h | 27 ++---- include/vcpkg/base/message-data.inc.h | 6 ++ locales/messages.json | 12 +++ src/vcpkg-test/configmetadata.cpp | 6 +- src/vcpkg-test/registries.cpp | 87 +++++++++--------- src/vcpkg/base/json.cpp | 127 ++++++++------------------ src/vcpkg/configuration.cpp | 43 +++++---- src/vcpkg/registries.cpp | 16 ++-- src/vcpkg/sourceparagraph.cpp | 68 +++++++++++--- 9 files changed, 201 insertions(+), 191 deletions(-) diff --git a/include/vcpkg/base/jsonreader.h b/include/vcpkg/base/jsonreader.h index d0119a8a9b..61749a4018 100644 --- a/include/vcpkg/base/jsonreader.h +++ b/include/vcpkg/base/jsonreader.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include @@ -43,27 +42,11 @@ namespace vcpkg::Json IDeserializer& operator=(IDeserializer&&) = default; }; - struct ReaderMessage - { - MessageKind kind; - LocalizedString message; - - ReaderMessage(MessageKind kind, LocalizedString&& message); - ReaderMessage(const ReaderMessage&); - ReaderMessage(ReaderMessage&&); - ReaderMessage& operator=(const ReaderMessage&); - ReaderMessage& operator=(ReaderMessage&&); - }; - - LocalizedString join(const std::vector& messages); - LocalizedString flatten_reader_messages(const std::vector& messages, MessageSink& warningsSink); - struct Reader { explicit Reader(StringView origin); - const std::vector& messages() const { return m_messages; } - std::size_t error_count() const { return m_error_count; } + const std::vector& errors() const { return m_errors; } void add_missing_field_error(const LocalizedString& type, StringView key, const LocalizedString& key_type); void add_expected_type_error(const LocalizedString& expected_type); @@ -72,6 +55,10 @@ namespace vcpkg::Json void add_warning(LocalizedString type, StringView msg); + const std::vector& warnings() const { return m_warnings; } + + LocalizedString join() const; + std::string path() const noexcept; StringView origin() const noexcept; @@ -79,8 +66,8 @@ namespace vcpkg::Json template friend struct IDeserializer; - std::vector m_messages; - std::size_t m_error_count; + std::vector m_errors; + std::vector m_warnings; struct JsonPathElement { constexpr JsonPathElement() = default; diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 0f609b2759..1af885eac2 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -1218,6 +1218,11 @@ DECLARE_MESSAGE(FailedToParseCMakeConsoleOut, (), "", "Failed to parse CMake console output to locate block start/end markers.") +DECLARE_MESSAGE(FailedToParseBaseline, (msg::path), "", "Failed to parse baseline: {path}") +DECLARE_MESSAGE(FailedToParseConfig, (msg::path), "", "Failed to parse configuration: {path}") +DECLARE_MESSAGE(FailedToParseControl, (msg::path), "", "Failed to parse CONTROL file: {path}") +DECLARE_MESSAGE(FailedToParseManifest, (msg::path), "", "Failed to parse manifest file: {path}") +DECLARE_MESSAGE(FailedToParseVersionFile, (msg::path), "", "Failed to parse version file: {path}") DECLARE_MESSAGE(FailedToParseNoTopLevelObj, (msg::path), "", "Failed to parse {path}, expected a top-level object.") DECLARE_MESSAGE(FailedToParseNoVersionsArray, (msg::path), "", "Failed to parse {path}, expected a 'versions' array.") DECLARE_MESSAGE(FailedToParseSerializedBinParagraph, @@ -3018,6 +3023,7 @@ DECLARE_MESSAGE(VSNoInstances, (), "", "Could not locate a complete Visual Studi DECLARE_MESSAGE(WaitingForChildrenToExit, (), "", "Waiting for child processes to exit...") DECLARE_MESSAGE(WaitingToTakeFilesystemLock, (msg::path), "", "waiting to take filesystem lock on {path}...") DECLARE_MESSAGE(WarningsTreatedAsErrors, (), "", "previous warnings being interpreted as errors") +DECLARE_MESSAGE(WarnOnParseConfig, (msg::path), "", "Found the following warnings in configuration {path}:") DECLARE_MESSAGE(WhileCheckingOutBaseline, (msg::commit_sha), "", "while checking out baseline {commit_sha}") DECLARE_MESSAGE(WhileCheckingOutPortTreeIsh, (msg::package_name, msg::git_tree_sha), diff --git a/locales/messages.json b/locales/messages.json index 8e9fcc1082..7d873261c8 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -736,13 +736,23 @@ "FailedToObtainPackageVersion": "Cannot find desired package version.", "FailedToOpenAlgorithm": "failed to open {value}", "_FailedToOpenAlgorithm.comment": "{value} is a crypto algorithm like SHA-1 or SHA-512", + "FailedToParseBaseline": "Failed to parse baseline: {path}", + "_FailedToParseBaseline.comment": "An example of {path} is /foo/bar.", "FailedToParseCMakeConsoleOut": "Failed to parse CMake console output to locate block start/end markers.", + "FailedToParseConfig": "Failed to parse configuration: {path}", + "_FailedToParseConfig.comment": "An example of {path} is /foo/bar.", + "FailedToParseControl": "Failed to parse CONTROL file: {path}", + "_FailedToParseControl.comment": "An example of {path} is /foo/bar.", + "FailedToParseManifest": "Failed to parse manifest file: {path}", + "_FailedToParseManifest.comment": "An example of {path} is /foo/bar.", "FailedToParseNoTopLevelObj": "Failed to parse {path}, expected a top-level object.", "_FailedToParseNoTopLevelObj.comment": "An example of {path} is /foo/bar.", "FailedToParseNoVersionsArray": "Failed to parse {path}, expected a 'versions' array.", "_FailedToParseNoVersionsArray.comment": "An example of {path} is /foo/bar.", "FailedToParseSerializedBinParagraph": "[sanity check] Failed to parse a serialized binary paragraph.\nPlease open an issue at https://github.com/microsoft/vcpkg, with the following output:\n{error_msg}\nSerialized Binary Paragraph:", "_FailedToParseSerializedBinParagraph.comment": "'{error_msg}' is the error message for failing to parse the Binary Paragraph. An example of {error_msg} is File Not Found.", + "FailedToParseVersionFile": "Failed to parse version file: {path}", + "_FailedToParseVersionFile.comment": "An example of {path} is /foo/bar.", "FailedToParseVersionXML": "Could not parse version for tool {tool_name}. Version string was: {version}", "_FailedToParseVersionXML.comment": "An example of {tool_name} is aria2. An example of {version} is 1.3.8.", "FailedToReadParagraph": "Failed to read paragraphs from {path}", @@ -1647,6 +1657,8 @@ "WaitingForChildrenToExit": "Waiting for child processes to exit...", "WaitingToTakeFilesystemLock": "waiting to take filesystem lock on {path}...", "_WaitingToTakeFilesystemLock.comment": "An example of {path} is /foo/bar.", + "WarnOnParseConfig": "Found the following warnings in configuration {path}:", + "_WarnOnParseConfig.comment": "An example of {path} is /foo/bar.", "WarningsTreatedAsErrors": "previous warnings being interpreted as errors", "WhileCheckingOutBaseline": "while checking out baseline {commit_sha}", "_WhileCheckingOutBaseline.comment": "An example of {commit_sha} is 7cfad47ae9f68b183983090afd6337cd60fd4949.", diff --git a/src/vcpkg-test/configmetadata.cpp b/src/vcpkg-test/configmetadata.cpp index 25643a3614..57373bd03d 100644 --- a/src/vcpkg-test/configmetadata.cpp +++ b/src/vcpkg-test/configmetadata.cpp @@ -41,7 +41,7 @@ static Configuration parse_test_configuration(StringView text) Json::Reader reader(origin); auto parsed_config_opt = reader.visit(object, get_configuration_deserializer()); - REQUIRE(reader.messages().empty()); + REQUIRE(reader.errors().empty()); return std::move(parsed_config_opt).value_or_exit(VCPKG_LINE_INFO); } @@ -61,9 +61,9 @@ static void check_errors(const std::string& config_text, const std::string& expe Json::Reader reader(origin); auto parsed_config_opt = reader.visit(object, get_configuration_deserializer()); - REQUIRE(reader.error_count() != 0); + REQUIRE(!reader.errors().empty()); - CHECK_LINES(Json::join(reader.messages()).data(), expected_errors); + CHECK_LINES(Strings::join("\n", reader.errors()), expected_errors); } TEST_CASE ("config registries only", "[ce-metadata]") diff --git a/src/vcpkg-test/registries.cpp b/src/vcpkg-test/registries.cpp index c62e724952..095c6d0bf8 100644 --- a/src/vcpkg-test/registries.cpp +++ b/src/vcpkg-test/registries.cpp @@ -276,7 +276,7 @@ TEST_CASE ("registry_parsing", "[registries]") } )json"); visit_default_registry(r, std::move(test_json)); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } { Json::Reader r{"test"}; @@ -288,7 +288,7 @@ TEST_CASE ("registry_parsing", "[registries]") )json"); visit_default_registry(r, std::move(test_json)); // Non-SHA strings are allowed and will be diagnosed later - CHECK(r.error_count() == 0); + CHECK(r.errors().empty()); } { Json::Reader r{"test"}; @@ -300,7 +300,7 @@ TEST_CASE ("registry_parsing", "[registries]") )json"); auto registry_impl = visit_default_registry(r, std::move(test_json)); REQUIRE(registry_impl); - CHECK(r.error_count() == 0); + CHECK(r.errors().empty()); } { Json::Reader r{"test"}; @@ -312,7 +312,7 @@ TEST_CASE ("registry_parsing", "[registries]") } )json"); visit_default_registry(r, std::move(test_json)); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } { Json::Reader r{"test"}; @@ -324,7 +324,7 @@ TEST_CASE ("registry_parsing", "[registries]") )json"); auto registry_impl = visit_default_registry(r, std::move(test_json)); REQUIRE(registry_impl); - CHECK(r.error_count() == 0); + CHECK(r.errors().empty()); test_json = parse_json(R"json( { @@ -334,7 +334,7 @@ TEST_CASE ("registry_parsing", "[registries]") )json"); registry_impl = visit_default_registry(r, std::move(test_json)); REQUIRE(registry_impl); - CHECK(r.error_count() == 0); + CHECK(r.errors().empty()); } auto test_json = parse_json(R"json( @@ -345,7 +345,7 @@ TEST_CASE ("registry_parsing", "[registries]") { Json::Reader r{"test"}; visit_default_registry(r, std::move(test_json)); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } test_json = parse_json(R"json( { @@ -356,7 +356,7 @@ TEST_CASE ("registry_parsing", "[registries]") { Json::Reader r{"test"}; visit_default_registry(r, std::move(test_json)); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } test_json = parse_json(R"json( @@ -368,7 +368,7 @@ TEST_CASE ("registry_parsing", "[registries]") { Json::Reader r{"test"}; visit_default_registry(r, std::move(test_json)); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } test_json = parse_json(R"json( @@ -383,8 +383,8 @@ TEST_CASE ("registry_parsing", "[registries]") Json::Reader r{"test"}; auto registry_impl = visit_default_registry(r, std::move(test_json)); REQUIRE(registry_impl); - INFO(Json::join(r.messages()).data()); - CHECK(r.error_count() == 0); + INFO(Strings::join("\n", r.errors())); + CHECK(r.errors().empty()); } test_json = parse_json(R"json( @@ -397,8 +397,8 @@ TEST_CASE ("registry_parsing", "[registries]") Json::Reader r{"test"}; auto registry_impl = visit_default_registry(r, std::move(test_json)); REQUIRE(registry_impl); - INFO(Json::join(r.messages()).data()); - CHECK(r.error_count() == 0); + INFO(Strings::join("\n", r.errors())); + CHECK(r.errors().empty()); } TEST_CASE ("registries report pattern errors", "[registries]") @@ -416,20 +416,21 @@ TEST_CASE ("registries report pattern errors", "[registries]") Json::Reader r{"test"}; auto maybe_conf = r.visit(test_json, get_configuration_deserializer()); - const auto& messages = r.messages(); - REQUIRE(messages.size() == 3); - CHECK(messages[0].message == - "test: error: $.registries[0].packages[1] (a package pattern): \"\" is not a valid package pattern. Package " - "patterns must use only one wildcard character (*) and it must be the last character in the pattern (see " - "https://learn.microsoft.com/vcpkg/users/registries for more information)."); - CHECK(messages[1].message == - "test: error: $.registries[0].packages[2] (a package pattern): \"a*a\" is not a valid package pattern. " - "Package patterns must use only one wildcard character (*) and it must be the last character in the pattern " - "(see https://learn.microsoft.com/vcpkg/users/registries for more information)."); - CHECK(messages[2].message == - "test: error: $.registries[0].packages[3] (a package pattern): \"*a\" is not a valid package pattern. " - "Package patterns must use only one wildcard character (*) and it must be the last character in the pattern " - "(see https://learn.microsoft.com/vcpkg/users/registries for more information)."); + const auto& errors = r.errors(); + CHECK(!errors.empty()); + REQUIRE(errors.size() == 3); + CHECK(errors[0] == "test: error: $.registries[0].packages[1] (a package pattern): \"\" is not a valid package " + "pattern. Package patterns must " + "use only one wildcard character (*) and it must be the last character in the pattern (see " + "https://learn.microsoft.com/vcpkg/users/registries for more information)."); + CHECK(errors[1] == "test: error: $.registries[0].packages[2] (a package pattern): \"a*a\" is not a valid package " + "pattern. Package patterns " + "must use only one wildcard character (*) and it must be the last character in the pattern (see " + "https://learn.microsoft.com/vcpkg/users/registries for more information)."); + CHECK(errors[2] == "test: error: $.registries[0].packages[3] (a package pattern): \"*a\" is not a valid package " + "pattern. Package patterns " + "must use only one wildcard character (*) and it must be the last character in the pattern (see " + "https://learn.microsoft.com/vcpkg/users/registries for more information)."); } TEST_CASE ("registries ignored patterns warning", "[registries]") @@ -498,9 +499,9 @@ TEST_CASE ("registries ignored patterns warning", "[registries]") CHECK((*pkgs)[1] == "bei*"); CHECK((*pkgs)[2] == "zlib"); - const auto& messages = r.messages(); - REQUIRE(messages.size() == 3); - CHECK(messages[0].message == R"(test: warning: $ (a configuration object): Package "*" is duplicated. + const auto& warnings = r.warnings(); + REQUIRE(warnings.size() == 3); + CHECK(warnings[0] == R"(test: warning: $ (a configuration object): Package "*" is duplicated. First declared in: location: $.registries[0].packages[0] registry: https://github.com/Microsoft/vcpkg @@ -509,7 +510,7 @@ TEST_CASE ("registries ignored patterns warning", "[registries]") location: $.registries[2].packages[0] registry: https://github.com/another-remote/another-vcpkg-registry )"); - CHECK(messages[1].message == R"(test: warning: $ (a configuration object): Package "bei*" is duplicated. + CHECK(warnings[1] == R"(test: warning: $ (a configuration object): Package "bei*" is duplicated. First declared in: location: $.registries[1].packages[0] registry: https://github.com/northwindtraders/vcpkg-registry @@ -518,7 +519,7 @@ TEST_CASE ("registries ignored patterns warning", "[registries]") location: $.registries[2].packages[1] registry: https://github.com/another-remote/another-vcpkg-registry )"); - CHECK(messages[2].message == R"(test: warning: $ (a configuration object): Package "zlib" is duplicated. + CHECK(warnings[2] == R"(test: warning: $ (a configuration object): Package "zlib" is duplicated. First declared in: location: $.registries[0].packages[2] registry: https://github.com/Microsoft/vcpkg @@ -564,7 +565,7 @@ TEST_CASE ("git_version_db_parsing", "[registries]") CHECK(results[1].git_tree == "12b84a31469a78dd4b42dcf58a27d4600f6b2d48"); CHECK(results[2].version == SchemedVersion{VersionScheme::String, Version{"2020-04-12", 0}}); CHECK(results[2].git_tree == "bd4565e8ab55bc5e098a1750fa5ff0bc4406ca9b"); - CHECK(r.error_count() == 0); + CHECK(r.errors().empty()); } TEST_CASE ("filesystem_version_db_parsing", "[registries]") @@ -600,7 +601,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") CHECK(results[1].p == "a/b" VCPKG_PREFERRED_SEPARATOR "e/d"); CHECK(results[2].version == SchemedVersion{VersionScheme::Semver, {"1.2.3", 0}}); CHECK(results[2].p == "a/b" VCPKG_PREFERRED_SEPARATOR "semvers/here"); - CHECK(r.error_count() == 0); + CHECK(r.errors().empty()); } { // missing $/ @@ -615,7 +616,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } { // uses backslash @@ -630,7 +631,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } { // doubled slash @@ -645,7 +646,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } { // dot path (first) @@ -660,7 +661,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } { // dot path (mid) @@ -675,7 +676,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } { // dot path (last) @@ -690,7 +691,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } { // dot dot path (first) @@ -705,7 +706,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } { // dot dot path (mid) @@ -720,7 +721,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } { // dot dot path (last) @@ -735,7 +736,7 @@ TEST_CASE ("filesystem_version_db_parsing", "[registries]") ] )json"); CHECK(r.visit(test_json, *filesystem_version_db).value_or_exit(VCPKG_LINE_INFO).empty()); - CHECK(r.error_count() != 0); + CHECK(!r.errors().empty()); } } diff --git a/src/vcpkg/base/json.cpp b/src/vcpkg/base/json.cpp index 96bf92e850..ff36c8aeba 100644 --- a/src/vcpkg/base/json.cpp +++ b/src/vcpkg/base/json.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -1393,71 +1392,9 @@ namespace vcpkg::Json return res; } - ReaderMessage::ReaderMessage(MessageKind kind, LocalizedString&& message) : kind(kind), message(std::move(message)) - { - } - - ReaderMessage::ReaderMessage(const ReaderMessage&) = default; - ReaderMessage::ReaderMessage(ReaderMessage&&) = default; - ReaderMessage& ReaderMessage::operator=(const ReaderMessage&) = default; - ReaderMessage& ReaderMessage::operator=(ReaderMessage&&) = default; - - LocalizedString join(const std::vector& messages) - { - LocalizedString result; - auto first = messages.begin(); - const auto last = messages.end(); - if (first == last) - { - return result; - } - - for (;;) - { - result.append(first->message); - if (++first == last) - { - return result; - } - - result.append_raw('\n'); - } - } - - LocalizedString flatten_reader_messages(const std::vector& messages, MessageSink& warningsSink) - { - LocalizedString flat_errors; - for (auto&& message : messages) - { - switch (message.kind) - { - case MessageKind::Warning: warningsSink.println(Color::warning, message.message); break; - case MessageKind::Error: - if (!flat_errors.empty()) - { - flat_errors.append_raw('\n'); - } - - flat_errors.append(message.message); - - break; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - - return flat_errors; - } - static std::atomic g_json_reader_stats(0); - Reader::Reader(StringView origin) - : m_messages() - , m_error_count(0) - , m_origin(origin.data(), origin.size()) - , m_path() - , m_stat_timer(g_json_reader_stats) - { - } + Reader::Reader(StringView origin) : m_origin(origin.data(), origin.size()), m_stat_timer(g_json_reader_stats) { } uint64_t Reader::get_reader_stats() { return g_json_reader_stats.load(); } @@ -1467,13 +1404,10 @@ namespace vcpkg::Json } void Reader::add_expected_type_error(const LocalizedString& expected_type) { - ++m_error_count; - m_messages.emplace_back( - MessageKind::Error, - LocalizedString::from_raw(m_origin) - .append_raw(": ") - .append_raw(ErrorPrefix) - .append(msgMismatchedType, msg::json_field = path(), msg::json_type = expected_type)); + m_errors.push_back(LocalizedString::from_raw(m_origin) + .append_raw(": ") + .append_raw(ErrorPrefix) + .append(msgMismatchedType, msg::json_field = path(), msg::json_type = expected_type)); } void Reader::add_extra_field_error(const LocalizedString& type, StringView field, StringView suggestion) { @@ -1489,16 +1423,14 @@ namespace vcpkg::Json } void Reader::add_generic_error(const LocalizedString& type, StringView message) { - ++m_error_count; - m_messages.emplace_back(MessageKind::Error, - LocalizedString::from_raw(m_origin) - .append_raw(": ") - .append_raw(ErrorPrefix) - .append_raw(path()) - .append_raw(" (") - .append(type) - .append_raw("): ") - .append_raw(message)); + m_errors.push_back(LocalizedString::from_raw(m_origin) + .append_raw(": ") + .append_raw(ErrorPrefix) + .append_raw(path()) + .append_raw(" (") + .append(type) + .append_raw("): ") + .append_raw(message)); } void Reader::check_for_unexpected_fields(const Object& obj, @@ -1530,15 +1462,30 @@ namespace vcpkg::Json void Reader::add_warning(LocalizedString type, StringView msg) { - m_messages.emplace_back(MessageKind::Warning, - LocalizedString::from_raw(m_origin) - .append_raw(": ") - .append_raw(WarningPrefix) - .append_raw(path()) - .append_raw(" (") - .append(type) - .append_raw("): ") - .append_raw(msg)); + m_warnings.push_back(LocalizedString::from_raw(m_origin) + .append_raw(": ") + .append_raw(WarningPrefix) + .append_raw(path()) + .append_raw(" (") + .append(type) + .append_raw("): ") + .append_raw(msg)); + } + + LocalizedString Reader::join() const + { + LocalizedString res; + for (const auto& e : m_errors) + { + if (!res.empty()) res.append_raw("\n"); + res.append(e); + } + for (const auto& w : m_warnings) + { + if (!res.empty()) res.append_raw("\n"); + res.append(w); + } + return res; } std::string Reader::path() const noexcept diff --git a/src/vcpkg/configuration.cpp b/src/vcpkg/configuration.cpp index 44ec3722c9..ad7e904ba5 100644 --- a/src/vcpkg/configuration.cpp +++ b/src/vcpkg/configuration.cpp @@ -380,10 +380,10 @@ namespace { auto extract_string = [&](const Json::Object& obj, StringView key, Json::Object& put_into) { std::string value; - const auto errors_count = r.error_count(); + const auto errors_count = r.errors(); if (r.optional_object_field(obj, key, value, Json::UntypedStringDeserializer::instance)) { - if (errors_count != r.error_count()) return; + if (errors_count != r.errors()) return; put_into.insert_or_replace(key, std::move(value)); } }; @@ -402,10 +402,10 @@ namespace }; auto extract_dictionary = [&](const Json::Object& obj, StringView key, Json::Object& put_into) { Json::Object value; - const auto errors_count = r.error_count(); + const auto errors_count = r.errors(); if (r.optional_object_field(obj, key, value, DictionaryDeserializer::instance)) { - if (errors_count != r.error_count()) return; + if (errors_count != r.errors()) return; put_into.insert_or_replace(key, value); } }; @@ -849,25 +849,34 @@ namespace vcpkg Optional parse_configuration(const Json::Object& obj, StringView origin, MessageSink& messageSink) { - Json::Reader reader{origin}; + Json::Reader reader(origin); auto maybe_configuration = reader.visit(obj, get_configuration_deserializer()); - bool has_messages = !reader.messages().empty(); - if (has_messages) + bool has_warnings = !reader.warnings().empty(); + bool has_errors = !reader.errors().empty(); + if (has_warnings || has_errors) { - for (auto&& msg : reader.messages()) + if (has_errors) { - Color c; - switch (msg.kind) - { - case MessageKind::Error: c = Color::error; break; - case MessageKind::Warning: c = Color::warning; break; - default: Checks::unreachable(VCPKG_LINE_INFO); break; - } + messageSink.println(Color::error, msgFailedToParseConfig, msg::path = origin); + } + else + { + messageSink.println(Color::warning, msgWarnOnParseConfig, msg::path = origin); + } - messageSink.println(c, msg.message); + for (auto&& msg : reader.errors()) + { + messageSink.println(Color::error, LocalizedString().append_indent().append_raw(msg)); } - if (reader.error_count() != 0) return nullopt; + for (auto&& msg : reader.warnings()) + { + messageSink.println(Color::warning, LocalizedString().append_indent().append(msg)); + } + + msg::println(msgExtendedDocumentationAtUrl, msg::url = docs::registries_url); + + if (has_errors) return nullopt; } return maybe_configuration; } diff --git a/src/vcpkg/registries.cpp b/src/vcpkg/registries.cpp index 2a0f76370c..9f839fc1a3 100644 --- a/src/vcpkg/registries.cpp +++ b/src/vcpkg/registries.cpp @@ -1240,12 +1240,12 @@ namespace Json::Reader r(origin); Baseline result; r.visit_in_key(*baseline_value, real_baseline, result, BaselineDeserializer::instance); - if (r.error_count() == 0) + if (r.errors().empty()) { return std::move(result); } - return join(r.messages()); + return msg::format_error(msgFailedToParseBaseline, msg::path = origin).append_raw('\n').append_raw(r.join()); } ExpectedL load_baseline_versions(const ReadOnlyFilesystem& fs, @@ -1520,9 +1520,11 @@ namespace GitVersionDbEntryArrayDeserializer deserializer{}; Json::Reader r(versions_file_path); r.visit_in_key(*maybe_versions_array, JsonIdVersions, db_entries, deserializer); - if (r.error_count() != 0) + if (!r.errors().empty() != 0) { - return join(r.messages()); + return msg::format_error(msgFailedToParseVersionFile, msg::path = versions_file_path) + .append_raw('\n') + .append_raw(r.join()); } return db_entries; @@ -1556,9 +1558,11 @@ namespace FilesystemVersionDbEntryArrayDeserializer deserializer{registry_root}; Json::Reader r(versions_file_path); r.visit_in_key(*maybe_versions_array, JsonIdVersions, db_entries, deserializer); - if (r.error_count() != 0) + if (!r.errors().empty() != 0) { - return join(r.messages()); + return msg::format_error(msgFailedToParseVersionFile, msg::path = versions_file_path) + .append_raw('\n') + .append_raw(r.join()); } return db_entries; diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 1daaa2ad12..10ed210821 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -1301,13 +1301,34 @@ namespace vcpkg Json::Reader reader(origin); auto res = reader.visit(manifest, ManifestConfigurationDeserializer::instance); - LocalizedString flat_errors = flatten_reader_messages(reader.messages(), warningsSink); - if (flat_errors.empty()) + if (!reader.warnings().empty()) { - return std::move(res).value_or_exit(VCPKG_LINE_INFO); + warningsSink.println(Color::warning, msgWarnOnParseConfig, msg::path = origin); + for (auto&& warning : reader.warnings()) + { + warningsSink.println(Color::warning, LocalizedString::from_raw(warning)); + } + warningsSink.println(Color::warning, msgExtendedDocumentationAtUrl, msg::url = docs::registries_url); + warningsSink.println(Color::warning, msgExtendedDocumentationAtUrl, msg::url = docs::manifests_url); + } + + if (!reader.errors().empty()) + { + LocalizedString ret; + ret.append(msgFailedToParseConfig, msg::path = origin); + ret.append_raw('\n'); + for (auto&& err : reader.errors()) + { + ret.append_indent().append(err).append_raw("\n"); + } + ret.append(msgExtendedDocumentationAtUrl, msg::url = docs::registries_url); + ret.append_raw('\n'); + ret.append(msgExtendedDocumentationAtUrl, msg::url = docs::manifests_url); + ret.append_raw('\n'); + return std::move(ret); } - return flat_errors; + return std::move(res).value_or_exit(VCPKG_LINE_INFO); } SourceControlFile SourceControlFile::clone() const @@ -1329,18 +1350,41 @@ namespace vcpkg Json::Reader reader(control_path); auto res = reader.visit(manifest, ManifestDeserializerType::instance); - LocalizedString flat_errors = flatten_reader_messages(reader.messages(), warnings_sink); - if (flat_errors.empty()) + + for (auto&& w : reader.warnings()) { - if (auto p = res.get()) + warnings_sink.println(Color::warning, w); + } + + switch (reader.errors().size()) + { + case 0: + if (auto p = res.get()) + { + return std::move(*p); + } + else + { + Checks::unreachable(VCPKG_LINE_INFO); + } + case 1: return reader.errors()[0]; + default: { - return std::move(*p); - } + LocalizedString result; + auto first = reader.errors().begin(); + const auto last = reader.errors().end(); + for (;;) + { + result.append(*first); + if (++first == last) + { + return result; + } - Checks::unreachable(VCPKG_LINE_INFO); + result.append_raw('\n'); + } + } } - - return flat_errors; } ExpectedL> SourceControlFile::parse_project_manifest_object( From 3d2f9b0d60322c4b95d4bee2d63458317425d976 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Fri, 7 Jun 2024 13:00:05 -0700 Subject: [PATCH 48/48] Remove unused messages. --- include/vcpkg/base/message-data.inc.h | 5 ----- locales/messages.json | 9 --------- 2 files changed, 14 deletions(-) diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index 1af885eac2..b60e02fbb7 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -102,7 +102,6 @@ DECLARE_MESSAGE( "actually semantic parts do not apply.\n" "If versions for this port are not ordered by these rules, disable this check by rerunning this command and adding " "--skip-version-format-check .") -DECLARE_MESSAGE(AddVersionUnableToParseVersionsFile, (msg::path), "", "unable to parse versions file {path}") DECLARE_MESSAGE(AddVersionUncommittedChanges, (msg::package_name), "", @@ -441,7 +440,6 @@ DECLARE_MESSAGE(CiBaselineUnexpectedPass, (msg::spec, msg::path), "", "PASSING, REMOVE FROM FAIL LIST: {spec} ({path}).") -DECLARE_MESSAGE(CISettingsExclude, (), "", "Comma-separated list of ports to skip") DECLARE_MESSAGE(CISettingsOptCIBase, (), "", @@ -1220,8 +1218,6 @@ DECLARE_MESSAGE(FailedToParseCMakeConsoleOut, "Failed to parse CMake console output to locate block start/end markers.") DECLARE_MESSAGE(FailedToParseBaseline, (msg::path), "", "Failed to parse baseline: {path}") DECLARE_MESSAGE(FailedToParseConfig, (msg::path), "", "Failed to parse configuration: {path}") -DECLARE_MESSAGE(FailedToParseControl, (msg::path), "", "Failed to parse CONTROL file: {path}") -DECLARE_MESSAGE(FailedToParseManifest, (msg::path), "", "Failed to parse manifest file: {path}") DECLARE_MESSAGE(FailedToParseVersionFile, (msg::path), "", "Failed to parse version file: {path}") DECLARE_MESSAGE(FailedToParseNoTopLevelObj, (msg::path), "", "Failed to parse {path}, expected a top-level object.") DECLARE_MESSAGE(FailedToParseNoVersionsArray, (msg::path), "", "Failed to parse {path}, expected a 'versions' array.") @@ -1235,7 +1231,6 @@ DECLARE_MESSAGE(FailedToParseVersionXML, (msg::tool_name, msg::version), "", "Could not parse version for tool {tool_name}. Version string was: {version}") -DECLARE_MESSAGE(FailedToReadParagraph, (msg::path), "", "Failed to read paragraphs from {path}") DECLARE_MESSAGE(FailedToRunToolToDetermineVersion, (msg::tool_name, msg::path), "Additional information, such as the command line output, if any, will be appended on " diff --git a/locales/messages.json b/locales/messages.json index 7d873261c8..7a87c6eb74 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -93,8 +93,6 @@ "_AddVersionSuggestVersionDate.comment": "\"version-string\" and \"version-date\" are JSON keys, and --skip-version-format-check is a command line switch. They should not be translated An example of {package_name} is zlib.", "AddVersionSuggestVersionRelaxed": "The version format of \"{package_name}\" uses \"version-string\", but the format is acceptable as a \"version\". If the versions for this port are orderable using relaxed-version rules, change the format to \"version\", and rerun this command. Relaxed-version rules order versions by each numeric component. Then, versions with dash suffixes are sorted lexcographically before. Plus'd build tags are ignored. Examples:\n1.0 < 1.1-alpha < 1.1-b < 1.1 < 1.1.1 < 1.2+build = 1.2 < 2.0\nNote in particular that dashed suffixes sort *before*, not after. 1.0-anything < 1.0\nNote that this sort order is the same as chosen in Semantic Versioning (see https://semver.org), even though the actually semantic parts do not apply.\nIf versions for this port are not ordered by these rules, disable this check by rerunning this command and adding --skip-version-format-check .", "_AddVersionSuggestVersionRelaxed.comment": "\"version-string\" and \"version\" are JSON keys, and --skip-version-format-check is a command line switch. They should not be translated An example of {package_name} is zlib.", - "AddVersionUnableToParseVersionsFile": "unable to parse versions file {path}", - "_AddVersionUnableToParseVersionsFile.comment": "An example of {path} is /foo/bar.", "AddVersionUncommittedChanges": "there are uncommitted changes for {package_name}", "_AddVersionUncommittedChanges.comment": "An example of {package_name} is zlib.", "AddVersionUpdateVersionReminder": "Did you remember to update the version or port version?", @@ -238,7 +236,6 @@ "_BuildingPackageFailedDueToMissingDeps.comment": "Printed after BuildingPackageFailed, and followed by a list of dependencies that were missing.", "BuiltInTriplets": "Built-in Triplets:", "BuiltWithIncorrectArchitecture": "The following files were built for an incorrect architecture:", - "CISettingsExclude": "Comma-separated list of ports to skip", "CISettingsOptCIBase": "Path to the ci.baseline.txt file. Used to skip ports and detect regressions.", "CISettingsOptExclude": "Comma separated list of ports to skip", "CISettingsOptFailureLogs": "Directory to which failure logs will be copied", @@ -741,10 +738,6 @@ "FailedToParseCMakeConsoleOut": "Failed to parse CMake console output to locate block start/end markers.", "FailedToParseConfig": "Failed to parse configuration: {path}", "_FailedToParseConfig.comment": "An example of {path} is /foo/bar.", - "FailedToParseControl": "Failed to parse CONTROL file: {path}", - "_FailedToParseControl.comment": "An example of {path} is /foo/bar.", - "FailedToParseManifest": "Failed to parse manifest file: {path}", - "_FailedToParseManifest.comment": "An example of {path} is /foo/bar.", "FailedToParseNoTopLevelObj": "Failed to parse {path}, expected a top-level object.", "_FailedToParseNoTopLevelObj.comment": "An example of {path} is /foo/bar.", "FailedToParseNoVersionsArray": "Failed to parse {path}, expected a 'versions' array.", @@ -755,8 +748,6 @@ "_FailedToParseVersionFile.comment": "An example of {path} is /foo/bar.", "FailedToParseVersionXML": "Could not parse version for tool {tool_name}. Version string was: {version}", "_FailedToParseVersionXML.comment": "An example of {tool_name} is aria2. An example of {version} is 1.3.8.", - "FailedToReadParagraph": "Failed to read paragraphs from {path}", - "_FailedToReadParagraph.comment": "An example of {path} is /foo/bar.", "FailedToRunToolToDetermineVersion": "Failed to run \"{path}\" to determine the {tool_name} version.", "_FailedToRunToolToDetermineVersion.comment": "Additional information, such as the command line output, if any, will be appended on the line after this message An example of {tool_name} is aria2. An example of {path} is /foo/bar.", "FailedToStoreBackToMirror": "failed to store back to mirror:",