diff --git a/include/vcpkg/base/format.h b/include/vcpkg/base/format.h index b64554785d..d597769293 100644 --- a/include/vcpkg/base/format.h +++ b/include/vcpkg/base/format.h @@ -29,8 +29,8 @@ namespace vcpkg namespace fmt { - template - struct formatter + template<> + struct formatter { constexpr auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) { @@ -43,13 +43,27 @@ namespace fmt } }; - template - struct formatter : formatter + template<> + struct formatter : formatter { template auto format(vcpkg::StringView sv, FormatContext& ctx) const -> decltype(ctx.out()) { - return formatter::format(string_view(sv.data(), sv.size()), ctx); + return formatter::format(string_view(sv.data(), sv.size()), ctx); + } + }; + + template<> + struct formatter : formatter + { + constexpr auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) + { + return vcpkg::basic_format_parse_impl(ctx); + } + template + auto format(const std::error_code& ec, FormatContext& ctx) const -> decltype(ctx.out()) + { + return formatter::format(ec.message(), ctx); } }; } diff --git a/include/vcpkg/base/messages.h b/include/vcpkg/base/messages.h index 9f9a7713ae..f22ae5886b 100644 --- a/include/vcpkg/base/messages.h +++ b/include/vcpkg/base/messages.h @@ -248,6 +248,7 @@ namespace vcpkg::msg DECLARE_MSG_ARG(count, "42"); DECLARE_MSG_ARG(elapsed, "3.532 min"); DECLARE_MSG_ARG(email, "vcpkg@microsoft.com"); + DECLARE_MSG_ARG(error_msg, "File Not Found"); DECLARE_MSG_ARG(exit_code, "127"); DECLARE_MSG_ARG(expected_version, "1.3.8"); DECLARE_MSG_ARG(new_scheme, "version"); @@ -305,12 +306,20 @@ namespace vcpkg::msg "", "error: cannot specify both --no-{option} and --{option}."); + inline void print_warning(const LocalizedString& s) + { + print(Color::warning, format(msgErrorMessage).append(s).appendnl()); + } template void print_warning(Message m, Ts... args) { print(Color::warning, format(msgWarningMessage).append(format(m, args...).appendnl())); } + inline void print_error(const LocalizedString& s) + { + print(Color::error, format(msgErrorMessage).append(s).appendnl()); + } template void print_error(Message m, Ts... args) { diff --git a/locales/messages.en.json b/locales/messages.en.json index 31f6b20c25..1ca654fba4 100644 --- a/locales/messages.en.json +++ b/locales/messages.en.json @@ -51,6 +51,7 @@ "ExpectedPortName": "expected a port name here", "ExpectedTripletName": "expected a triplet name here", "FailedToProvisionCe": "Failed to provision vcpkg-ce.", + "FailedToStoreBackToMirror": "failed to store back to mirror:", "ForceSystemBinariesOnWeirdPlatforms": "Environment variable VCPKG_FORCE_SYSTEM_BINARIES must be set on arm, s390x, and ppc64le platforms.", "FormattedParseMessageExpression": " on expression: {value}", "GenerateMsgErrorParsingFormatArgs": "error: parsing format string for {value}:", @@ -63,6 +64,8 @@ "IllegalPlatformSpec": "error: Platform qualifier is not allowed in this context", "InternalErrorMessage": "internal error: ", "InternalErrorMessageContact": "Please open an issue at https://github.com/microsoft/vcpkg/issues/new?template=other-type-of-bug-report.md&labels=category:vcpkg-bug with detailed steps to reproduce the problem.", + "JsonErrorFailedToParse": "failed to parse {path}:", + "JsonErrorFailedToRead": "failed to read {path}: {error_msg}", "LicenseExpressionContainsExtraPlus": "SPDX license expression contains an extra '+'. These are only allowed directly after a license identifier.", "LicenseExpressionContainsInvalidCharacter": "SPDX license expression contains an invalid character (0x{value:02X} '{value}').", "LicenseExpressionContainsUnicode": "SPDX license expression contains a unicode character (U+{value:04X} '{pretty_value}'), but these expressions are ASCII-only.", @@ -91,6 +94,7 @@ "ResultsHeader": "RESULTS", "SeeURL": "See {url} for more information.", "SuggestNewVersionScheme": "Use the version scheme \"{new_scheme}\" instead of \"{old_scheme}\" in port \"{package_name}\".\nUse `--{option}` to disable this check.", + "UnexpectedErrorDuringBulkDownload": "an unexpected error occurred during bulk download.", "UnknownBaselineFileContent": "unrecognizable baseline entry; expected 'port:triplet=(fail|skip)'", "UnsupportedSystemName": "Error: Could not map VCPKG_CMAKE_SYSTEM_NAME '{system_name}' to a vcvarsall platform. Supported system names are '', 'Windows' and 'WindowsStore'.", "UnsupportedToolchain": "Error: in triplet {triplet}: Unable to find a valid toolchain combination.\n The requested target architecture was {arch}\n The selected Visual Studio instance is at {path}\n The available toolchain combinations are {list}\n", @@ -110,6 +114,8 @@ "VersionInvalidRelaxed": "`{version}` is not a valid relaxed version (semver with arbitrary numeric element count).", "VersionInvalidSemver": "`{version}` is not a valid semantic version, consult .", "VersionSpecMismatch": "error: Failed to load port because version specs did not match\n Path: {path}\n Expected: {expected_version}\n Actual: {actual_version}", + "WaitingForChildrenToExit": "Waiting for child processes to exit...", + "WaitingToTakeFilesystemLock": "waiting to take filesystem lock on {path}...", "WarningMessage": "warning: ", "WarningsTreatedAsErrors": "previous warnings being interpreted as errors" } diff --git a/locales/messages.json b/locales/messages.json index b4377f6024..ddbcf559c7 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -88,6 +88,7 @@ "ExpectedPortName": "expected a port name here", "ExpectedTripletName": "expected a triplet name here", "FailedToProvisionCe": "Failed to provision vcpkg-ce.", + "FailedToStoreBackToMirror": "failed to store back to mirror:", "ForceSystemBinariesOnWeirdPlatforms": "Environment variable VCPKG_FORCE_SYSTEM_BINARIES must be set on arm, s390x, and ppc64le platforms.", "FormattedParseMessageExpression": " on expression: {value}", "_FormattedParseMessageExpression.comment": "Example of {value} is 'x64 & windows'\n", @@ -107,6 +108,10 @@ "IllegalPlatformSpec": "error: Platform qualifier is not allowed in this context", "InternalErrorMessage": "internal error: ", "InternalErrorMessageContact": "Please open an issue at https://github.com/microsoft/vcpkg/issues/new?template=other-type-of-bug-report.md&labels=category:vcpkg-bug with detailed steps to reproduce the problem.", + "JsonErrorFailedToParse": "failed to parse {path}:", + "_JsonErrorFailedToParse.comment": "example of {path} is '/foo/bar'.\n", + "JsonErrorFailedToRead": "failed to read {path}: {error_msg}", + "_JsonErrorFailedToRead.comment": "example of {path} is '/foo/bar'.\nexample of {error_msg} is 'File Not Found'.\n", "LicenseExpressionContainsExtraPlus": "SPDX license expression contains an extra '+'. These are only allowed directly after a license identifier.", "LicenseExpressionContainsInvalidCharacter": "SPDX license expression contains an invalid character (0x{value:02X} '{value}').", "_LicenseExpressionContainsInvalidCharacter.comment": "example of {value:02X} is '7B'\nexample of {value} is '{'\n", @@ -152,6 +157,7 @@ "_SeeURL.comment": "example of {url} is 'https://github.com/microsoft/vcpkg'.\n", "SuggestNewVersionScheme": "Use the version scheme \"{new_scheme}\" instead of \"{old_scheme}\" in port \"{package_name}\".\nUse `--{option}` to disable this check.", "_SuggestNewVersionScheme.comment": "example of {new_scheme} is 'version'.\nexample of {old_scheme} is 'version-string'.\nexample of {package_name} is 'zlib'.\nexample of {option} is 'editable'.\n", + "UnexpectedErrorDuringBulkDownload": "an unexpected error occurred during bulk download.", "UnknownBaselineFileContent": "unrecognizable baseline entry; expected 'port:triplet=(fail|skip)'", "UnsupportedSystemName": "Error: Could not map VCPKG_CMAKE_SYSTEM_NAME '{system_name}' to a vcvarsall platform. Supported system names are '', 'Windows' and 'WindowsStore'.", "_UnsupportedSystemName.comment": "example of {system_name} is 'Darwin'.\n", @@ -182,6 +188,9 @@ "_VersionInvalidSemver.comment": "example of {version} is '1.3.8'.\n", "VersionSpecMismatch": "error: Failed to load port because version specs did not match\n Path: {path}\n Expected: {expected_version}\n Actual: {actual_version}", "_VersionSpecMismatch.comment": "example of {path} is '/foo/bar'.\nexample of {expected_version} is '1.3.8'.\nexample of {actual_version} is '1.3.8'.\n", + "WaitingForChildrenToExit": "Waiting for child processes to exit...", + "WaitingToTakeFilesystemLock": "waiting to take filesystem lock on {path}...", + "_WaitingToTakeFilesystemLock.comment": "example of {path} is '/foo/bar'.\n", "WarningMessage": "warning: ", "WarningsTreatedAsErrors": "previous warnings being interpreted as errors" } diff --git a/src/vcpkg-fuzz/main.cpp b/src/vcpkg-fuzz/main.cpp index 3cd9cac527..1168a8cc26 100644 --- a/src/vcpkg-fuzz/main.cpp +++ b/src/vcpkg-fuzz/main.cpp @@ -1,7 +1,7 @@ #include #include +#include #include -#include #include #include @@ -16,6 +16,18 @@ using namespace vcpkg; namespace { + DECLARE_AND_REGISTER_MESSAGE(FuzzInvalidKind, (msg::value), "example of {value} is 'utf-8'", "invalid kind: {}"); + DECLARE_AND_REGISTER_MESSAGE(FuzzExpectedOneOf, + (), + "the list after the colon should stay the same, they're literal values", + "expected one of: utf-8, json, platform-expr"); + DECLARE_AND_REGISTER_MESSAGE(FuzzUnknownOption, (msg::option), "", "unknown option: --{option}"); + + DECLARE_AND_REGISTER_MESSAGE(FuzzHelpUsage, (), "", "usage: vcpkg-fuzz --kind="); + DECLARE_AND_REGISTER_MESSAGE(FuzzHelpInput, (), "", "accepts input on stdin."); + DECLARE_AND_REGISTER_MESSAGE(FuzzHelpOptions, (), "", "options:"); + DECLARE_AND_REGISTER_MESSAGE(FuzzHelpOptionKind, (), "", "one of {{utf-8, json, platform-expr}}"); + enum class FuzzKind { None, @@ -68,14 +80,16 @@ namespace } else { - print2(Color::error, "Invalid kind: ", value, "\n"); - print2(Color::error, " Expected one of: utf-8, json, platform-expr\n\n"); + msg::print_error(msg::format(msgFuzzInvalidKind, msg::value = value) + .appendnl() + .append_indent() + .append(msgFuzzExpectedOneOf)); print_help_and_exit(true); } } else { - print2("Unknown option: ", key, "\n\n"); + msg::print_error(msgFuzzUnknownOption, msg::option = key); print_help_and_exit(true); } } @@ -99,19 +113,30 @@ namespace [[noreturn]] void print_help_and_exit(bool invalid = false) { - constexpr auto help = - R"( -Usage: vcpkg-fuzz + auto color = invalid ? Color::error : Color::none; -Accepts input on stdin. + auto message = msg::format(msgFuzzHelpUsage).appendnl().appendnl(); + message.append(msgFuzzHelpInput).appendnl().appendnl(); + message.append(msgFuzzHelpOptions).appendnl(); -Options: - --kind=... One of {utf-8, json} -)"; + struct + { + StringLiteral option; + LocalizedString help; + } options[] = { + {"kind", msg::format(msgFuzzHelpOptionKind)}, + }; - auto color = invalid ? Color::error : Color::success; + for (const auto& option : options) + { + auto start_option = fmt::format(" --{}=...", option.option); + message.append_raw(start_option) + .append_raw(std::string(30 - start_option.size(), ' ')) + .append(option.help) + .appendnl(); + } - print2(color, help); + msg::print(color, message); if (invalid) { Checks::exit_fail(VCPKG_LINE_INFO); @@ -176,6 +201,8 @@ Accepts input on stdin. int main(int argc, char** argv) { + msg::threadunsafe_initialize_context(); + auto args = FuzzArgs(argc, argv); if (args.kind == FuzzKind::None) diff --git a/src/vcpkg-test/manifests.cpp b/src/vcpkg-test/manifests.cpp index 01054df382..d0a2859693 100644 --- a/src/vcpkg-test/manifests.cpp +++ b/src/vcpkg-test/manifests.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include @@ -25,8 +24,10 @@ static Json::Object parse_json_object(StringView sv) } else { - vcpkg::print2("Error found while parsing JSON document:\n", sv, '\n'); - Checks::exit_with_message(VCPKG_LINE_INFO, json.error()->format()); + INFO("Error found while parsing JSON document:"); + INFO(sv.to_string()); + FAIL(json.error()->format()); + return Json::Object{}; } } diff --git a/src/vcpkg-test/specifier.cpp b/src/vcpkg-test/specifier.cpp index d39429a485..7958b08308 100644 --- a/src/vcpkg-test/specifier.cpp +++ b/src/vcpkg-test/specifier.cpp @@ -1,6 +1,5 @@ #include -#include #include #include @@ -86,11 +85,7 @@ TEST_CASE ("specifier parsing", "[specifier]") SECTION ("parsed specifier wildcard feature") { - auto maybe_spec = vcpkg::parse_qualified_specifier("zlib[*]"); - print2(maybe_spec.error()); - REQUIRE(maybe_spec); - - auto& spec = *maybe_spec.get(); + auto spec = Test::unwrap(vcpkg::parse_qualified_specifier("zlib[*]")); REQUIRE(spec.features.value_or(std::vector{}) == std::vector{"*"}); } diff --git a/src/vcpkg/base/checks.cpp b/src/vcpkg/base/checks.cpp index 21d43da877..fc28d91a2d 100644 --- a/src/vcpkg/base/checks.cpp +++ b/src/vcpkg/base/checks.cpp @@ -1,7 +1,7 @@ #include +#include #include #include -#include #include @@ -78,7 +78,8 @@ namespace vcpkg [[noreturn]] void Checks::exit_with_message(const LineInfo& line_info, StringView error_message) { - print2(Color::error, error_message, '\n'); + msg::write_unlocalized_text_to_stdout(Color::error, error_message); + msg::write_unlocalized_text_to_stdout(Color::error, "\n"); exit_fail(line_info); } [[noreturn]] void Checks::msg_exit_with_message(const LineInfo& line_info, const LocalizedString& error_message) @@ -89,8 +90,7 @@ namespace vcpkg [[noreturn]] void Checks::exit_with_message_and_line(const LineInfo& line_info, StringView error_message) { - msg::print(Color::error, locale_invariant_lineinfo(line_info)); - print2(Color::error, error_message, '\n'); + msg::println(Color::error, locale_invariant_lineinfo(line_info).append_raw(error_message)); exit_fail(line_info); } @@ -137,7 +137,8 @@ namespace vcpkg [[noreturn]] void Checks::exit_maybe_upgrade(const LineInfo& line_info, StringView error_message) { - print2(Color::error, error_message, '\n'); + msg::write_unlocalized_text_to_stdout(Color::error, error_message); + msg::write_unlocalized_text_to_stdout(Color::error, "\n"); display_upgrade_message(); exit_fail(line_info); } diff --git a/src/vcpkg/base/downloads.cpp b/src/vcpkg/base/downloads.cpp index 46083d2ea1..26dfe0e929 100644 --- a/src/vcpkg/base/downloads.cpp +++ b/src/vcpkg/base/downloads.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -26,6 +25,11 @@ namespace "=== curl output ===\n" "{actual}\n" "=== end curl output ===\n"); + DECLARE_AND_REGISTER_MESSAGE(UnexpectedErrorDuringBulkDownload, + (), + "", + "an unexpected error occurred during bulk download."); + DECLARE_AND_REGISTER_MESSAGE(FailedToStoreBackToMirror, (), "", "failed to store back to mirror:"); } namespace vcpkg @@ -372,7 +376,7 @@ namespace vcpkg if (start_size + url_pairs.size() > out->size()) { // curl stopped before finishing all downloads; retry after some time - print2(Color::warning, "Warning: an unexpected error occurred during bulk download.\n"); + msg::print_warning(msgUnexpectedErrorDuringBulkDownload); std::this_thread::sleep_for(std::chrono::milliseconds(i)); url_pairs = View>{url_pairs.begin() + out->size() - start_size, url_pairs.end()}; @@ -731,7 +735,8 @@ namespace vcpkg auto maybe_push = put_file_to_mirror(fs, download_path, *hash); if (!maybe_push.has_value()) { - print2(Color::warning, "Warning: failed to store back to mirror:\n", maybe_push.error()); + msg::print_warning(msgFailedToStoreBackToMirror); + msg::write_unlocalized_text_to_stdout(Color::warning, maybe_push.error()); } } return *url; diff --git a/src/vcpkg/base/files.cpp b/src/vcpkg/base/files.cpp index af27bf050c..944af8739b 100644 --- a/src/vcpkg/base/files.cpp +++ b/src/vcpkg/base/files.cpp @@ -1,9 +1,9 @@ #include #include +#include #include #include -#include #include #include @@ -40,6 +40,11 @@ namespace { using namespace vcpkg; + DECLARE_AND_REGISTER_MESSAGE(WaitingToTakeFilesystemLock, + (msg::path), + "", + "waiting to take filesystem lock on {path}..."); + std::atomic g_us_filesystem_stats(0); struct IsSlash @@ -3224,7 +3229,7 @@ namespace vcpkg auto result = std::make_unique(lockfile, ec); if (!ec && !result->lock_attempt(ec) && !ec) { - vcpkg::printf("Waiting to take filesystem lock on %s...\n", lockfile); + msg::println(msgWaitingToTakeFilesystemLock, msg::path = lockfile); do { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); @@ -3240,7 +3245,7 @@ namespace vcpkg auto result = std::make_unique(lockfile, ec); if (!ec && !result->lock_attempt(ec) && !ec) { - Debug::print("Waiting to take filesystem lock on ", lockfile, "...\n"); + Debug::println(msg::format(msgWaitingToTakeFilesystemLock, msg::path = lockfile)); // waits, at most, a second and a half. for (auto wait = std::chrono::milliseconds(100);;) { @@ -3320,7 +3325,7 @@ namespace vcpkg Strings::append(message, " ", p.generic_u8string(), '\n'); } message.push_back('\n'); - print2(message); + msg::write_unlocalized_text_to_stdout(Color::none, message); } uint64_t get_filesystem_stats() { return g_us_filesystem_stats.load(); } diff --git a/src/vcpkg/base/json.cpp b/src/vcpkg/base/json.cpp index 450e120159..e3167b8ae6 100644 --- a/src/vcpkg/base/json.cpp +++ b/src/vcpkg/base/json.cpp @@ -1,14 +1,24 @@ #include #include #include +#include #include -#include #include #include #include +namespace +{ + using namespace vcpkg; + DECLARE_AND_REGISTER_MESSAGE(JsonErrorFailedToRead, + (msg::path, msg::error_msg), + "", + "failed to read {path}: {error_msg}"); + DECLARE_AND_REGISTER_MESSAGE(JsonErrorFailedToParse, (msg::path), "", "failed to parse {path}:"); +} + namespace vcpkg::Json { static std::atomic g_json_parsing_stats(0); @@ -1087,13 +1097,14 @@ namespace vcpkg::Json auto ret = parse_file(fs, json_file, ec); if (ec) { - print2(Color::error, "Failed to read ", json_file, ": ", ec.message(), "\n"); + msg::print_error(msgJsonErrorFailedToRead, msg::path = json_file, msg::error_msg = ec); Checks::exit_fail(li); } else if (!ret) { - print2(Color::error, "Failed to parse ", json_file, ":\n"); - print2(ret.error()->format()); + msg::print_error(msgJsonErrorFailedToParse, msg::path = json_file); + msg::write_unlocalized_text_to_stdout(Color::error, ret.error()->format()); + msg::println(); Checks::exit_fail(li); } return ret.value_or_exit(li); diff --git a/src/vcpkg/base/parse.cpp b/src/vcpkg/base/parse.cpp index 17bb5e5b2e..dc9139b5df 100644 --- a/src/vcpkg/base/parse.cpp +++ b/src/vcpkg/base/parse.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include diff --git a/src/vcpkg/base/system.process.cpp b/src/vcpkg/base/system.process.cpp index 559c61ce3a..182d44ab2c 100644 --- a/src/vcpkg/base/system.process.cpp +++ b/src/vcpkg/base/system.process.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -25,6 +24,11 @@ #pragma comment(lib, "Advapi32") #endif +namespace +{ + DECLARE_AND_REGISTER_MESSAGE(WaitingForChildrenToExit, (), "", "Waiting for child processes to exit..."); +} + namespace vcpkg { void append_shell_escaped(std::string& target, StringView content) @@ -95,7 +99,7 @@ namespace vcpkg while (true) { std::this_thread::sleep_for(std::chrono::seconds(10)); - print2("Waiting for child processes to exit...\n"); + msg::println(msgWaitingForChildrenToExit); } } } @@ -118,7 +122,7 @@ namespace vcpkg while (true) { std::this_thread::sleep_for(std::chrono::seconds(10)); - print2("Waiting for child processes to exit...\n"); + msg::println(msgWaitingForChildrenToExit); } } } @@ -900,7 +904,7 @@ namespace vcpkg Strings::append(output, sv); if (echo_in_debug == EchoInDebug::Show && Debug::g_debugging) { - print2(sv); + msg::write_unlocalized_text_to_stdout(Color::none, sv); } }, wd,