From d010c81b132d2d40e6f72adb49bcfe5a4d1ac353 Mon Sep 17 00:00:00 2001 From: Olaf Date: Mon, 8 May 2017 11:45:01 +0200 Subject: List packages for vcpkg install --- toolsrc/src/commands_update.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp index e39c7dd35..f87ccfb06 100644 --- a/toolsrc/src/commands_update.cpp +++ b/toolsrc/src/commands_update.cpp @@ -56,15 +56,18 @@ namespace vcpkg::Commands::Update } else { + std::string install_line; System::println("The following packages differ from their port versions:"); for (auto&& package : outdated_packages) { + install_line += package.spec.to_string(); + install_line += " "; System::println(" %-32s %s", package.spec, package.version_diff.to_string()); } System::println("\n" "To update these packages, run\n" " .\\vcpkg remove --outdated\n" - " .\\vcpkg install ..."); + " .\\vcpkg install " + install_line); } auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt"); -- cgit v1.2.3 From c0be6aecc6c817e556e6bfd1251842615023644e Mon Sep 17 00:00:00 2001 From: Jon Erickson Date: Tue, 16 May 2017 21:10:00 -0400 Subject: Added '--full-desc' option to search and list commands to shows full description for packages. --- toolsrc/src/commands_list.cpp | 28 ++++++++++++++++++++-------- toolsrc/src/commands_search.cpp | 28 ++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 16 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp index 6451ac5eb..521fc5a9a 100644 --- a/toolsrc/src/commands_list.cpp +++ b/toolsrc/src/commands_list.cpp @@ -7,12 +7,24 @@ namespace vcpkg::Commands::List { - static void do_print(const StatusParagraph& pgh) + static const std::string OPTION_FULLDESC = "--full-desc"; // TODO: This should find a better home, eventually + + static void do_print(const StatusParagraph& pgh, bool FullDesc) { - System::println("%-27s %-16s %s", - pgh.package.displayname(), - pgh.package.version, - details::shorten_description(pgh.package.description)); + if (FullDesc) + { + System::println("%-27s %-16s %s", + pgh.package.displayname(), + pgh.package.version, + pgh.package.description); + } + else + { + System::println("%-27s %-16s %s", + pgh.package.displayname(), + pgh.package.version, + details::shorten_description(pgh.package.description)); + } } void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) @@ -21,7 +33,7 @@ namespace vcpkg::Commands::List "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", Commands::Help::create_example_string("list png")); args.check_max_arg_count(1, example); - args.check_and_get_optional_command_arguments({}); + const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_FULLDESC}); const StatusParagraphs status_paragraphs = database_load_check(paths); std::vector installed_packages = get_installed_ports(status_paragraphs); @@ -42,7 +54,7 @@ namespace vcpkg::Commands::List { for (const StatusParagraph* status_paragraph : installed_packages) { - do_print(*status_paragraph); + do_print(*status_paragraph, options.find(OPTION_FULLDESC) != options.cend()); } } else @@ -56,7 +68,7 @@ namespace vcpkg::Commands::List continue; } - do_print(*status_paragraph); + do_print(*status_paragraph, options.find(OPTION_FULLDESC) != options.cend()); } } diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index 0ba7305e9..6ec2a5395 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -9,6 +9,8 @@ namespace vcpkg::Commands::Search { static const std::string OPTION_GRAPH = "--graph"; // TODO: This should find a better home, eventually + static const std::string OPTION_FULLDESC = "--full-desc"; // TODO: This should find a better home, eventually + static std::string replace_dashes_with_underscore(const std::string& input) { @@ -45,12 +47,22 @@ namespace vcpkg::Commands::Search return s; } - static void do_print(const SourceParagraph& source_paragraph) + static void do_print(const SourceParagraph& source_paragraph, bool FullDesc) { - System::println("%-20s %-16s %s", - source_paragraph.name, - source_paragraph.version, - details::shorten_description(source_paragraph.description)); + if (FullDesc) + { + System::println("%-20s %-16s %s", + source_paragraph.name, + source_paragraph.version, + source_paragraph.description); + } + else + { + System::println("%-20s %-16s %s", + source_paragraph.name, + source_paragraph.version, + details::shorten_description(source_paragraph.description)); + } } void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) @@ -59,7 +71,7 @@ namespace vcpkg::Commands::Search "The argument should be a substring to search for, or no argument to display all libraries.\n%s", Commands::Help::create_example_string("search png")); args.check_max_arg_count(1, example); - const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_GRAPH}); + const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC}); const std::vector source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); @@ -74,7 +86,7 @@ namespace vcpkg::Commands::Search { for (const SourceParagraph& source_paragraph : source_paragraphs) { - do_print(source_paragraph); + do_print(source_paragraph, options.find(OPTION_FULLDESC) != options.cend()); } } else @@ -88,7 +100,7 @@ namespace vcpkg::Commands::Search continue; } - do_print(source_paragraph); + do_print(source_paragraph, options.find(OPTION_FULLDESC) != options.cend()); } } -- cgit v1.2.3 From 621d2f852d43b5766bbf13bd22591524a083e48e Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Mon, 22 May 2017 15:41:02 -0700 Subject: [vcpkg-search] added search in description --- toolsrc/src/commands_search.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index 0ba7305e9..739aa0f43 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -85,7 +85,11 @@ namespace vcpkg::Commands::Search if (Strings::case_insensitive_ascii_find(source_paragraph.name, args.command_arguments[0]) == source_paragraph.name.end()) { - continue; + if (Strings::case_insensitive_ascii_find(source_paragraph.description, args.command_arguments[0]) == + source_paragraph.description.end()) + { + continue; + } } do_print(source_paragraph); -- cgit v1.2.3 From 3dd8bde9bdb46e3c501db5a123cb1431c701f2a1 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Mon, 22 May 2017 21:30:50 -0500 Subject: Adding policy ALLOW_OBSOLETE_MSVCRT suppressing dependency check for msvcrt.dll --- toolsrc/src/PostBuildLint.cpp | 60 ++++++++++++++++------------- toolsrc/src/PostBuildLint_BuildPolicies.cpp | 9 +++++ 2 files changed, 42 insertions(+), 27 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 0d2f556c1..a8365e109 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -37,30 +37,6 @@ namespace vcpkg::PostBuildLint } }; - const std::vector& get_outdated_dynamic_crts() - { - static const std::vector v = {{"msvcp100.dll", R"(msvcp100\.dll)"}, - {"msvcp100d.dll", R"(msvcp100d\.dll)"}, - {"msvcp110.dll", R"(msvcp110\.dll)"}, - {"msvcp110_win.dll", R"(msvcp110_win\.dll)"}, - {"msvcp120.dll", R"(msvcp120\.dll)"}, - {"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"}, - {"msvcp60.dll", R"(msvcp60\.dll)"}, - {"msvcp60.dll", R"(msvcp60\.dll)"}, - - {"msvcr100.dll", R"(msvcr100\.dll)"}, - {"msvcr100d.dll", R"(msvcr100d\.dll)"}, - {"msvcr100_clr0400.dll", R"(msvcr100_clr0400\.dll)"}, - {"msvcr110.dll", R"(msvcr110\.dll)"}, - {"msvcr120.dll", R"(msvcr120\.dll)"}, - {"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"}, - {"msvcrt.dll", R"(msvcrt\.dll)"}, - {"msvcrt20.dll", R"(msvcrt20\.dll)"}, - {"msvcrt40.dll", R"(msvcrt40\.dll)"}}; - - return v; - } - template static bool contains_and_enabled(const std::map map, const T& key) { @@ -70,6 +46,34 @@ namespace vcpkg::PostBuildLint return false; } + const std::vector& get_outdated_dynamic_crts(const std::map& policies) + { + static std::vector v = {{"msvcp100.dll", R"(msvcp100\.dll)"}, + {"msvcp100d.dll", R"(msvcp100d\.dll)"}, + {"msvcp110.dll", R"(msvcp110\.dll)"}, + {"msvcp110_win.dll", R"(msvcp110_win\.dll)"}, + {"msvcp120.dll", R"(msvcp120\.dll)"}, + {"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"}, + {"msvcp60.dll", R"(msvcp60\.dll)"}, + {"msvcp60.dll", R"(msvcp60\.dll)"}, + + {"msvcr100.dll", R"(msvcr100\.dll)"}, + {"msvcr100d.dll", R"(msvcr100d\.dll)"}, + {"msvcr100_clr0400.dll", R"(msvcr100_clr0400\.dll)"}, + {"msvcr110.dll", R"(msvcr110\.dll)"}, + {"msvcr120.dll", R"(msvcr120\.dll)"}, + {"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"}, + {"msvcrt20.dll", R"(msvcrt20\.dll)"}, + {"msvcrt40.dll", R"(msvcrt40\.dll)"}}; + + if (contains_and_enabled(policies, BuildPoliciesC::ALLOW_OBSOLETE_MSVCRT)) + { + v.push_back(OutdatedDynamicCrt{"msvcrt.dll", R"(msvcrt\.dll)"}); + } + + return v; + } + static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs, const std::map& policies, const fs::path& package_dir) @@ -656,9 +660,11 @@ namespace vcpkg::PostBuildLint OutdatedDynamicCrt_and_file() = delete; }; - static LintStatus check_outdated_crt_linkage_of_dlls(const std::vector& dlls, const fs::path dumpbin_exe) + static LintStatus check_outdated_crt_linkage_of_dlls(const std::vector& dlls, + const fs::path dumpbin_exe, + const BuildInfo& build_info) { - const std::vector& outdated_crts = get_outdated_dynamic_crts(); + const std::vector& outdated_crts = get_outdated_dynamic_crts(build_info.policies); std::vector dlls_with_outdated_crt; @@ -798,7 +804,7 @@ namespace vcpkg::PostBuildLint error_count += check_uwp_bit_of_dlls(pre_build_info.cmake_system_name, dlls, toolset.dumpbin); error_count += check_dll_architecture(pre_build_info.target_architecture, dlls); - error_count += check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin); + error_count += check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info); break; } case LinkageType::BackingEnum::STATIC: diff --git a/toolsrc/src/PostBuildLint_BuildPolicies.cpp b/toolsrc/src/PostBuildLint_BuildPolicies.cpp index 001ba31e7..d2189e20d 100644 --- a/toolsrc/src/PostBuildLint_BuildPolicies.cpp +++ b/toolsrc/src/PostBuildLint_BuildPolicies.cpp @@ -12,6 +12,7 @@ namespace vcpkg::PostBuildLint static const std::string NAME_DLLS_WITHOUT_LIBS = "PolicyDLLsWithoutLIBs"; static const std::string NAME_ONLY_RELEASE_CRT = "PolicyOnlyReleaseCRT"; static const std::string NAME_EMPTY_INCLUDE_FOLDER = "PolicyEmptyIncludeFolder"; + static const std::string NAME_ALLOW_OBSOLETE_MSVCRT = "PolicyAllowObsoleteMsvcrt"; BuildPolicies BuildPolicies::parse(const std::string& s) { @@ -35,6 +36,11 @@ namespace vcpkg::PostBuildLint return BuildPoliciesC::EMPTY_INCLUDE_FOLDER; } + if (s == NAME_ALLOW_OBSOLETE_MSVCRT) + { + return BuildPoliciesC::ALLOW_OBSOLETE_MSVCRT; + } + return BuildPoliciesC::NULLVALUE; } @@ -46,6 +52,7 @@ namespace vcpkg::PostBuildLint case BuildPoliciesC::DLLS_WITHOUT_LIBS: return NAME_DLLS_WITHOUT_LIBS; case BuildPoliciesC::ONLY_RELEASE_CRT: return NAME_ONLY_RELEASE_CRT; case BuildPoliciesC::EMPTY_INCLUDE_FOLDER: return NAME_EMPTY_INCLUDE_FOLDER; + case BuildPoliciesC::ALLOW_OBSOLETE_MSVCRT: return NAME_ALLOW_OBSOLETE_MSVCRT; case BuildPoliciesC::NULLVALUE: return NULLVALUE_STRING; default: Checks::unreachable(VCPKG_LINE_INFO); } @@ -57,6 +64,7 @@ namespace vcpkg::PostBuildLint static const std::string CMAKE_VARIABLE_DLLS_WITHOUT_LIBS = "VCPKG_POLICY_DLLS_WITHOUT_LIBS"; static const std::string CMAKE_VARIABLE_ONLY_RELEASE_CRT = "VCPKG_POLICY_ONLY_RELEASE_CRT"; static const std::string CMAKE_VARIABLE_EMPTY_INCLUDE_FOLDER = "VCPKG_POLICY_EMPTY_INCLUDE_FOLDER"; + static const std::string CMAKE_VARIABLE_ALLOW_OBSOLETE_MSVCRT = "VCPKG_POLICY_ALLOW_OBSOLETE_MSVCRT"; switch (this->backing_enum) { @@ -64,6 +72,7 @@ namespace vcpkg::PostBuildLint case BuildPoliciesC::DLLS_WITHOUT_LIBS: return CMAKE_VARIABLE_DLLS_WITHOUT_LIBS; case BuildPoliciesC::ONLY_RELEASE_CRT: return CMAKE_VARIABLE_ONLY_RELEASE_CRT; case BuildPoliciesC::EMPTY_INCLUDE_FOLDER: return CMAKE_VARIABLE_EMPTY_INCLUDE_FOLDER; + case BuildPoliciesC::ALLOW_OBSOLETE_MSVCRT: return CMAKE_VARIABLE_ALLOW_OBSOLETE_MSVCRT; case BuildPoliciesC::NULLVALUE: Enums::nullvalue_used(VCPKG_LINE_INFO, BuildPoliciesC::ENUM_NAME); default: Checks::unreachable(VCPKG_LINE_INFO); } -- cgit v1.2.3 From f9d0ee313c815f7d2b322f0c68d20b539465ce38 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 22 May 2017 20:49:15 -0700 Subject: [vcpkg] Avoid modifying static globals after initialization --- toolsrc/src/PostBuildLint.cpp | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index a8365e109..4491f3f2e 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -48,27 +48,34 @@ namespace vcpkg::PostBuildLint const std::vector& get_outdated_dynamic_crts(const std::map& policies) { - static std::vector v = {{"msvcp100.dll", R"(msvcp100\.dll)"}, - {"msvcp100d.dll", R"(msvcp100d\.dll)"}, - {"msvcp110.dll", R"(msvcp110\.dll)"}, - {"msvcp110_win.dll", R"(msvcp110_win\.dll)"}, - {"msvcp120.dll", R"(msvcp120\.dll)"}, - {"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"}, - {"msvcp60.dll", R"(msvcp60\.dll)"}, - {"msvcp60.dll", R"(msvcp60\.dll)"}, - - {"msvcr100.dll", R"(msvcr100\.dll)"}, - {"msvcr100d.dll", R"(msvcr100d\.dll)"}, - {"msvcr100_clr0400.dll", R"(msvcr100_clr0400\.dll)"}, - {"msvcr110.dll", R"(msvcr110\.dll)"}, - {"msvcr120.dll", R"(msvcr120\.dll)"}, - {"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"}, - {"msvcrt20.dll", R"(msvcrt20\.dll)"}, - {"msvcrt40.dll", R"(msvcrt40\.dll)"}}; + static const std::vector v_no_msvcrt = { + {"msvcp100.dll", R"(msvcp100\.dll)"}, + {"msvcp100d.dll", R"(msvcp100d\.dll)"}, + {"msvcp110.dll", R"(msvcp110\.dll)"}, + {"msvcp110_win.dll", R"(msvcp110_win\.dll)"}, + {"msvcp120.dll", R"(msvcp120\.dll)"}, + {"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"}, + {"msvcp60.dll", R"(msvcp60\.dll)"}, + {"msvcp60.dll", R"(msvcp60\.dll)"}, + + {"msvcr100.dll", R"(msvcr100\.dll)"}, + {"msvcr100d.dll", R"(msvcr100d\.dll)"}, + {"msvcr100_clr0400.dll", R"(msvcr100_clr0400\.dll)"}, + {"msvcr110.dll", R"(msvcr110\.dll)"}, + {"msvcr120.dll", R"(msvcr120\.dll)"}, + {"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"}, + {"msvcrt20.dll", R"(msvcrt20\.dll)"}, + {"msvcrt40.dll", R"(msvcrt40\.dll)"}}; + + static const std::vector v = [&]() { + auto ret = v_no_msvcrt; + ret.push_back(OutdatedDynamicCrt{"msvcrt.dll", R"(msvcrt\.dll)"}); + return ret; + }(); if (contains_and_enabled(policies, BuildPoliciesC::ALLOW_OBSOLETE_MSVCRT)) { - v.push_back(OutdatedDynamicCrt{"msvcrt.dll", R"(msvcrt\.dll)"}); + return v_no_msvcrt; } return v; -- cgit v1.2.3 From 6be01a12db23788c32ca8cc8e70b8467ae912d1d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 24 May 2017 00:44:00 -0700 Subject: [vcpkg] Refactored to simplify BuildPolicies into BuildPolicy. Restrict policy consumers to a simpler interface than std::map. Rename vcpkg::getMachineType -> vcpkg::to_machine_type. --- toolsrc/src/MachineType.cpp | 2 +- toolsrc/src/PostBuildLint.cpp | 32 ++++-------- toolsrc/src/PostBuildLint_BuildPolicies.cpp | 80 ----------------------------- toolsrc/src/coff_file_reader.cpp | 6 +-- toolsrc/src/vcpkg_Build.cpp | 37 ++++++++----- toolsrc/src/vcpkg_Build_BuildPolicy.cpp | 51 ++++++++++++++++++ 6 files changed, 90 insertions(+), 118 deletions(-) delete mode 100644 toolsrc/src/PostBuildLint_BuildPolicies.cpp create mode 100644 toolsrc/src/vcpkg_Build_BuildPolicy.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/MachineType.cpp b/toolsrc/src/MachineType.cpp index f288855e6..2f44ce21a 100644 --- a/toolsrc/src/MachineType.cpp +++ b/toolsrc/src/MachineType.cpp @@ -5,7 +5,7 @@ namespace vcpkg { - MachineType getMachineType(const uint16_t value) + MachineType to_machine_type(const uint16_t value) { MachineType t = static_cast(value); switch (t) diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 4491f3f2e..bcad27032 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -12,6 +12,7 @@ using vcpkg::Build::PreBuildInfo; using vcpkg::Build::BuildInfo; +using vcpkg::Build::BuildPolicy; namespace vcpkg::PostBuildLint { @@ -37,16 +38,7 @@ namespace vcpkg::PostBuildLint } }; - template - static bool contains_and_enabled(const std::map map, const T& key) - { - auto it = map.find(key); - if (it != map.cend()) return it->second; - - return false; - } - - const std::vector& get_outdated_dynamic_crts(const std::map& policies) + const std::vector& get_outdated_dynamic_crts(const Build::BuildPolicies& policies) { static const std::vector v_no_msvcrt = { {"msvcp100.dll", R"(msvcp100\.dll)"}, @@ -73,7 +65,7 @@ namespace vcpkg::PostBuildLint return ret; }(); - if (contains_and_enabled(policies, BuildPoliciesC::ALLOW_OBSOLETE_MSVCRT)) + if (policies.is_enabled(BuildPolicy::ALLOW_OBSOLETE_MSVCRT)) { return v_no_msvcrt; } @@ -82,10 +74,10 @@ namespace vcpkg::PostBuildLint } static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs, - const std::map& policies, + const Build::BuildPolicies& policies, const fs::path& package_dir) { - if (contains_and_enabled(policies, BuildPoliciesC::EMPTY_INCLUDE_FOLDER)) + if (policies.is_enabled(BuildPolicy::EMPTY_INCLUDE_FOLDER)) { return LintStatus::SUCCESS; } @@ -511,16 +503,12 @@ namespace vcpkg::PostBuildLint return LintStatus::ERROR_DETECTED; } - static LintStatus check_lib_files_are_available_if_dlls_are_available(const std::map& policies, + static LintStatus check_lib_files_are_available_if_dlls_are_available(const Build::BuildPolicies& policies, const size_t lib_count, const size_t dll_count, const fs::path& lib_dir) { - auto it = policies.find(BuildPoliciesC::DLLS_WITHOUT_LIBS); - if (it != policies.cend() && it->second) - { - return LintStatus::SUCCESS; - } + if (policies.is_enabled(BuildPolicy::DLLS_WITHOUT_LIBS)) return LintStatus::SUCCESS; if (lib_count == 0 && dll_count != 0) { @@ -528,7 +516,7 @@ namespace vcpkg::PostBuildLint System::println(System::Color::warning, "If this is intended, add the following line in the portfile:\n" " SET(%s enabled)", - BuildPoliciesC::DLLS_WITHOUT_LIBS.cmake_variable()); + to_cmake_variable(BuildPolicy::DLLS_WITHOUT_LIBS)); return LintStatus::ERROR_DETECTED; } @@ -750,7 +738,7 @@ namespace vcpkg::PostBuildLint size_t error_count = 0; - if (contains_and_enabled(build_info.policies, BuildPoliciesC::EMPTY_PACKAGE)) + if (build_info.policies.is_enabled(BuildPolicy::EMPTY_PACKAGE)) { return error_count; } @@ -822,7 +810,7 @@ namespace vcpkg::PostBuildLint error_count += check_bin_folders_are_not_present_in_static_build(fs, package_dir); - if (!contains_and_enabled(build_info.policies, BuildPoliciesC::ONLY_RELEASE_CRT)) + if (!build_info.policies.is_enabled(BuildPolicy::ONLY_RELEASE_CRT)) { error_count += check_crt_linkage_of_libs( BuildType::value_of(ConfigurationTypeC::DEBUG, build_info.crt_linkage), diff --git a/toolsrc/src/PostBuildLint_BuildPolicies.cpp b/toolsrc/src/PostBuildLint_BuildPolicies.cpp deleted file mode 100644 index d2189e20d..000000000 --- a/toolsrc/src/PostBuildLint_BuildPolicies.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "pch.h" - -#include "PostBuildLint_BuildPolicies.h" -#include "vcpkg_Checks.h" -#include "vcpkg_Enums.h" - -namespace vcpkg::PostBuildLint -{ - static const std::string NULLVALUE_STRING = Enums::nullvalue_to_string(BuildPoliciesC::ENUM_NAME); - - static const std::string NAME_EMPTY_PACKAGE = "PolicyEmptyPackage"; - static const std::string NAME_DLLS_WITHOUT_LIBS = "PolicyDLLsWithoutLIBs"; - static const std::string NAME_ONLY_RELEASE_CRT = "PolicyOnlyReleaseCRT"; - static const std::string NAME_EMPTY_INCLUDE_FOLDER = "PolicyEmptyIncludeFolder"; - static const std::string NAME_ALLOW_OBSOLETE_MSVCRT = "PolicyAllowObsoleteMsvcrt"; - - BuildPolicies BuildPolicies::parse(const std::string& s) - { - if (s == NAME_EMPTY_PACKAGE) - { - return BuildPoliciesC::EMPTY_PACKAGE; - } - - if (s == NAME_DLLS_WITHOUT_LIBS) - { - return BuildPoliciesC::DLLS_WITHOUT_LIBS; - } - - if (s == NAME_ONLY_RELEASE_CRT) - { - return BuildPoliciesC::ONLY_RELEASE_CRT; - } - - if (s == NAME_EMPTY_INCLUDE_FOLDER) - { - return BuildPoliciesC::EMPTY_INCLUDE_FOLDER; - } - - if (s == NAME_ALLOW_OBSOLETE_MSVCRT) - { - return BuildPoliciesC::ALLOW_OBSOLETE_MSVCRT; - } - - return BuildPoliciesC::NULLVALUE; - } - - const std::string& BuildPolicies::to_string() const - { - switch (this->backing_enum) - { - case BuildPoliciesC::EMPTY_PACKAGE: return NAME_EMPTY_PACKAGE; - case BuildPoliciesC::DLLS_WITHOUT_LIBS: return NAME_DLLS_WITHOUT_LIBS; - case BuildPoliciesC::ONLY_RELEASE_CRT: return NAME_ONLY_RELEASE_CRT; - case BuildPoliciesC::EMPTY_INCLUDE_FOLDER: return NAME_EMPTY_INCLUDE_FOLDER; - case BuildPoliciesC::ALLOW_OBSOLETE_MSVCRT: return NAME_ALLOW_OBSOLETE_MSVCRT; - case BuildPoliciesC::NULLVALUE: return NULLVALUE_STRING; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - - const std::string& BuildPolicies::cmake_variable() const - { - static const std::string CMAKE_VARIABLE_EMPTY_PACKAGE = "VCPKG_POLICY_EMPTY_PACKAGE"; - static const std::string CMAKE_VARIABLE_DLLS_WITHOUT_LIBS = "VCPKG_POLICY_DLLS_WITHOUT_LIBS"; - static const std::string CMAKE_VARIABLE_ONLY_RELEASE_CRT = "VCPKG_POLICY_ONLY_RELEASE_CRT"; - static const std::string CMAKE_VARIABLE_EMPTY_INCLUDE_FOLDER = "VCPKG_POLICY_EMPTY_INCLUDE_FOLDER"; - static const std::string CMAKE_VARIABLE_ALLOW_OBSOLETE_MSVCRT = "VCPKG_POLICY_ALLOW_OBSOLETE_MSVCRT"; - - switch (this->backing_enum) - { - case BuildPoliciesC::EMPTY_PACKAGE: return CMAKE_VARIABLE_EMPTY_PACKAGE; - case BuildPoliciesC::DLLS_WITHOUT_LIBS: return CMAKE_VARIABLE_DLLS_WITHOUT_LIBS; - case BuildPoliciesC::ONLY_RELEASE_CRT: return CMAKE_VARIABLE_ONLY_RELEASE_CRT; - case BuildPoliciesC::EMPTY_INCLUDE_FOLDER: return CMAKE_VARIABLE_EMPTY_INCLUDE_FOLDER; - case BuildPoliciesC::ALLOW_OBSOLETE_MSVCRT: return CMAKE_VARIABLE_ALLOW_OBSOLETE_MSVCRT; - case BuildPoliciesC::NULLVALUE: Enums::nullvalue_used(VCPKG_LINE_INFO, BuildPoliciesC::ENUM_NAME); - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } -} diff --git a/toolsrc/src/coff_file_reader.cpp b/toolsrc/src/coff_file_reader.cpp index 467fc9a64..b06c6d57b 100644 --- a/toolsrc/src/coff_file_reader.cpp +++ b/toolsrc/src/coff_file_reader.cpp @@ -87,7 +87,7 @@ namespace vcpkg::COFFFileReader std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE); const uint16_t machine = reinterpret_bytes(machine_field_as_string.c_str()); - return getMachineType(machine); + return to_machine_type(machine); } private: @@ -210,7 +210,7 @@ namespace vcpkg::COFFFileReader std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE); const uint16_t machine = reinterpret_bytes(machine_field_as_string.c_str()); - return getMachineType(machine); + return to_machine_type(machine); } private: @@ -297,7 +297,7 @@ namespace vcpkg::COFFFileReader marker.set_to_offset(offset + ArchiveMemberHeader::HEADER_SIZE); // Skip the header, no need to read it. marker.seek_to_marker(fs); const uint16_t first_two_bytes = peek_value_from_stream(fs); - const bool isImportHeader = getMachineType(first_two_bytes) == MachineType::UNKNOWN; + const bool isImportHeader = to_machine_type(first_two_bytes) == MachineType::UNKNOWN; const MachineType machine = isImportHeader ? ImportHeader::read(fs).machineType() : CoffFileHeader::read(fs).machineType(); machine_types.insert(machine); diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index 6605fa4fb..d44a673fc 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -13,8 +13,6 @@ #include "vcpkglib.h" #include "vcpkglib_helpers.h" -using vcpkg::PostBuildLint::BuildPolicies; -namespace BuildPoliciesC = vcpkg::PostBuildLint::BuildPoliciesC; using vcpkg::PostBuildLint::LinkageType; namespace LinkageTypeC = vcpkg::PostBuildLint::LinkageTypeC; @@ -214,7 +212,7 @@ namespace vcpkg::Build Commands::Version::version()); } - BuildInfo BuildInfo::create(std::unordered_map pgh) + static BuildInfo inner_create_buildinfo(std::unordered_map pgh) { BuildInfo build_info; const std::string crt_linkage_as_string = @@ -240,20 +238,35 @@ namespace vcpkg::Build pgh.erase(it_version); } + std::map policies; + // The remaining entries are policies for (const std::unordered_map::value_type& p : pgh) { - const BuildPolicies policy = BuildPolicies::parse(p.first); - Checks::check_exit( - VCPKG_LINE_INFO, policy != BuildPoliciesC::NULLVALUE, "Unknown policy found: %s", p.first); - if (p.second == "enabled") - build_info.policies.emplace(policy, true); - else if (p.second == "disabled") - build_info.policies.emplace(policy, false); + auto maybe_policy = to_build_policy(p.first); + if (auto policy = maybe_policy.get()) + { + Checks::check_exit(VCPKG_LINE_INFO, + policies.find(*policy) == policies.end(), + "Policy specified multiple times: %s", + p.first); + + if (p.second == "enabled") + policies.emplace(*policy, true); + else if (p.second == "disabled") + policies.emplace(*policy, false); + else + Checks::exit_with_message( + VCPKG_LINE_INFO, "Unknown setting for policy '%s': %s", p.first, p.second); + } else - Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown setting for policy '%s': %s", p.first, p.second); + { + Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown policy found: %s", p.first); + } } + build_info.policies = BuildPolicies(std::move(policies)); + return build_info; } @@ -262,7 +275,7 @@ namespace vcpkg::Build const Expected> pghs = Paragraphs::get_single_paragraph(fs, filepath); Checks::check_exit(VCPKG_LINE_INFO, pghs.get() != nullptr, "Invalid BUILD_INFO file for package"); - return BuildInfo::create(*pghs.get()); + return inner_create_buildinfo(*pghs.get()); } PreBuildInfo PreBuildInfo::from_triplet_file(const VcpkgPaths& paths, const Triplet& triplet) diff --git a/toolsrc/src/vcpkg_Build_BuildPolicy.cpp b/toolsrc/src/vcpkg_Build_BuildPolicy.cpp new file mode 100644 index 000000000..e75e176a2 --- /dev/null +++ b/toolsrc/src/vcpkg_Build_BuildPolicy.cpp @@ -0,0 +1,51 @@ +#include "pch.h" + +#include "vcpkg_Build.h" +#include "vcpkg_Checks.h" +#include "vcpkg_Enums.h" + +namespace vcpkg::Build +{ + static const std::string NAME_EMPTY_PACKAGE = "PolicyEmptyPackage"; + static const std::string NAME_DLLS_WITHOUT_LIBS = "PolicyDLLsWithoutLIBs"; + static const std::string NAME_ONLY_RELEASE_CRT = "PolicyOnlyReleaseCRT"; + static const std::string NAME_EMPTY_INCLUDE_FOLDER = "PolicyEmptyIncludeFolder"; + static const std::string NAME_ALLOW_OBSOLETE_MSVCRT = "PolicyAllowObsoleteMsvcrt"; + + Optional to_build_policy(const std::string& s) + { + if (s == NAME_EMPTY_PACKAGE) return BuildPolicy::EMPTY_PACKAGE; + if (s == NAME_DLLS_WITHOUT_LIBS) return BuildPolicy::DLLS_WITHOUT_LIBS; + if (s == NAME_ONLY_RELEASE_CRT) return BuildPolicy::ONLY_RELEASE_CRT; + if (s == NAME_EMPTY_INCLUDE_FOLDER) return BuildPolicy::EMPTY_INCLUDE_FOLDER; + if (s == NAME_ALLOW_OBSOLETE_MSVCRT) return BuildPolicy::ALLOW_OBSOLETE_MSVCRT; + + return nullopt; + } + + const std::string& to_string(BuildPolicy policy) + { + switch (policy) + { + case BuildPolicy::EMPTY_PACKAGE: return NAME_EMPTY_PACKAGE; + case BuildPolicy::DLLS_WITHOUT_LIBS: return NAME_DLLS_WITHOUT_LIBS; + case BuildPolicy::ONLY_RELEASE_CRT: return NAME_ONLY_RELEASE_CRT; + case BuildPolicy::EMPTY_INCLUDE_FOLDER: return NAME_EMPTY_INCLUDE_FOLDER; + case BuildPolicy::ALLOW_OBSOLETE_MSVCRT: return NAME_ALLOW_OBSOLETE_MSVCRT; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + + CStringView to_cmake_variable(BuildPolicy policy) + { + switch (policy) + { + case BuildPolicy::EMPTY_PACKAGE: return "VCPKG_POLICY_EMPTY_PACKAGE"; + case BuildPolicy::DLLS_WITHOUT_LIBS: return "VCPKG_POLICY_DLLS_WITHOUT_LIBS"; + case BuildPolicy::ONLY_RELEASE_CRT: return "VCPKG_POLICY_ONLY_RELEASE_CRT"; + case BuildPolicy::EMPTY_INCLUDE_FOLDER: return "VCPKG_POLICY_EMPTY_INCLUDE_FOLDER"; + case BuildPolicy::ALLOW_OBSOLETE_MSVCRT: return "VCPKG_POLICY_ALLOW_OBSOLETE_MSVCRT"; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } +} -- cgit v1.2.3 From a5eb44f1a62315f673b8f2f48c1d3895dcceabda Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 24 May 2017 15:51:18 -0700 Subject: [vcpkg] Rename CoffFileHeader::machineType -> machine_type --- toolsrc/src/coff_file_reader.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/coff_file_reader.cpp b/toolsrc/src/coff_file_reader.cpp index b06c6d57b..6c38c452b 100644 --- a/toolsrc/src/coff_file_reader.cpp +++ b/toolsrc/src/coff_file_reader.cpp @@ -80,7 +80,7 @@ namespace vcpkg::COFFFileReader return ret; } - MachineType machineType() const + MachineType machine_type() const { static const size_t MACHINE_TYPE_OFFSET = 0; static const size_t MACHINE_TYPE_SIZE = 2; @@ -203,7 +203,7 @@ namespace vcpkg::COFFFileReader return ret; } - MachineType machineType() const + MachineType machine_type() const { static const size_t MACHINE_TYPE_OFFSET = 6; static const size_t MACHINE_TYPE_SIZE = 2; @@ -236,7 +236,7 @@ namespace vcpkg::COFFFileReader read_and_verify_PE_signature(fs); CoffFileHeader header = CoffFileHeader::read(fs); - MachineType machine = header.machineType(); + MachineType machine = header.machine_type(); return {machine}; } @@ -299,7 +299,7 @@ namespace vcpkg::COFFFileReader const uint16_t first_two_bytes = peek_value_from_stream(fs); const bool isImportHeader = to_machine_type(first_two_bytes) == MachineType::UNKNOWN; const MachineType machine = - isImportHeader ? ImportHeader::read(fs).machineType() : CoffFileHeader::read(fs).machineType(); + isImportHeader ? ImportHeader::read(fs).machine_type() : CoffFileHeader::read(fs).machine_type(); machine_types.insert(machine); } -- cgit v1.2.3 From 1253b875195590e528d8a28e12a798264603ba43 Mon Sep 17 00:00:00 2001 From: Albert Ziegenhagel Date: Fri, 2 Jun 2017 18:13:12 +0200 Subject: Implement support to request a specific toolset version via the variable `VCPKG_PLATFORM_TOOLSET` in the triplet file --- toolsrc/src/PostBuildLint.cpp | 2 +- toolsrc/src/VcpkgPaths.cpp | 63 ++++++++++++++++++++++++++++++++++++------- toolsrc/src/commands_env.cpp | 2 +- toolsrc/src/vcpkg_Build.cpp | 2 +- 4 files changed, 56 insertions(+), 13 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index bcad27032..363346ab6 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -733,7 +733,7 @@ namespace vcpkg::PostBuildLint const auto& fs = paths.get_filesystem(); // for dumpbin - const Toolset& toolset = paths.get_toolset(); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); const fs::path package_dir = paths.package_dir(spec); size_t error_count = 0; diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 3dd32de01..acd847b5f 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -269,7 +269,7 @@ namespace vcpkg return nullopt; } - static Toolset find_toolset_instance(const VcpkgPaths& paths) + static std::vector find_toolset_instances(const VcpkgPaths& paths) { const auto& fs = paths.get_filesystem(); @@ -277,7 +277,10 @@ namespace vcpkg // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. std::vector paths_examined; + std::vector found_toolsets; + // VS2017 + Optional vs2017_toolset; for (const fs::path& instance : vs2017_installation_instances) { const fs::path vc_dir = instance / "VC"; @@ -303,9 +306,15 @@ namespace vcpkg paths_examined.push_back(dumpbin_path); if (fs.exists(dumpbin_path)) { - return {dumpbin_path, vcvarsall_bat, L"v141"}; + vs2017_toolset = Toolset{dumpbin_path, vcvarsall_bat, L"v141"}; + break; } } + if(vs2017_toolset) break; + } + if(auto value = vs2017_toolset.get()) + { + found_toolsets.push_back(*value); } // VS2015 @@ -321,23 +330,57 @@ namespace vcpkg paths_examined.push_back(vs2015_dumpbin_exe); if (fs.exists(vs2015_dumpbin_exe)) { - return {vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140"}; + found_toolsets.push_back({vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140"}); } } } - System::println(System::Color::error, "Could not locate a complete toolset."); - System::println("The following paths were examined:"); - for (const fs::path& path : paths_examined) + std::sort(found_toolsets.begin(), + found_toolsets.end(), + [](const Toolset& left, const Toolset& right) { return left.version > right.version; }); + + if(found_toolsets.empty()) { - System::println(" %s", path.u8string()); + System::println(System::Color::error, "Could not locate a complete toolset."); + System::println("The following paths were examined:"); + for(const fs::path& path : paths_examined) + { + System::println(" %s", path.u8string()); + } + Checks::exit_fail(VCPKG_LINE_INFO); } - Checks::exit_fail(VCPKG_LINE_INFO); + + return found_toolsets; + } + + const std::vector& VcpkgPaths::get_toolsets() const + { + return this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); } - const Toolset& VcpkgPaths::get_toolset() const + const Toolset& VcpkgPaths::get_latest_toolset() const { - return this->toolset.get_lazy([this]() { return find_toolset_instance(*this); }); + // Invariant: toolsets are non-empty and sorted + return get_toolsets().back(); } + const Toolset& VcpkgPaths::get_toolset(const std::string& toolset_version) const + { + if(toolset_version.empty()) + { + return this->get_latest_toolset(); + } + else + { + const auto& vs_toolsets = this->get_toolsets(); + + const auto toolset = Util::find_if(vs_toolsets, [&](const Toolset& toolset) { return toolset_version == Strings::to_utf8(toolset.version); }); + if(toolset == vs_toolsets.end()) + { + Checks::exit_with_message(VCPKG_LINE_INFO, Strings::format("Could not find toolset %s", toolset_version)); + } + return *toolset; + } + } + Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); } } diff --git a/toolsrc/src/commands_env.cpp b/toolsrc/src/commands_env.cpp index 5e1ecc5e7..dd7172b89 100644 --- a/toolsrc/src/commands_env.cpp +++ b/toolsrc/src/commands_env.cpp @@ -13,7 +13,7 @@ namespace vcpkg::Commands::Env args.check_and_get_optional_command_arguments({}); auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); - System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, paths.get_toolset()) + L" && cmd"); + System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, paths.get_toolset(pre_build_info.platform_toolset)) + L" && cmd"); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index d44a673fc..817febe2f 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -128,8 +128,8 @@ namespace vcpkg::Build const fs::path& git_exe_path = paths.get_git_exe(); const fs::path ports_cmake_script_path = paths.ports_cmake; - const Toolset& toolset = paths.get_toolset(); auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); const std::wstring cmd_launch_cmake = -- cgit v1.2.3 From 60825eed0e8b8c7646d0e66bc2743b4a1e8e4a96 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 5 Jun 2017 22:01:41 -0700 Subject: [vcpkg] Formatting and simplification of VcpkgPaths::get_toolset() --- toolsrc/src/VcpkgPaths.cpp | 79 +++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 46 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index acd847b5f..9068e3903 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -279,6 +279,24 @@ namespace vcpkg std::vector found_toolsets; + // VS2015 + const Optional vs_2015_installation_instance = get_VS2015_installation_instance(); + if (auto v = vs_2015_installation_instance.get()) + { + const fs::path vs2015_vcvarsall_bat = *v / "VC" / "vcvarsall.bat"; + + paths_examined.push_back(vs2015_vcvarsall_bat); + if (fs.exists(vs2015_vcvarsall_bat)) + { + const fs::path vs2015_dumpbin_exe = *v / "VC" / "bin" / "dumpbin.exe"; + paths_examined.push_back(vs2015_dumpbin_exe); + if (fs.exists(vs2015_dumpbin_exe)) + { + found_toolsets.push_back({vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140"}); + } + } + } + // VS2017 Optional vs2017_toolset; for (const fs::path& instance : vs2017_installation_instances) @@ -310,40 +328,18 @@ namespace vcpkg break; } } - if(vs2017_toolset) break; - } - if(auto value = vs2017_toolset.get()) - { - found_toolsets.push_back(*value); - } - - // VS2015 - const Optional vs_2015_installation_instance = get_VS2015_installation_instance(); - if (auto v = vs_2015_installation_instance.get()) - { - const fs::path vs2015_vcvarsall_bat = *v / "VC" / "vcvarsall.bat"; - - paths_examined.push_back(vs2015_vcvarsall_bat); - if (fs.exists(vs2015_vcvarsall_bat)) + if (auto value = vs2017_toolset.get()) { - const fs::path vs2015_dumpbin_exe = *v / "VC" / "bin" / "dumpbin.exe"; - paths_examined.push_back(vs2015_dumpbin_exe); - if (fs.exists(vs2015_dumpbin_exe)) - { - found_toolsets.push_back({vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140"}); - } + found_toolsets.push_back(*value); + break; } } - std::sort(found_toolsets.begin(), - found_toolsets.end(), - [](const Toolset& left, const Toolset& right) { return left.version > right.version; }); - - if(found_toolsets.empty()) + if (found_toolsets.empty()) { System::println(System::Color::error, "Could not locate a complete toolset."); System::println("The following paths were examined:"); - for(const fs::path& path : paths_examined) + for (const fs::path& path : paths_examined) { System::println(" %s", path.u8string()); } @@ -353,31 +349,22 @@ namespace vcpkg return found_toolsets; } - const std::vector& VcpkgPaths::get_toolsets() const - { - return this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); - } - - const Toolset& VcpkgPaths::get_latest_toolset() const - { - // Invariant: toolsets are non-empty and sorted - return get_toolsets().back(); - } const Toolset& VcpkgPaths::get_toolset(const std::string& toolset_version) const { - if(toolset_version.empty()) + // Invariant: toolsets are non-empty and sorted with newest at back() + const auto& vs_toolsets = this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); + + if (toolset_version.empty()) { - return this->get_latest_toolset(); + return vs_toolsets.back(); } else { - const auto& vs_toolsets = this->get_toolsets(); - - const auto toolset = Util::find_if(vs_toolsets, [&](const Toolset& toolset) { return toolset_version == Strings::to_utf8(toolset.version); }); - if(toolset == vs_toolsets.end()) - { - Checks::exit_with_message(VCPKG_LINE_INFO, Strings::format("Could not find toolset %s", toolset_version)); - } + const auto toolset = Util::find_if(vs_toolsets, [&](const Toolset& toolset) { + return toolset_version == Strings::to_utf8(toolset.version); + }); + Checks::check_exit( + VCPKG_LINE_INFO, toolset != vs_toolsets.end(), "Could not find toolset '%s'", toolset_version); return *toolset; } } -- cgit v1.2.3 From 264cd050e6280e5b87ec055e0a9d8985a7ba30b3 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Mon, 5 Jun 2017 15:58:47 -0700 Subject: ExpectedT factory class --- toolsrc/src/PackageSpec.cpp | 10 +++--- toolsrc/src/PackageSpecParseResult.cpp | 24 ++----------- toolsrc/src/Paragraphs.cpp | 23 +++++++----- toolsrc/src/SourceParagraph.cpp | 47 ++++++++++++++++++------ toolsrc/src/commands_build.cpp | 17 +++++---- toolsrc/src/tests_paragraph.cpp | 66 ++++++++++++++++++++-------------- toolsrc/src/vcpkg.cpp | 4 +-- toolsrc/src/vcpkg_Dependencies.cpp | 10 ++++-- toolsrc/src/vcpkg_Files.cpp | 6 ++-- toolsrc/src/vcpkg_Input.cpp | 4 +-- 10 files changed, 124 insertions(+), 87 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index 69883a030..ab005f255 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -7,7 +7,8 @@ namespace vcpkg { static bool is_valid_package_spec_char(char c) { return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)); } - Expected PackageSpec::from_string(const std::string& spec_as_string, const Triplet& default_triplet) + ExpectedT PackageSpec::from_string(const std::string& spec_as_string, + const Triplet& default_triplet) { auto pos = spec_as_string.find(':'); if (pos == std::string::npos) @@ -18,7 +19,7 @@ namespace vcpkg auto pos2 = spec_as_string.find(':', pos + 1); if (pos2 != std::string::npos) { - return std::error_code(PackageSpecParseResult::TOO_MANY_COLONS); + return PackageSpecParseResult::TOO_MANY_COLONS; } const std::string name = spec_as_string.substr(0, pos); @@ -26,11 +27,12 @@ namespace vcpkg return from_name_and_triplet(name, triplet); } - Expected PackageSpec::from_name_and_triplet(const std::string& name, const Triplet& triplet) + ExpectedT PackageSpec::from_name_and_triplet(const std::string& name, + const Triplet& triplet) { if (Util::find_if_not(name, is_valid_package_spec_char) != name.end()) { - return std::error_code(PackageSpecParseResult::INVALID_CHARACTERS); + return PackageSpecParseResult::INVALID_CHARACTERS; } PackageSpec p; diff --git a/toolsrc/src/PackageSpecParseResult.cpp b/toolsrc/src/PackageSpecParseResult.cpp index 487c3aa1d..838c788ba 100644 --- a/toolsrc/src/PackageSpecParseResult.cpp +++ b/toolsrc/src/PackageSpecParseResult.cpp @@ -5,11 +5,9 @@ namespace vcpkg { - const char* PackageSpecParseResultCategoryImpl::name() const noexcept { return "PackageSpecParseResult"; } - - std::string PackageSpecParseResultCategoryImpl::message(int ev) const noexcept + CStringView to_string(PackageSpecParseResult ev) noexcept { - switch (static_cast(ev)) + switch (ev) { case PackageSpecParseResult::SUCCESS: return "OK"; case PackageSpecParseResult::TOO_MANY_COLONS: return "Too many colons"; @@ -19,22 +17,4 @@ namespace vcpkg default: Checks::unreachable(VCPKG_LINE_INFO); } } - - const std::error_category& package_spec_parse_result_category() - { - static PackageSpecParseResultCategoryImpl instance; - return instance; - } - - std::error_code make_error_code(PackageSpecParseResult e) - { - return std::error_code(static_cast(e), package_spec_parse_result_category()); - } - - PackageSpecParseResult to_package_spec_parse_result(int i) { return static_cast(i); } - - PackageSpecParseResult to_package_spec_parse_result(std::error_code ec) - { - return to_package_spec_parse_result(ec.value()); - } } diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index 70d3db2b3..13103d1f8 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -168,7 +168,7 @@ namespace vcpkg::Paragraphs return parse_single_paragraph(*spgh); } - return contents.error_code(); + return contents.error(); } Expected>> get_paragraphs(const Files::Filesystem& fs, @@ -180,7 +180,7 @@ namespace vcpkg::Paragraphs return parse_paragraphs(*spgh); } - return contents.error_code(); + return contents.error(); } Expected> parse_single_paragraph(const std::string& str) @@ -201,15 +201,16 @@ namespace vcpkg::Paragraphs return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); } - Expected try_load_port(const Files::Filesystem& fs, const fs::path& path) + ExpectedT try_load_port(const Files::Filesystem& fs, const fs::path& path) { + ParseControlErrorInfo error_info; Expected> pghs = get_single_paragraph(fs, path / "CONTROL"); if (auto p = pghs.get()) { - return SourceParagraph(*p); + return SourceParagraph::parse_control_file(*p); } - - return pghs.error_code(); + error_info.error = pghs.error(); + return error_info; } Expected try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec) @@ -222,20 +223,26 @@ namespace vcpkg::Paragraphs return BinaryParagraph(*p); } - return pghs.error_code(); + return pghs.error(); } std::vector load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) { std::vector output; + std::vector port_errors; for (auto&& path : fs.get_files_non_recursive(ports_dir)) { - Expected source_paragraph = try_load_port(fs, path); + ExpectedT source_paragraph = try_load_port(fs, path); if (auto srcpgh = source_paragraph.get()) { output.emplace_back(std::move(*srcpgh)); } + else + { + port_errors.emplace_back(source_paragraph.error()); + } } + print_error_message(port_errors); return output; } diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index d140ce72b..9516681c9 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -5,6 +5,8 @@ #include "vcpkg_Checks.h" #include "vcpkg_Maps.h" #include "vcpkg_System.h" +#include "vcpkg_expected.h" + #include "vcpkglib_helpers.h" namespace vcpkg @@ -37,15 +39,41 @@ namespace vcpkg SourceParagraph::SourceParagraph() = default; - SourceParagraph::SourceParagraph(std::unordered_map fields) + void print_error_message(const ParseControlErrorInfo& info) + { + System::println( + System::Color::error, "Error: There are invalid fields in the Source Paragraph of %s", info.name); + System::println("The following fields were not expected:\n\n %s\n\n", info.remaining_fields_as_string); + System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", info.valid_fields_as_string); + System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); + } + + void print_error_message(std::vector error_info_list) + { + for (ParseControlErrorInfo error_info : error_info_list) + { + System::println( + System::Color::error, "Error: There are invalid fields in the Source Paragraph of %s", error_info.name); + System::println("The following fields were not expected:\n\n %s\n\n", + error_info.remaining_fields_as_string); + } + + System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", + error_info_list.front().valid_fields_as_string); + System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); + } + + ExpectedT SourceParagraph::parse_control_file( + std::unordered_map fields) { - this->name = details::remove_required_field(&fields, SourceParagraphRequiredField::SOURCE); - this->version = details::remove_required_field(&fields, SourceParagraphRequiredField::VERSION); - this->description = details::remove_optional_field(&fields, SourceParagraphOptionalField::DESCRIPTION); - this->maintainer = details::remove_optional_field(&fields, SourceParagraphOptionalField::MAINTAINER); + SourceParagraph sparagraph; + sparagraph.name = details::remove_required_field(&fields, SourceParagraphRequiredField::SOURCE); + sparagraph.version = details::remove_required_field(&fields, SourceParagraphRequiredField::VERSION); + sparagraph.description = details::remove_optional_field(&fields, SourceParagraphOptionalField::DESCRIPTION); + sparagraph.maintainer = details::remove_optional_field(&fields, SourceParagraphOptionalField::MAINTAINER); std::string deps = details::remove_optional_field(&fields, SourceParagraphOptionalField::BUILD_DEPENDS); - this->depends = expand_qualified_dependencies(parse_depends(deps)); + sparagraph.depends = expand_qualified_dependencies(parse_depends(deps)); if (!fields.empty()) { @@ -55,12 +83,9 @@ namespace vcpkg const std::string remaining_fields_as_string = Strings::join("\n ", remaining_fields); const std::string valid_fields_as_string = Strings::join("\n ", valid_fields); - System::println( - System::Color::error, "Error: There are invalid fields in the Source Paragraph of %s", this->name); - System::println("The following fields were not expected:\n\n %s\n\n", remaining_fields_as_string); - System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", valid_fields_as_string); - Checks::exit_fail(VCPKG_LINE_INFO); + return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string, valid_fields_as_string}; } + return sparagraph; } std::vector vcpkg::expand_qualified_dependencies(const std::vector& depends) diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index ec6586fa3..4a0cee021 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -33,13 +33,16 @@ namespace vcpkg::Commands::BuildCommand Checks::exit_success(VCPKG_LINE_INFO); } - const Expected maybe_spgh = Paragraphs::try_load_port(paths.get_filesystem(), port_dir); - Checks::check_exit(VCPKG_LINE_INFO, - !maybe_spgh.error_code(), - "Could not find package %s: %s", - spec, - maybe_spgh.error_code().message()); - const SourceParagraph& spgh = *maybe_spgh.get(); + const ExpectedT maybe_spgh = + Paragraphs::try_load_port(paths.get_filesystem(), port_dir); + // why do we add a const here + if (!maybe_spgh) + { + print_error_message(maybe_spgh.error()); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + const SourceParagraph& spgh = maybe_spgh.value_or_exit(VCPKG_LINE_INFO); Checks::check_exit(VCPKG_LINE_INFO, spec.name() == spgh.name, "The Name: field inside the CONTROL does not match the port directory: '%s' != '%s'", diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index b66adc816..1c77b437b 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -25,7 +25,10 @@ namespace UnitTest1 { TEST_METHOD(SourceParagraph_Construct_Minimum) { - vcpkg::SourceParagraph pgh({{"Source", "zlib"}, {"Version", "1.2.8"}}); + auto m_pgh = vcpkg::SourceParagraph::parse_control_file({{"Source", "zlib"}, {"Version", "1.2.8"}}); + + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); Assert::AreEqual("zlib", pgh.name.c_str()); Assert::AreEqual("1.2.8", pgh.version.c_str()); @@ -36,11 +39,12 @@ namespace UnitTest1 TEST_METHOD(SourceParagraph_Construct_Maximum) { - vcpkg::SourceParagraph pgh({{"Source", "s"}, - {"Version", "v"}, - {"Maintainer", "m"}, - {"Description", "d"}, - {"Build-Depends", "bd"}}); + auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ + {"Source", "s"}, {"Version", "v"}, {"Maintainer", "m"}, {"Description", "d"}, {"Build-Depends", "bd"}, + }); + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); + Assert::AreEqual("s", pgh.name.c_str()); Assert::AreEqual("v", pgh.version.c_str()); Assert::AreEqual("m", pgh.maintainer.c_str()); @@ -51,7 +55,11 @@ namespace UnitTest1 TEST_METHOD(SourceParagraph_Two_Depends) { - vcpkg::SourceParagraph pgh({{"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl"}}); + auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ + {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl"}, + }); + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); Assert::AreEqual(size_t(2), pgh.depends.size()); Assert::AreEqual("z", pgh.depends[0].name.c_str()); @@ -60,8 +68,11 @@ namespace UnitTest1 TEST_METHOD(SourceParagraph_Three_Depends) { - vcpkg::SourceParagraph pgh( - {{"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl, xyz"}}); + auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ + {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl, xyz"}, + }); + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); Assert::AreEqual(size_t(3), pgh.depends.size()); Assert::AreEqual("z", pgh.depends[0].name.c_str()); @@ -71,8 +82,11 @@ namespace UnitTest1 TEST_METHOD(SourceParagraph_Construct_Qualified_Depends) { - vcpkg::SourceParagraph pgh( - {{"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA [windows], libB [uwp]"}}); + auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ + {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA [windows], libB [uwp]"}, + }); + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); Assert::AreEqual("zlib", pgh.name.c_str()); Assert::AreEqual("1.2.8", pgh.version.c_str()); @@ -101,13 +115,15 @@ namespace UnitTest1 TEST_METHOD(BinaryParagraph_Construct_Maximum) { - vcpkg::BinaryParagraph pgh({{"Package", "s"}, - {"Version", "v"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Maintainer", "m"}, - {"Description", "d"}, - {"Depends", "bd"}}); + vcpkg::BinaryParagraph pgh({ + {"Package", "s"}, + {"Version", "v"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Maintainer", "m"}, + {"Description", "d"}, + {"Depends", "bd"}, + }); Assert::AreEqual("s", pgh.spec.name().c_str()); Assert::AreEqual("v", pgh.version.c_str()); Assert::AreEqual("m", pgh.maintainer.c_str()); @@ -327,28 +343,26 @@ namespace UnitTest1 TEST_METHOD(package_spec_parse) { - vcpkg::Expected spec = + vcpkg::ExpectedT spec = vcpkg::PackageSpec::from_string("zlib", vcpkg::Triplet::X86_WINDOWS); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, - vcpkg::to_package_spec_parse_result(spec.error_code())); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); Assert::AreEqual("zlib", spec.get()->name().c_str()); Assert::AreEqual(vcpkg::Triplet::X86_WINDOWS.canonical_name(), spec.get()->triplet().canonical_name()); } TEST_METHOD(package_spec_parse_with_arch) { - vcpkg::Expected spec = + vcpkg::ExpectedT spec = vcpkg::PackageSpec::from_string("zlib:x64-uwp", vcpkg::Triplet::X86_WINDOWS); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, - vcpkg::to_package_spec_parse_result(spec.error_code())); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); Assert::AreEqual("zlib", spec.get()->name().c_str()); Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), spec.get()->triplet().canonical_name()); } TEST_METHOD(package_spec_parse_with_multiple_colon) { - auto ec = vcpkg::PackageSpec::from_string("zlib:x86-uwp:", vcpkg::Triplet::X86_WINDOWS).error_code(); - Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, vcpkg::to_package_spec_parse_result(ec)); + auto ec = vcpkg::PackageSpec::from_string("zlib:x86-uwp:", vcpkg::Triplet::X86_WINDOWS).error(); + Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); } TEST_METHOD(utf8_to_utf16) diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 154aefd0a..738b7b284 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -61,10 +61,10 @@ static void inner(const VcpkgCmdArguments& args) const Expected expected_paths = VcpkgPaths::create(vcpkg_root_dir); Checks::check_exit(VCPKG_LINE_INFO, - !expected_paths.error_code(), + !expected_paths.error(), "Error: Invalid vcpkg root directory %s: %s", vcpkg_root_dir.string(), - expected_paths.error_code().message()); + expected_paths.error().message()); const VcpkgPaths paths = expected_paths.value_or_exit(VCPKG_LINE_INFO); int exit_code = _wchdir(paths.root.c_str()); Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed"); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index acfb55239..ea5832e46 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -174,11 +174,14 @@ namespace vcpkg::Dependencies if (auto bpgh = maybe_bpgh.get()) return InstallPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type}; - Expected maybe_spgh = + ExpectedT maybe_spgh = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); if (auto spgh = maybe_spgh.get()) return InstallPlanAction{spec, {nullopt, nullopt, *spgh}, request_type}; + else + print_error_message(maybe_spgh.error()); + Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); } }; @@ -283,11 +286,14 @@ namespace vcpkg::Dependencies if (auto bpgh = maybe_bpgh.get()) return ExportPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type}; - Expected maybe_spgh = + ExpectedT maybe_spgh = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); if (auto spgh = maybe_spgh.get()) return ExportPlanAction{spec, {nullopt, nullopt, *spgh}, request_type}; + else + print_error_message(maybe_spgh.error()); + Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); } }; diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp index 17aa2997a..7b12ea699 100644 --- a/toolsrc/src/vcpkg_Files.cpp +++ b/toolsrc/src/vcpkg_Files.cpp @@ -15,7 +15,7 @@ namespace vcpkg::Files std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); if (file_stream.fail()) { - return std::errc::no_such_file_or_directory; + return std::make_error_code(std::errc::no_such_file_or_directory); } file_stream.seekg(0, file_stream.end); @@ -24,7 +24,7 @@ namespace vcpkg::Files if (length > SIZE_MAX) { - return std::errc::file_too_large; + return std::make_error_code(std::errc::file_too_large); } std::string output; @@ -39,7 +39,7 @@ namespace vcpkg::Files std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); if (file_stream.fail()) { - return std::errc::no_such_file_or_directory; + return std::make_error_code(std::errc::no_such_file_or_directory); } std::vector output; diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp index 7d8e4767e..df738315b 100644 --- a/toolsrc/src/vcpkg_Input.cpp +++ b/toolsrc/src/vcpkg_Input.cpp @@ -12,14 +12,14 @@ namespace vcpkg::Input CStringView example_text) { const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); - Expected expected_spec = PackageSpec::from_string(as_lowercase, default_triplet); + auto expected_spec = PackageSpec::from_string(as_lowercase, default_triplet); if (auto spec = expected_spec.get()) { return *spec; } // Intentionally show the lowercased string - System::println(System::Color::error, "Error: %s: %s", expected_spec.error_code().message(), as_lowercase); + System::println(System::Color::error, "Error: %s: %s", vcpkg::to_string(expected_spec.error()), as_lowercase); System::print(example_text); Checks::exit_fail(VCPKG_LINE_INFO); } -- cgit v1.2.3 From fcf0f331c67a39a758d55c5c841cb81b2dd49289 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Mon, 5 Jun 2017 16:25:04 -0700 Subject: error message vector check --- toolsrc/src/SourceParagraph.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 9516681c9..8a131ef6a 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -50,6 +50,7 @@ namespace vcpkg void print_error_message(std::vector error_info_list) { + if (error_info_list.size() == 0) return; for (ParseControlErrorInfo error_info : error_info_list) { System::println( -- cgit v1.2.3 From cc443d1c6b10735f9e4e5d439432124ffcfb376f Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Mon, 5 Jun 2017 17:55:06 -0700 Subject: minor changes --- toolsrc/src/SourceParagraph.cpp | 2 -- toolsrc/src/commands_build.cpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 8a131ef6a..c77659176 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -37,8 +37,6 @@ namespace vcpkg return valid_fields; } - SourceParagraph::SourceParagraph() = default; - void print_error_message(const ParseControlErrorInfo& info) { System::println( diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index 4a0cee021..294b70b27 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -35,7 +35,7 @@ namespace vcpkg::Commands::BuildCommand const ExpectedT maybe_spgh = Paragraphs::try_load_port(paths.get_filesystem(), port_dir); - // why do we add a const here + if (!maybe_spgh) { print_error_message(maybe_spgh.error()); -- cgit v1.2.3 From 69d5f50ce433750c422446b64b0a45b6b4ea738a Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 22 May 2017 20:18:40 -0700 Subject: Install continue --- toolsrc/src/commands_build.cpp | 5 +- toolsrc/src/commands_ci.cpp | 55 ++------------- toolsrc/src/commands_install.cpp | 147 ++++++++++++++++++++------------------- toolsrc/src/vcpkg_Build.cpp | 22 +++--- 4 files changed, 96 insertions(+), 133 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index 294b70b27..5a5cd462e 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -50,9 +50,8 @@ namespace vcpkg::Commands::BuildCommand spec.name()); StatusParagraphs status_db = database_load_check(paths); - const Build::BuildPackageConfig build_config{ - spgh, spec.triplet(), paths.port_dir(spec), - }; + Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; + const Build::BuildPackageConfig build_config{spgh, spec.triplet(), paths.port_dir(spec), build_package_options}; const auto result = Build::build_package(paths, build_config, status_db); if (result.code == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES) { diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index e9755335c..bad1286f0 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -50,6 +50,8 @@ namespace vcpkg::Commands::CI const ElapsedTime timer = ElapsedTime::create_started(); size_t counter = 0; const size_t package_count = install_plan.size(); + const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; + for (const InstallPlanAction& action : install_plan) { const ElapsedTime build_timer = ElapsedTime::create_started(); @@ -60,55 +62,10 @@ namespace vcpkg::Commands::CI timing.push_back("0"); results.push_back(BuildResult::NULLVALUE); - try - { - switch (action.plan_type) - { - case InstallPlanType::ALREADY_INSTALLED: - results.back() = BuildResult::SUCCEEDED; - System::println(System::Color::success, "Package %s is already installed", display_name); - break; - case InstallPlanType::BUILD_AND_INSTALL: - { - System::println("Building package %s... ", display_name); - auto&& source_paragraph = action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO); - const Build::BuildPackageConfig build_config{ - source_paragraph, action.spec.triplet(), paths.port_dir(action.spec), - }; - const auto result_ex = Build::build_package(paths, build_config, status_db); - const auto result = result_ex.code; - - timing.back() = build_timer.to_string(); - results.back() = result; - if (result != BuildResult::SUCCEEDED) - { - System::println(System::Color::error, Build::create_error_message(result, action.spec)); - continue; - } - System::println(System::Color::success, "Building package %s... done", display_name); - - const BinaryParagraph bpgh = - Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); - System::println("Installing package %s... ", display_name); - Install::install_package(paths, bpgh, &status_db); - System::println(System::Color::success, "Installing package %s... done", display_name); - break; - } - case InstallPlanType::INSTALL: - results.back() = BuildResult::SUCCEEDED; - System::println("Installing package %s... ", display_name); - Install::install_package( - paths, action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO), &status_db); - System::println(System::Color::success, "Installing package %s... done", display_name); - break; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - catch (const std::exception& e) - { - System::println(System::Color::error, "Error: Could not install package %s: %s", action.spec, e.what()); - results.back() = BuildResult::NULLVALUE; - } + const BuildResult result = + Install::perform_install_plan_action(paths, action, install_plan_options, status_db); + timing.back() = build_timer.to_string(); + results.back() = result; System::println("Elapsed time for package %s: %s", action.spec, build_timer.to_string()); } diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index bebe6a3a2..73b3e9eab 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -263,6 +263,77 @@ namespace vcpkg::Commands::Install status_db->insert(std::make_unique(source_paragraph)); } + using Build::BuildResult; + + BuildResult perform_install_plan_action(const VcpkgPaths& paths, + const InstallPlanAction& action, + const Build::BuildPackageOptions& build_package_options, + StatusParagraphs& status_db) + { + const InstallPlanType& plan_type = action.plan_type; + const std::string display_name = action.spec.to_string(); + + const bool is_user_requested = action.request_type == RequestType::USER_REQUESTED; + const bool use_head_version = to_bool(build_package_options.use_head_version); + + if (plan_type == InstallPlanType::ALREADY_INSTALLED) + { + if (use_head_version && is_user_requested) + { + System::println( + System::Color::warning, "Package %s is already installed -- not building from HEAD", display_name); + } + else + { + System::println(System::Color::success, "Package %s is already installed", display_name); + } + return BuildResult::SUCCEEDED; + } + + if (plan_type == InstallPlanType::BUILD_AND_INSTALL) + { + if (use_head_version) + System::println("Building package %s from HEAD... ", display_name); + else + System::println("Building package %s... ", display_name); + + const Build::BuildPackageConfig build_config{ + action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO), + action.spec.triplet(), + paths.port_dir(action.spec), + build_package_options}; + const auto result = Build::build_package(paths, build_config, status_db); + if (result.code != Build::BuildResult::SUCCEEDED) + { + System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); + return result.code; + } + System::println("Building package %s... done", display_name); + + const BinaryParagraph bpgh = + Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); + System::println("Installing package %s... ", display_name); + install_package(paths, bpgh, &status_db); + System::println(System::Color::success, "Installing package %s... done", display_name); + return BuildResult::SUCCEEDED; + } + + if (plan_type == InstallPlanType::INSTALL) + { + if (use_head_version && is_user_requested) + { + System::println( + System::Color::warning, "Package %s is already built -- not building from HEAD", display_name); + } + System::println("Installing package %s... ", display_name); + install_package(paths, action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO), &status_db); + System::println(System::Color::success, "Installing package %s... done", display_name); + return BuildResult::SUCCEEDED; + } + + Checks::unreachable(VCPKG_LINE_INFO); + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { static const std::string OPTION_DRY_RUN = "--dry-run"; @@ -315,80 +386,16 @@ namespace vcpkg::Commands::Install Checks::exit_success(VCPKG_LINE_INFO); } + const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), + Build::to_allow_downloads(!no_downloads)}; + // execute the plan for (const InstallPlanAction& action : install_plan) { - const std::string display_name = action.spec.to_string(); - - try - { - switch (action.plan_type) - { - case InstallPlanType::ALREADY_INSTALLED: - if (use_head_version && action.request_type == RequestType::USER_REQUESTED) - { - System::println(System::Color::warning, - "Package %s is already installed -- not building from HEAD", - display_name); - } - else - { - System::println(System::Color::success, "Package %s is already installed", display_name); - } - break; - case InstallPlanType::BUILD_AND_INSTALL: - { - Build::BuildPackageConfig build_config{ - action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO), - action.spec.triplet(), - paths.port_dir(action.spec), - }; - - build_config.use_head_version = - use_head_version && action.request_type == RequestType::USER_REQUESTED; - build_config.no_downloads = no_downloads; - - if (build_config.use_head_version) - System::println("Building package %s from HEAD... ", display_name); - else - System::println("Building package %s... ", display_name); - - const auto result = Build::build_package(paths, build_config, status_db); - if (result.code != Build::BuildResult::SUCCEEDED) - { - System::println(System::Color::error, - Build::create_error_message(result.code, action.spec)); - System::println(Build::create_user_troubleshooting_message(action.spec)); - Checks::exit_fail(VCPKG_LINE_INFO); - } - System::println("Building package %s... done", display_name); - - const BinaryParagraph bpgh = - Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); - System::println("Installing package %s... ", display_name); - install_package(paths, bpgh, &status_db); - System::println(System::Color::success, "Installing package %s... done", display_name); - break; - } - case InstallPlanType::INSTALL: - if (use_head_version && action.request_type == RequestType::USER_REQUESTED) - { - System::println(System::Color::warning, - "Package %s is already built -- not building from HEAD", - display_name); - } - System::println("Installing package %s... ", display_name); - install_package( - paths, action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO), &status_db); - System::println(System::Color::success, "Installing package %s... done", display_name); - break; - case InstallPlanType::UNKNOWN: - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - catch (const std::exception& e) + const BuildResult result = perform_install_plan_action(paths, action, install_plan_options, status_db); + if (result != BuildResult::SUCCEEDED) { - System::println(System::Color::error, "Error: Could not install package %s: %s", action.spec, e.what()); + System::println(Build::create_user_troubleshooting_message(action.spec)); Checks::exit_fail(VCPKG_LINE_INFO); } } diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index 817febe2f..91e4552ec 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -132,17 +132,17 @@ namespace vcpkg::Build const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); - const std::wstring cmd_launch_cmake = - make_cmake_cmd(cmake_exe_path, - ports_cmake_script_path, - {{L"CMD", L"BUILD"}, - {L"PORT", config.src.name}, - {L"CURRENT_PORT_DIR", config.port_dir / "/."}, - {L"TARGET_TRIPLET", triplet.canonical_name()}, - {L"VCPKG_PLATFORM_TOOLSET", toolset.version}, - {L"VCPKG_USE_HEAD_VERSION", config.use_head_version ? L"1" : L"0"}, - {L"_VCPKG_NO_DOWNLOADS", config.no_downloads ? L"1" : L"0"}, - {L"GIT", git_exe_path}}); + const std::wstring cmd_launch_cmake = make_cmake_cmd( + cmake_exe_path, + ports_cmake_script_path, + {{L"CMD", L"BUILD"}, + {L"PORT", config.src.name}, + {L"CURRENT_PORT_DIR", config.port_dir / "/."}, + {L"TARGET_TRIPLET", triplet.canonical_name()}, + {L"VCPKG_PLATFORM_TOOLSET", toolset.version}, + {L"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? L"1" : L"0"}, + {L"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? L"1" : L"0"}, + {L"GIT", git_exe_path}}); const std::wstring command = Strings::wformat(LR"(%s && %s)", cmd_set_environment, cmd_launch_cmake); -- cgit v1.2.3 From 831f0631f7eea7aebad5fcce95c0bbf0e0cdff68 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 6 Jun 2017 16:08:36 -0700 Subject: [vcpkg] Added parser support for 'Supports' field --- toolsrc/src/BinaryParagraph.cpp | 2 +- toolsrc/src/SourceParagraph.cpp | 80 +++++++++++++++++++++++++++++--------- toolsrc/src/tests_dependencies.cpp | 65 ++++++++++++++++++++++++++++++- toolsrc/src/tests_paragraph.cpp | 23 ++++++++++- 4 files changed, 147 insertions(+), 23 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index d545eee2a..21980cd7d 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -42,7 +42,7 @@ namespace vcpkg Checks::check_exit(VCPKG_LINE_INFO, multi_arch == "same", "Multi-Arch must be 'same' but was %s", multi_arch); std::string deps = details::remove_optional_field(&fields, BinaryParagraphOptionalField::DEPENDS); - this->depends = parse_depends(deps); + this->depends = parse_comma_list(deps); } BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const Triplet& triplet) diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index c77659176..2508af1e8 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -5,6 +5,7 @@ #include "vcpkg_Checks.h" #include "vcpkg_Maps.h" #include "vcpkg_System.h" +#include "vcpkg_Util.h" #include "vcpkg_expected.h" #include "vcpkglib_helpers.h" @@ -23,6 +24,7 @@ namespace vcpkg static const std::string DESCRIPTION = "Description"; static const std::string MAINTAINER = "Maintainer"; static const std::string BUILD_DEPENDS = "Build-Depends"; + static const std::string SUPPORTS = "Supports"; } static const std::vector& get_list_of_valid_fields() @@ -32,7 +34,8 @@ namespace vcpkg SourceParagraphOptionalField::DESCRIPTION, SourceParagraphOptionalField::MAINTAINER, - SourceParagraphOptionalField::BUILD_DEPENDS}; + SourceParagraphOptionalField::BUILD_DEPENDS, + SourceParagraphOptionalField::SUPPORTS}; return valid_fields; } @@ -72,7 +75,10 @@ namespace vcpkg sparagraph.maintainer = details::remove_optional_field(&fields, SourceParagraphOptionalField::MAINTAINER); std::string deps = details::remove_optional_field(&fields, SourceParagraphOptionalField::BUILD_DEPENDS); - sparagraph.depends = expand_qualified_dependencies(parse_depends(deps)); + sparagraph.depends = expand_qualified_dependencies(parse_comma_list(deps)); + + std::string sups = details::remove_optional_field(&fields, SourceParagraphOptionalField::SUPPORTS); + sparagraph.supports = parse_comma_list(sups); if (!fields.empty()) { @@ -89,7 +95,7 @@ namespace vcpkg std::vector vcpkg::expand_qualified_dependencies(const std::vector& depends) { - auto convert = [&](const std::string& depend_string) -> Dependency { + return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency { auto pos = depend_string.find(' '); if (pos == std::string::npos) return {depend_string, ""}; // expect of the form "\w+ \[\w+\]" @@ -102,21 +108,12 @@ namespace vcpkg } dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3); return dep; - }; - - std::vector ret; - - for (auto&& depend_string : depends) - { - ret.push_back(convert(depend_string)); - } - - return ret; + }); } - std::vector parse_depends(const std::string& depends_string) + std::vector parse_comma_list(const std::string& str) { - if (depends_string.empty()) + if (str.empty()) { return {}; } @@ -126,17 +123,17 @@ namespace vcpkg size_t cur = 0; do { - auto pos = depends_string.find(',', cur); + auto pos = str.find(',', cur); if (pos == std::string::npos) { - out.push_back(depends_string.substr(cur)); + out.push_back(str.substr(cur)); break; } - out.push_back(depends_string.substr(cur, pos - cur)); + out.push_back(str.substr(cur, pos - cur)); // skip comma and space ++pos; - if (depends_string[pos] == ' ') + if (str[pos] == ' ') { ++pos; } @@ -161,4 +158,49 @@ namespace vcpkg } const std::string& to_string(const Dependency& dep) { return dep.name; } + + ExpectedT> Supports::parse(const std::vector& strs) + { + Supports ret; + std::vector unrecognized; + + for (auto&& str : strs) + { + if (str == "x64") + ret.architectures.push_back(Architecture::X64); + else if (str == "x86") + ret.architectures.push_back(Architecture::X86); + else if (str == "arm") + ret.architectures.push_back(Architecture::ARM); + else if (str == "windows") + ret.platforms.push_back(Platform::WINDOWS); + else if (str == "uwp") + ret.platforms.push_back(Platform::UWP); + else if (str == "v140") + ret.toolsets.push_back(ToolsetVersion::V140); + else if (str == "v141") + ret.toolsets.push_back(ToolsetVersion::V141); + else if (str == "crt-static") + ret.crt_linkages.push_back(Linkage::STATIC); + else if (str == "crt-dynamic") + ret.crt_linkages.push_back(Linkage::DYNAMIC); + else + unrecognized.push_back(str); + } + + if (unrecognized.empty()) + return std::move(ret); + else + return std::move(unrecognized); + } + + bool Supports::supports(Architecture arch, Platform plat, Linkage crt, ToolsetVersion tools) + { + auto is_in_or_empty = [](auto v, auto&& c) -> bool { return c.empty() || c.end() != Util::find(c, v); }; + if (!is_in_or_empty(arch, architectures)) return false; + if (!is_in_or_empty(plat, platforms)) return false; + if (!is_in_or_empty(crt, crt_linkages)) return false; + if (!is_in_or_empty(tools, toolsets)) return false; + return true; + } } diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp index 3aabed80e..fdf2afea8 100644 --- a/toolsrc/src/tests_dependencies.cpp +++ b/toolsrc/src/tests_dependencies.cpp @@ -15,7 +15,7 @@ namespace UnitTest1 { TEST_METHOD(parse_depends_one) { - auto v = expand_qualified_dependencies(parse_depends("libA [windows]")); + auto v = expand_qualified_dependencies(parse_comma_list("libA [windows]")); Assert::AreEqual(size_t(1), v.size()); Assert::AreEqual("libA", v[0].name.c_str()); Assert::AreEqual("windows", v[0].qualifier.c_str()); @@ -23,7 +23,7 @@ namespace UnitTest1 TEST_METHOD(filter_depends) { - auto deps = expand_qualified_dependencies(parse_depends("libA [windows], libB, libC [uwp]")); + auto deps = expand_qualified_dependencies(parse_comma_list("libA [windows], libB, libC [uwp]")); auto v = filter_dependencies(deps, Triplet::X64_WINDOWS); Assert::AreEqual(size_t(2), v.size()); Assert::AreEqual("libA", v[0].c_str()); @@ -35,4 +35,65 @@ namespace UnitTest1 Assert::AreEqual("libC", v2[1].c_str()); } }; + + class SupportsTests : public TestClass + { + TEST_METHOD(parse_supports_all) + { + auto v = Supports::parse({ + "x64", "x86", "arm", "windows", "uwp", "v140", "v141", "crt-static", "crt-dynamic", + }); + Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); + + Assert::IsTrue(v.get()->supports(System::CPUArchitecture::X64, + Supports::Platform::UWP, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsTrue(v.get()->supports(System::CPUArchitecture::ARM, + Supports::Platform::WINDOWS, + Supports::Linkage::STATIC, + Supports::ToolsetVersion::V141)); + } + + TEST_METHOD(parse_supports_invalid) + { + auto v = Supports::parse({"arm64"}); + Assert::AreEqual(uintptr_t(0), uintptr_t(v.get())); + Assert::AreEqual(size_t(1), v.error().size()); + Assert::AreEqual("arm64", v.error()[0].c_str()); + } + + TEST_METHOD(parse_supports_case_sensitive) + { + auto v = Supports::parse({"Windows"}); + Assert::AreEqual(uintptr_t(0), uintptr_t(v.get())); + Assert::AreEqual(size_t(1), v.error().size()); + Assert::AreEqual("Windows", v.error()[0].c_str()); + } + + TEST_METHOD(parse_supports_some) + { + auto v = Supports::parse({ + "x64", "x86", "windows", + }); + Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); + + Assert::IsTrue(v.get()->supports(System::CPUArchitecture::X64, + Supports::Platform::WINDOWS, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsFalse(v.get()->supports(System::CPUArchitecture::ARM, + Supports::Platform::WINDOWS, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsFalse(v.get()->supports(System::CPUArchitecture::X64, + Supports::Platform::UWP, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsTrue(v.get()->supports(System::CPUArchitecture::X64, + Supports::Platform::WINDOWS, + Supports::Linkage::STATIC, + Supports::ToolsetVersion::V141)); + } + }; } diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index 1c77b437b..374e4ddd1 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -40,7 +40,12 @@ namespace UnitTest1 TEST_METHOD(SourceParagraph_Construct_Maximum) { auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ - {"Source", "s"}, {"Version", "v"}, {"Maintainer", "m"}, {"Description", "d"}, {"Build-Depends", "bd"}, + {"Source", "s"}, + {"Version", "v"}, + {"Maintainer", "m"}, + {"Description", "d"}, + {"Build-Depends", "bd"}, + {"Supports", "x64"}, }); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); @@ -51,6 +56,8 @@ namespace UnitTest1 Assert::AreEqual("d", pgh.description.c_str()); Assert::AreEqual(size_t(1), pgh.depends.size()); Assert::AreEqual("bd", pgh.depends[0].name.c_str()); + Assert::AreEqual(size_t(1), pgh.supports.size()); + Assert::AreEqual("x64", pgh.supports[0].c_str()); } TEST_METHOD(SourceParagraph_Two_Depends) @@ -80,6 +87,20 @@ namespace UnitTest1 Assert::AreEqual("xyz", pgh.depends[2].name.c_str()); } + TEST_METHOD(SourceParagraph_Three_Supports) + { + auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ + {"Source", "zlib"}, {"Version", "1.2.8"}, {"Supports", "x64, windows, uwp"}, + }); + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); + + Assert::AreEqual(size_t(3), pgh.supports.size()); + Assert::AreEqual("x64", pgh.supports[0].c_str()); + Assert::AreEqual("windows", pgh.supports[1].c_str()); + Assert::AreEqual("uwp", pgh.supports[2].c_str()); + } + TEST_METHOD(SourceParagraph_Construct_Qualified_Depends) { auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ -- cgit v1.2.3 From 9a698d7088beb3fa32b1b9d0321781c0ba07e18e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 6 Jun 2017 16:30:01 -0700 Subject: Convert BuildType/Configuration Type into simple enum classes --- toolsrc/src/PostBuildLint.cpp | 15 +++++----- toolsrc/src/PostBuildLint_BuildType.cpp | 12 ++++---- toolsrc/src/PostBuildLint_ConfigurationType.cpp | 24 --------------- toolsrc/src/PostBuildLint_LinkageType.cpp | 39 ------------------------- toolsrc/src/vcpkg_Build.cpp | 31 +++++++++++--------- 5 files changed, 31 insertions(+), 90 deletions(-) delete mode 100644 toolsrc/src/PostBuildLint_ConfigurationType.cpp delete mode 100644 toolsrc/src/PostBuildLint_LinkageType.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 363346ab6..82d50a68f 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -777,7 +777,7 @@ namespace vcpkg::PostBuildLint switch (build_info.library_linkage) { - case LinkageType::BackingEnum::DYNAMIC: + case Build::LinkageType::DYNAMIC: { std::vector debug_dlls = fs.get_files_recursive(debug_bin_dir); Util::unstable_keep_if(debug_dlls, has_extension_pred(fs, ".dll")); @@ -802,7 +802,7 @@ namespace vcpkg::PostBuildLint error_count += check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info); break; } - case LinkageType::BackingEnum::STATIC: + case Build::LinkageType::STATIC: { std::vector dlls = fs.get_files_recursive(package_dir); Util::unstable_keep_if(dlls, has_extension_pred(fs, ".dll")); @@ -812,18 +812,17 @@ namespace vcpkg::PostBuildLint if (!build_info.policies.is_enabled(BuildPolicy::ONLY_RELEASE_CRT)) { - error_count += check_crt_linkage_of_libs( - BuildType::value_of(ConfigurationTypeC::DEBUG, build_info.crt_linkage), - debug_libs, - toolset.dumpbin); + error_count += + check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::DEBUG, build_info.crt_linkage), + debug_libs, + toolset.dumpbin); } error_count += - check_crt_linkage_of_libs(BuildType::value_of(ConfigurationTypeC::RELEASE, build_info.crt_linkage), + check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::RELEASE, build_info.crt_linkage), release_libs, toolset.dumpbin); break; } - case LinkageType::BackingEnum::NULLVALUE: default: Checks::unreachable(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/PostBuildLint_BuildType.cpp b/toolsrc/src/PostBuildLint_BuildType.cpp index e690036d2..649f0ccca 100644 --- a/toolsrc/src/PostBuildLint_BuildType.cpp +++ b/toolsrc/src/PostBuildLint_BuildType.cpp @@ -5,24 +5,24 @@ namespace vcpkg::PostBuildLint { - BuildType BuildType::value_of(const ConfigurationType& config, const LinkageType& linkage) + BuildType BuildType::value_of(const ConfigurationType& config, const Build::LinkageType& linkage) { - if (config == ConfigurationTypeC::DEBUG && linkage == LinkageTypeC::STATIC) + if (config == ConfigurationType::DEBUG && linkage == Build::LinkageType::STATIC) { return BuildTypeC::DEBUG_STATIC; } - if (config == ConfigurationTypeC::DEBUG && linkage == LinkageTypeC::DYNAMIC) + if (config == ConfigurationType::DEBUG && linkage == Build::LinkageType::DYNAMIC) { return BuildTypeC::DEBUG_DYNAMIC; } - if (config == ConfigurationTypeC::RELEASE && linkage == LinkageTypeC::STATIC) + if (config == ConfigurationType::RELEASE && linkage == Build::LinkageType::STATIC) { return BuildTypeC::RELEASE_STATIC; } - if (config == ConfigurationTypeC::RELEASE && linkage == LinkageTypeC::DYNAMIC) + if (config == ConfigurationType::RELEASE && linkage == Build::LinkageType::DYNAMIC) { return BuildTypeC::RELEASE_DYNAMIC; } @@ -32,7 +32,7 @@ namespace vcpkg::PostBuildLint const ConfigurationType& BuildType::config() const { return this->m_config; } - const LinkageType& BuildType::linkage() const { return this->m_linkage; } + const Build::LinkageType& BuildType::linkage() const { return this->m_linkage; } const std::regex& BuildType::crt_regex() const { diff --git a/toolsrc/src/PostBuildLint_ConfigurationType.cpp b/toolsrc/src/PostBuildLint_ConfigurationType.cpp deleted file mode 100644 index eeccb1804..000000000 --- a/toolsrc/src/PostBuildLint_ConfigurationType.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "pch.h" - -#include "PackageSpec.h" -#include "PostBuildLint_ConfigurationType.h" -#include "vcpkg_Enums.h" - -namespace vcpkg::PostBuildLint -{ - static const std::string NULLVALUE_STRING = Enums::nullvalue_to_string(ConfigurationTypeC::ENUM_NAME); - - static const std::string NAME_DEBUG = "Debug"; - static const std::string NAME_RELEASE = "Release"; - - const std::string& ConfigurationType::to_string() const - { - switch (this->backing_enum) - { - case ConfigurationTypeC::DEBUG: return NAME_DEBUG; - case ConfigurationTypeC::RELEASE: return NAME_RELEASE; - case ConfigurationTypeC::NULLVALUE: return NULLVALUE_STRING; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } -} diff --git a/toolsrc/src/PostBuildLint_LinkageType.cpp b/toolsrc/src/PostBuildLint_LinkageType.cpp deleted file mode 100644 index 43bdbed7b..000000000 --- a/toolsrc/src/PostBuildLint_LinkageType.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "pch.h" - -#include "PostBuildLint_LinkageType.h" -#include "vcpkg_Checks.h" -#include "vcpkg_Enums.h" - -namespace vcpkg::PostBuildLint -{ - static const std::string NULLVALUE_STRING = Enums::nullvalue_to_string(LinkageTypeC::ENUM_NAME); - - static const std::string NAME_DYNAMIC = "dynamic"; - static const std::string NAME_STATIC = "static"; - - LinkageType LinkageType::value_of(const std::string& as_string) - { - if (as_string == NAME_DYNAMIC) - { - return LinkageTypeC::DYNAMIC; - } - - if (as_string == NAME_STATIC) - { - return LinkageTypeC::STATIC; - } - - return LinkageTypeC::NULLVALUE; - } - - const std::string& LinkageType::to_string() const - { - switch (this->backing_enum) - { - case LinkageTypeC::DYNAMIC: return NAME_DYNAMIC; - case LinkageTypeC::STATIC: return NAME_STATIC; - case LinkageTypeC::NULLVALUE: return NULLVALUE_STRING; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } -} diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index 91e4552ec..0ca6dc243 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -13,11 +13,15 @@ #include "vcpkglib.h" #include "vcpkglib_helpers.h" -using vcpkg::PostBuildLint::LinkageType; -namespace LinkageTypeC = vcpkg::PostBuildLint::LinkageTypeC; - namespace vcpkg::Build { + Optional to_linkage_type(const std::string& str) + { + if (str == "dynamic") return LinkageType::DYNAMIC; + if (str == "static") return LinkageType::STATIC; + return nullopt; + } + namespace BuildInfoRequiredField { static const std::string CRT_LINKAGE = "CRTLinkage"; @@ -217,19 +221,20 @@ namespace vcpkg::Build BuildInfo build_info; const std::string crt_linkage_as_string = details::remove_required_field(&pgh, BuildInfoRequiredField::CRT_LINKAGE); - build_info.crt_linkage = LinkageType::value_of(crt_linkage_as_string); - Checks::check_exit(VCPKG_LINE_INFO, - build_info.crt_linkage != LinkageTypeC::NULLVALUE, - "Invalid crt linkage type: [%s]", - crt_linkage_as_string); + + auto crtlinkage = to_linkage_type(crt_linkage_as_string); + if (auto p = crtlinkage.get()) + build_info.crt_linkage = *p; + else + Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid crt linkage type: [%s]", crt_linkage_as_string); const std::string library_linkage_as_string = details::remove_required_field(&pgh, BuildInfoRequiredField::LIBRARY_LINKAGE); - build_info.library_linkage = LinkageType::value_of(library_linkage_as_string); - Checks::check_exit(VCPKG_LINE_INFO, - build_info.library_linkage != LinkageTypeC::NULLVALUE, - "Invalid library linkage type: [%s]", - library_linkage_as_string); + auto liblinkage = to_linkage_type(library_linkage_as_string); + if (auto p = liblinkage.get()) + build_info.library_linkage = *p; + else + Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid library linkage type: [%s]", library_linkage_as_string); auto it_version = pgh.find("Version"); if (it_version != pgh.end()) -- cgit v1.2.3 From 247a6cec90004b8666d155eacc0f27d3a6c8fcf9 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 8 Jun 2017 00:36:17 -0700 Subject: [vcpkg] Improve diagnostics upon port load failure --- toolsrc/src/Paragraphs.cpp | 23 +++++++++----- toolsrc/src/SourceParagraph.cpp | 64 +++++++++++++++++++++----------------- toolsrc/src/commands_ci.cpp | 5 +-- toolsrc/src/commands_depends.cpp | 5 ++- toolsrc/src/commands_search.cpp | 25 +++++++++++++-- toolsrc/src/vcpkg_Dependencies.cpp | 6 ++-- 6 files changed, 82 insertions(+), 46 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index 13103d1f8..31e8f1da3 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -209,6 +209,7 @@ namespace vcpkg::Paragraphs { return SourceParagraph::parse_control_file(*p); } + error_info.name = path.filename().generic_u8string(); error_info.error = pghs.error(); return error_info; } @@ -226,25 +227,33 @@ namespace vcpkg::Paragraphs return pghs.error(); } - std::vector load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) + LoadResults try_load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) { - std::vector output; - std::vector port_errors; + LoadResults ret; for (auto&& path : fs.get_files_non_recursive(ports_dir)) { ExpectedT source_paragraph = try_load_port(fs, path); if (auto srcpgh = source_paragraph.get()) { - output.emplace_back(std::move(*srcpgh)); + ret.paragraphs.emplace_back(std::move(*srcpgh)); } else { - port_errors.emplace_back(source_paragraph.error()); + ret.errors.emplace_back(source_paragraph.error()); } } - print_error_message(port_errors); + return ret; + } - return output; + std::vector load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) + { + auto results = try_load_all_ports(fs, ports_dir); + if (!results.errors.empty()) + { + print_error_message(results.errors); + Checks::exit_fail(VCPKG_LINE_INFO); + } + return std::move(results.paragraphs); } std::map extract_port_names_and_versions( diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 2508af1e8..4001e891f 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -27,42 +27,52 @@ namespace vcpkg static const std::string SUPPORTS = "Supports"; } - static const std::vector& get_list_of_valid_fields() + static span get_list_of_valid_fields() { - static const std::vector valid_fields = {SourceParagraphRequiredField::SOURCE, - SourceParagraphRequiredField::VERSION, + static const std::string valid_fields[] = {SourceParagraphRequiredField::SOURCE, + SourceParagraphRequiredField::VERSION, - SourceParagraphOptionalField::DESCRIPTION, - SourceParagraphOptionalField::MAINTAINER, - SourceParagraphOptionalField::BUILD_DEPENDS, - SourceParagraphOptionalField::SUPPORTS}; + SourceParagraphOptionalField::DESCRIPTION, + SourceParagraphOptionalField::MAINTAINER, + SourceParagraphOptionalField::BUILD_DEPENDS, + SourceParagraphOptionalField::SUPPORTS}; return valid_fields; } - void print_error_message(const ParseControlErrorInfo& info) + void print_error_message(span error_info_list) { - System::println( - System::Color::error, "Error: There are invalid fields in the Source Paragraph of %s", info.name); - System::println("The following fields were not expected:\n\n %s\n\n", info.remaining_fields_as_string); - System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", info.valid_fields_as_string); - System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); - } + Checks::check_exit(VCPKG_LINE_INFO, error_info_list.size() > 0); - void print_error_message(std::vector error_info_list) - { - if (error_info_list.size() == 0) return; - for (ParseControlErrorInfo error_info : error_info_list) + for (auto&& error_info : error_info_list) { - System::println( - System::Color::error, "Error: There are invalid fields in the Source Paragraph of %s", error_info.name); - System::println("The following fields were not expected:\n\n %s\n\n", - error_info.remaining_fields_as_string); + if (error_info.error) + { + System::println( + System::Color::error, "Error: while loading %s: %s", error_info.name, error_info.error.message()); + } } - System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", - error_info_list.front().valid_fields_as_string); - System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); + bool have_remaining_fields = false; + for (auto&& error_info : error_info_list) + { + if (!error_info.remaining_fields_as_string.empty()) + { + System::println(System::Color::error, + "Error: There are invalid fields in the Source Paragraph of %s", + error_info.name); + System::println("The following fields were not expected:\n\n %s\n\n", + error_info.remaining_fields_as_string); + have_remaining_fields = true; + } + } + + if (have_remaining_fields) + { + System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", + Strings::join("\n ", get_list_of_valid_fields())); + System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); + } } ExpectedT SourceParagraph::parse_control_file( @@ -83,12 +93,10 @@ namespace vcpkg if (!fields.empty()) { const std::vector remaining_fields = Maps::extract_keys(fields); - const std::vector& valid_fields = get_list_of_valid_fields(); const std::string remaining_fields_as_string = Strings::join("\n ", remaining_fields); - const std::string valid_fields_as_string = Strings::join("\n ", valid_fields); - return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string, valid_fields_as_string}; + return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string}; } return sparagraph; } diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index bad1286f0..7e724f3ee 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -20,9 +20,10 @@ namespace vcpkg::Commands::CI const fs::path& ports_directory, const Triplet& triplet) { - std::vector ports = Paragraphs::load_all_ports(fs, ports_directory); + auto sources = Paragraphs::load_all_ports(fs, ports_directory); + std::vector specs; - for (const SourceParagraph& p : ports) + for (const SourceParagraph& p : sources) { specs.push_back(PackageSpec::from_name_and_triplet(p.name, triplet).value_or_exit(VCPKG_LINE_INFO)); } diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index ad33bbad4..9db4b7bb1 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -13,10 +13,9 @@ namespace vcpkg::Commands::DependInfo args.check_exact_arg_count(0, example); args.check_and_get_optional_command_arguments({}); - const std::vector source_paragraphs = - Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + auto sources = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - for (const SourceParagraph& source_paragraph : source_paragraphs) + for (const SourceParagraph& source_paragraph : sources) { auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name; }); System::println("%s: %s", source_paragraph.name, s); diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index 739aa0f43..4b7f49ba8 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -4,6 +4,7 @@ #include "SourceParagraph.h" #include "vcpkg_Commands.h" #include "vcpkg_System.h" +#include "vcpkglib.h" #include "vcpkglib_helpers.h" namespace vcpkg::Commands::Search @@ -61,8 +62,28 @@ namespace vcpkg::Commands::Search args.check_max_arg_count(1, example); const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_GRAPH}); - const std::vector source_paragraphs = - Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + + if (!sources_and_errors.errors.empty()) + { + if (vcpkg::g_debugging) + { + print_error_message(sources_and_errors.errors); + } + else + { + for (auto&& error : sources_and_errors.errors) + { + System::println( + System::Color::warning, "Warning: an error occurred while parsing '%s'\n", error.name); + } + System::println(System::Color::warning, + "Use '--debug' to get more information about the parse failures.\n"); + } + } + + auto& source_paragraphs = sources_and_errors.paragraphs; + if (options.find(OPTION_GRAPH) != options.cend()) { const std::string graph_as_string = create_graph_as_string(source_paragraphs); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index ea5832e46..f32d92f4c 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -179,10 +179,8 @@ namespace vcpkg::Dependencies if (auto spgh = maybe_spgh.get()) return InstallPlanAction{spec, {nullopt, nullopt, *spgh}, request_type}; - else - print_error_message(maybe_spgh.error()); - - Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); + print_error_message(maybe_spgh.error()); + Checks::exit_fail(VCPKG_LINE_INFO); } }; -- cgit v1.2.3 From 44a995d4461c54f0ff838af2649b618c533e60b7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 8 Jun 2017 04:36:11 -0700 Subject: [vcpkg] Hotfix previous commit. --- toolsrc/src/SourceParagraph.cpp | 2 +- toolsrc/src/tests_dependencies.cpp | 48 +++++++++++++++++++------------------- 2 files changed, 25 insertions(+), 25 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 4001e891f..3b770a4b4 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -202,7 +202,7 @@ namespace vcpkg return std::move(unrecognized); } - bool Supports::supports(Architecture arch, Platform plat, Linkage crt, ToolsetVersion tools) + bool Supports::is_supported(Architecture arch, Platform plat, Linkage crt, ToolsetVersion tools) { auto is_in_or_empty = [](auto v, auto&& c) -> bool { return c.empty() || c.end() != Util::find(c, v); }; if (!is_in_or_empty(arch, architectures)) return false; diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp index fdf2afea8..995d46873 100644 --- a/toolsrc/src/tests_dependencies.cpp +++ b/toolsrc/src/tests_dependencies.cpp @@ -45,14 +45,14 @@ namespace UnitTest1 }); Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); - Assert::IsTrue(v.get()->supports(System::CPUArchitecture::X64, - Supports::Platform::UWP, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsTrue(v.get()->supports(System::CPUArchitecture::ARM, - Supports::Platform::WINDOWS, - Supports::Linkage::STATIC, - Supports::ToolsetVersion::V141)); + Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::UWP, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::ARM, + Supports::Platform::WINDOWS, + Supports::Linkage::STATIC, + Supports::ToolsetVersion::V141)); } TEST_METHOD(parse_supports_invalid) @@ -78,22 +78,22 @@ namespace UnitTest1 }); Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); - Assert::IsTrue(v.get()->supports(System::CPUArchitecture::X64, - Supports::Platform::WINDOWS, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsFalse(v.get()->supports(System::CPUArchitecture::ARM, - Supports::Platform::WINDOWS, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsFalse(v.get()->supports(System::CPUArchitecture::X64, - Supports::Platform::UWP, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsTrue(v.get()->supports(System::CPUArchitecture::X64, - Supports::Platform::WINDOWS, - Supports::Linkage::STATIC, - Supports::ToolsetVersion::V141)); + Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::WINDOWS, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsFalse(v.get()->is_supported(System::CPUArchitecture::ARM, + Supports::Platform::WINDOWS, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsFalse(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::UWP, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::WINDOWS, + Supports::Linkage::STATIC, + Supports::ToolsetVersion::V141)); } }; } -- cgit v1.2.3 From e5dc2f9c8ff5dfe3266a0c144a1e21b96fa62e25 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 9 Jun 2017 23:45:52 -0700 Subject: [vcpkg] Rename --full-desc to --x-full-desc --- toolsrc/src/commands_list.cpp | 10 ++++------ toolsrc/src/commands_search.cpp | 20 +++++++++----------- 2 files changed, 13 insertions(+), 17 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp index 521fc5a9a..d21883fc2 100644 --- a/toolsrc/src/commands_list.cpp +++ b/toolsrc/src/commands_list.cpp @@ -7,16 +7,13 @@ namespace vcpkg::Commands::List { - static const std::string OPTION_FULLDESC = "--full-desc"; // TODO: This should find a better home, eventually + static const std::string OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually static void do_print(const StatusParagraph& pgh, bool FullDesc) { if (FullDesc) { - System::println("%-27s %-16s %s", - pgh.package.displayname(), - pgh.package.version, - pgh.package.description); + System::println("%-27s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description); } else { @@ -33,7 +30,8 @@ namespace vcpkg::Commands::List "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", Commands::Help::create_example_string("list png")); args.check_max_arg_count(1, example); - const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_FULLDESC}); + const std::unordered_set options = + args.check_and_get_optional_command_arguments({OPTION_FULLDESC}); const StatusParagraphs status_paragraphs = database_load_check(paths); std::vector installed_packages = get_installed_ports(status_paragraphs); diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index 6ec2a5395..bdb1e5d77 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -8,9 +8,8 @@ namespace vcpkg::Commands::Search { - static const std::string OPTION_GRAPH = "--graph"; // TODO: This should find a better home, eventually - static const std::string OPTION_FULLDESC = "--full-desc"; // TODO: This should find a better home, eventually - + static const std::string OPTION_GRAPH = "--graph"; // TODO: This should find a better home, eventually + static const std::string OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually static std::string replace_dashes_with_underscore(const std::string& input) { @@ -51,17 +50,15 @@ namespace vcpkg::Commands::Search { if (FullDesc) { - System::println("%-20s %-16s %s", - source_paragraph.name, - source_paragraph.version, - source_paragraph.description); + System::println( + "%-20s %-16s %s", source_paragraph.name, source_paragraph.version, source_paragraph.description); } else { System::println("%-20s %-16s %s", - source_paragraph.name, - source_paragraph.version, - details::shorten_description(source_paragraph.description)); + source_paragraph.name, + source_paragraph.version, + details::shorten_description(source_paragraph.description)); } } @@ -71,7 +68,8 @@ namespace vcpkg::Commands::Search "The argument should be a substring to search for, or no argument to display all libraries.\n%s", Commands::Help::create_example_string("search png")); args.check_max_arg_count(1, example); - const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC}); + const std::unordered_set options = + args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC}); const std::vector source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); -- cgit v1.2.3 From 687440f9760f3b9492de9a3105cdd6b99f9a3634 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 14 Jun 2017 22:06:52 -0700 Subject: [vcpkg] Add additional debug messages --- toolsrc/src/vcpkg_System.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 21329e003..c91c6be78 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -142,6 +142,7 @@ namespace vcpkg::System const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s 2>&1")###", cmd_line); + Debug::println("_wpopen(%s)", Strings::to_utf8(actual_cmd_line)); std::string output; char buf[1024]; auto pipe = _wpopen(actual_cmd_line.c_str(), L"r"); @@ -158,6 +159,7 @@ namespace vcpkg::System return {1, output}; } auto ec = _pclose(pipe); + Debug::println("_wpopen() returned %d", ec); return {ec, output}; } -- cgit v1.2.3 From bca0988023a8c7bfc896d0f5787eb02e74c6fb59 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Mon, 19 Jun 2017 15:06:15 -0700 Subject: [vcpkg] feature packages initial parsing --- toolsrc/src/Paragraphs.cpp | 21 ++++-- toolsrc/src/SourceParagraph.cpp | 62 +++++++++++++++-- toolsrc/src/VcpkgCmdArguments.cpp | 5 ++ toolsrc/src/commands_build.cpp | 32 +++++---- toolsrc/src/commands_build_external.cpp | 6 +- toolsrc/src/commands_ci.cpp | 6 +- toolsrc/src/commands_depends.cpp | 5 +- toolsrc/src/commands_portsdiff.cpp | 4 +- toolsrc/src/commands_search.cpp | 61 ++++++++++++----- toolsrc/src/commands_update.cpp | 4 +- toolsrc/src/tests_paragraph.cpp | 116 +++++++++++++++++--------------- toolsrc/src/vcpkg_Dependencies.cpp | 16 ++--- toolsrc/src/vcpkg_Input.cpp | 34 +++++++++- toolsrc/src/vcpkg_Strings.cpp | 5 ++ 14 files changed, 262 insertions(+), 115 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index 31e8f1da3..440d04ce4 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -201,13 +201,22 @@ namespace vcpkg::Paragraphs return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); } - ExpectedT try_load_port(const Files::Filesystem& fs, const fs::path& path) + ExpectedT try_load_port(const Files::Filesystem& fs, const fs::path& path) { ParseControlErrorInfo error_info; - Expected> pghs = get_single_paragraph(fs, path / "CONTROL"); - if (auto p = pghs.get()) + Expected>> pghs = get_paragraphs(fs, path / "CONTROL"); + if (auto vector_pghs = pghs.get()) { - return SourceParagraph::parse_control_file(*p); + auto csf = SourceControlFile::parse_control_file(std::move(*vector_pghs)); + if (!g_feature_packages) + { + if (auto ptr = csf.get()) + { + ptr->core_paragraph.default_features.clear(); + ptr->feature_paragraphs.clear(); + } + } + return csf; } error_info.name = path.filename().generic_u8string(); error_info.error = pghs.error(); @@ -232,7 +241,7 @@ namespace vcpkg::Paragraphs LoadResults ret; for (auto&& path : fs.get_files_non_recursive(ports_dir)) { - ExpectedT source_paragraph = try_load_port(fs, path); + ExpectedT source_paragraph = try_load_port(fs, path); if (auto srcpgh = source_paragraph.get()) { ret.paragraphs.emplace_back(std::move(*srcpgh)); @@ -245,7 +254,7 @@ namespace vcpkg::Paragraphs return ret; } - std::vector load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) + std::vector load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) { auto results = try_load_all_ports(fs, ports_dir); if (!results.errors.empty()) diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 3b770a4b4..a938feb99 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -12,7 +12,7 @@ namespace vcpkg { - // + bool g_feature_packages = false; namespace SourceParagraphRequiredField { static const std::string SOURCE = "Source"; @@ -25,6 +25,7 @@ namespace vcpkg static const std::string MAINTAINER = "Maintainer"; static const std::string BUILD_DEPENDS = "Build-Depends"; static const std::string SUPPORTS = "Supports"; + static const std::string DEFAULTFEATURES = "Default-Features"; } static span get_list_of_valid_fields() @@ -40,6 +41,17 @@ namespace vcpkg return valid_fields; } + namespace FeatureParagraphRequiredField + { + static const std::string FEATURE = "Feature"; + } + + namespace FeatureParagraphOptionalField + { + static const std::string DESCRIPTION = "Description"; + static const std::string BUILD_DEPENDS = "Build-Depends"; + } + void print_error_message(span error_info_list) { Checks::check_exit(VCPKG_LINE_INFO, error_info_list.size() > 0); @@ -74,11 +86,22 @@ namespace vcpkg System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); } } + std::vector getSourceParagraphs(const std::vector& control_files) + { + return Util::fmap(control_files, [](const SourceControlFile& x) { return x.core_paragraph; }); + } - ExpectedT SourceParagraph::parse_control_file( - std::unordered_map fields) + ExpectedT SourceControlFile::parse_control_file( + std::vector>&& control_paragraphs) { - SourceParagraph sparagraph; + if (control_paragraphs.size() == 0) + { + return ExpectedT(); + } + auto&& fields = control_paragraphs.front(); + + SourceControlFile control_file; + SourceParagraph& sparagraph = control_file.core_paragraph; sparagraph.name = details::remove_required_field(&fields, SourceParagraphRequiredField::SOURCE); sparagraph.version = details::remove_required_field(&fields, SourceParagraphRequiredField::VERSION); sparagraph.description = details::remove_optional_field(&fields, SourceParagraphOptionalField::DESCRIPTION); @@ -90,6 +113,9 @@ namespace vcpkg std::string sups = details::remove_optional_field(&fields, SourceParagraphOptionalField::SUPPORTS); sparagraph.supports = parse_comma_list(sups); + sparagraph.default_features = + details::remove_optional_field(&fields, SourceParagraphOptionalField::DEFAULTFEATURES); + if (!fields.empty()) { const std::vector remaining_fields = Maps::extract_keys(fields); @@ -98,7 +124,33 @@ namespace vcpkg return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string}; } - return sparagraph; + + control_paragraphs.erase(control_paragraphs.begin()); + + for (auto&& feature_pgh : control_paragraphs) + { + control_file.feature_paragraphs.emplace_back(std::make_unique()); + + FeatureParagraph& fparagraph = *control_file.feature_paragraphs.back(); + + fparagraph.name = details::remove_required_field(&feature_pgh, FeatureParagraphRequiredField::FEATURE); + fparagraph.description = + details::remove_required_field(&feature_pgh, FeatureParagraphOptionalField::DESCRIPTION); + std::string feature_deps = + details::remove_optional_field(&feature_pgh, FeatureParagraphOptionalField::BUILD_DEPENDS); + fparagraph.depends = expand_qualified_dependencies(parse_comma_list(feature_deps)); + + if (!feature_pgh.empty()) + { + const std::vector remaining_fields = Maps::extract_keys(feature_pgh); + + const std::string remaining_fields_as_string = Strings::join("\n ", remaining_fields); + + return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string}; + } + } + + return control_file; } std::vector vcpkg::expand_qualified_dependencies(const std::vector& depends) diff --git a/toolsrc/src/VcpkgCmdArguments.cpp b/toolsrc/src/VcpkgCmdArguments.cpp index 733308cb0..62e0b114c 100644 --- a/toolsrc/src/VcpkgCmdArguments.cpp +++ b/toolsrc/src/VcpkgCmdArguments.cpp @@ -117,6 +117,11 @@ namespace vcpkg parse_switch(false, "printmetrics", args.printmetrics); continue; } + if (arg == "--featurepackages") + { + g_feature_packages = true; + continue; + } args.optional_command_arguments.insert(arg); continue; diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index 5a5cd462e..a9e4f574e 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -19,11 +19,12 @@ namespace vcpkg::Commands::BuildCommand static const std::string OPTION_CHECKS_ONLY = "--checks-only"; - void perform_and_exit(const PackageSpec& spec, + void perform_and_exit(const FullPackageSpec& full_spec, const fs::path& port_dir, const std::unordered_set& options, const VcpkgPaths& paths) { + const PackageSpec& spec = full_spec.package_spec; if (options.find(OPTION_CHECKS_ONLY) != options.end()) { auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet()); @@ -33,25 +34,32 @@ namespace vcpkg::Commands::BuildCommand Checks::exit_success(VCPKG_LINE_INFO); } - const ExpectedT maybe_spgh = + const ExpectedT source_control_file = Paragraphs::try_load_port(paths.get_filesystem(), port_dir); - if (!maybe_spgh) + if (!source_control_file.has_value()) { - print_error_message(maybe_spgh.error()); + print_error_message(source_control_file.error()); Checks::exit_fail(VCPKG_LINE_INFO); } - const SourceParagraph& spgh = maybe_spgh.value_or_exit(VCPKG_LINE_INFO); + for (std::string str : full_spec.features) + { + System::println("%s \n", str); + } + const SourceControlFile& scf = source_control_file.value_or_exit(VCPKG_LINE_INFO); Checks::check_exit(VCPKG_LINE_INFO, - spec.name() == spgh.name, + spec.name() == scf.core_paragraph.name, "The Name: field inside the CONTROL does not match the port directory: '%s' != '%s'", - spgh.name, + scf.core_paragraph.name, spec.name()); StatusParagraphs status_db = database_load_check(paths); Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; - const Build::BuildPackageConfig build_config{spgh, spec.triplet(), paths.port_dir(spec), build_package_options}; + + const Build::BuildPackageConfig build_config{ + scf.core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options}; + const auto result = Build::build_package(paths, build_config, status_db); if (result.code == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES) { @@ -82,11 +90,11 @@ namespace vcpkg::Commands::BuildCommand static const std::string example = Commands::Help::create_example_string("build zlib:x64-windows"); args.check_exact_arg_count( 1, example); // Build only takes a single package and all dependencies must already be installed - const PackageSpec spec = - Input::check_and_get_package_spec(args.command_arguments.at(0), default_triplet, example); - Input::check_triplet(spec.triplet(), paths); + std::string command_argument = args.command_arguments.at(0); + const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, example); + Input::check_triplet(spec.package_spec.triplet(), paths); const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}); - perform_and_exit(spec, paths.port_dir(spec), options, paths); + perform_and_exit(spec, paths.port_dir(spec.package_spec), options, paths); } } diff --git a/toolsrc/src/commands_build_external.cpp b/toolsrc/src/commands_build_external.cpp index 2712ba0cf..ff70e9cf2 100644 --- a/toolsrc/src/commands_build_external.cpp +++ b/toolsrc/src/commands_build_external.cpp @@ -11,9 +11,9 @@ namespace vcpkg::Commands::BuildExternal static const std::string example = Commands::Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)"); args.check_exact_arg_count(2, example); - const PackageSpec spec = - Input::check_and_get_package_spec(args.command_arguments.at(0), default_triplet, example); - Input::check_triplet(spec.triplet(), paths); + const FullPackageSpec spec = + Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, example); + Input::check_triplet(spec.package_spec.triplet(), paths); const std::unordered_set options = args.check_and_get_optional_command_arguments({}); const fs::path port_dir = args.command_arguments.at(1); diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index 7e724f3ee..65e44e847 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -20,11 +20,11 @@ namespace vcpkg::Commands::CI const fs::path& ports_directory, const Triplet& triplet) { - auto sources = Paragraphs::load_all_ports(fs, ports_directory); - + auto ports = Paragraphs::load_all_ports(fs, ports_directory); std::vector specs; - for (const SourceParagraph& p : sources) + for (const SourceControlFile& control_file : ports) { + const SourceParagraph& p = control_file.core_paragraph; specs.push_back(PackageSpec::from_name_and_triplet(p.name, triplet).value_or_exit(VCPKG_LINE_INFO)); } diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index 9db4b7bb1..468bf5d72 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -13,10 +13,11 @@ namespace vcpkg::Commands::DependInfo args.check_exact_arg_count(0, example); args.check_and_get_optional_command_arguments({}); - auto sources = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + const auto source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - for (const SourceParagraph& source_paragraph : sources) + for (const SourceControlFile& source_control_file : source_control_files) { + const SourceParagraph& source_paragraph = source_control_file.core_paragraph; auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name; }); System::println("%s: %s", source_paragraph.name, s); } diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp index a614d654e..e872c394d 100644 --- a/toolsrc/src/commands_portsdiff.cpp +++ b/toolsrc/src/commands_portsdiff.cpp @@ -97,10 +97,10 @@ namespace vcpkg::Commands::PortsDiff L".vcpkg-root", git_exe.native()); System::cmd_execute_clean(cmd); - const std::vector source_paragraphs = + const std::vector source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); const std::map names_and_versions = - Paragraphs::extract_port_names_and_versions(source_paragraphs); + Paragraphs::extract_port_names_and_versions(getSourceParagraphs(source_control_files)); fs.remove_all(temp_checkout_path, ec); return names_and_versions; } diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index 0f8ebbb3b..b39d21887 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -19,15 +19,16 @@ namespace vcpkg::Commands::Search return output; } - static std::string create_graph_as_string(const std::vector& source_paragraphs) + static std::string create_graph_as_string(const std::vector& source_control_files) { int empty_node_count = 0; std::string s; s.append("digraph G{ rankdir=LR; edge [minlen=3]; overlap=false;"); - for (const SourceParagraph& source_paragraph : source_paragraphs) + for (const SourceControlFile& source_control_file : source_control_files) { + const SourceParagraph& source_paragraph = source_control_file.core_paragraph; if (source_paragraph.depends.empty()) { empty_node_count++; @@ -46,10 +47,9 @@ namespace vcpkg::Commands::Search s.append(Strings::format("empty [label=\"%d singletons...\"]; }", empty_node_count)); return s; } - - static void do_print(const SourceParagraph& source_paragraph, bool FullDesc) + static void do_print(const SourceParagraph& source_paragraph, bool full_desc) { - if (FullDesc) + if (full_desc) { System::println( "%-20s %-16s %s", source_paragraph.name, source_paragraph.version, source_paragraph.description); @@ -63,6 +63,20 @@ namespace vcpkg::Commands::Search } } + static void do_print(const std::string& name, const FeatureParagraph& feature_paragraph, bool full_desc) + { + if (full_desc) + { + System::println("%-37s %s", name + "[" + feature_paragraph.name + "]", feature_paragraph.description); + } + else + { + System::println("%-37s %s", + name + "[" + feature_paragraph.name + "]", + details::shorten_description(feature_paragraph.description)); + } + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { static const std::string example = Strings::format( @@ -85,7 +99,7 @@ namespace vcpkg::Commands::Search for (auto&& error : sources_and_errors.errors) { System::println( - System::Color::warning, "Warning: an error occurred while parsing '%s'\n", error.name); + System::Color::warning, "Warning: an error occurred while parsing '%s'", error.name); } System::println(System::Color::warning, "Use '--debug' to get more information about the parse failures.\n"); @@ -93,7 +107,6 @@ namespace vcpkg::Commands::Search } auto& source_paragraphs = sources_and_errors.paragraphs; - if (options.find(OPTION_GRAPH) != options.cend()) { const std::string graph_as_string = create_graph_as_string(source_paragraphs); @@ -103,27 +116,41 @@ namespace vcpkg::Commands::Search if (args.command_arguments.empty()) { - for (const SourceParagraph& source_paragraph : source_paragraphs) + for (const SourceControlFile& source_control_file : source_paragraphs) { - do_print(source_paragraph, options.find(OPTION_FULLDESC) != options.cend()); + do_print(source_control_file.core_paragraph, options.find(OPTION_FULLDESC) != options.cend()); + for (auto&& feature_paragraph : source_control_file.feature_paragraphs) + { + do_print(source_control_file.core_paragraph.name, + *feature_paragraph, + options.find(OPTION_FULLDESC) != options.cend()); + } } } else { + const auto& icontains = Strings::case_insensitive_ascii_contains; + // At this point there is 1 argument - for (const SourceParagraph& source_paragraph : source_paragraphs) + auto&& args_zero = args.command_arguments[0]; + for (const SourceControlFile& source_control_file : source_paragraphs) { - if (Strings::case_insensitive_ascii_find(source_paragraph.name, args.command_arguments[0]) == - source_paragraph.name.end()) + auto&& sp = source_control_file.core_paragraph; + + bool contains_name = icontains(sp.name, args_zero); + if (contains_name || icontains(sp.description, args_zero)) { - if (Strings::case_insensitive_ascii_find(source_paragraph.description, args.command_arguments[0]) == - source_paragraph.description.end()) + do_print(sp, options.find(OPTION_FULLDESC) != options.cend()); + } + + for (auto&& feature_paragraph : source_control_file.feature_paragraphs) + { + if (contains_name || icontains(feature_paragraph->name, args_zero) || + icontains(feature_paragraph->description, args_zero)) { - continue; + do_print(sp.name, *feature_paragraph, options.find(OPTION_FULLDESC) != options.cend()); } } - - do_print(source_paragraph, options.find(OPTION_FULLDESC) != options.cend()); } } diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp index f87ccfb06..f00a89da4 100644 --- a/toolsrc/src/commands_update.cpp +++ b/toolsrc/src/commands_update.cpp @@ -15,8 +15,8 @@ namespace vcpkg::Commands::Update std::vector find_outdated_packages(const VcpkgPaths& paths, const StatusParagraphs& status_db) { - const std::vector source_paragraphs = - Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + auto source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + const std::vector source_paragraphs = getSourceParagraphs(source_control_files); const std::map src_names_to_versions = Paragraphs::extract_port_names_and_versions(source_paragraphs); const std::vector installed_packages = get_installed_ports(status_db); diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index 374e4ddd1..8dff520fb 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -25,99 +25,107 @@ namespace UnitTest1 { TEST_METHOD(SourceParagraph_Construct_Minimum) { - auto m_pgh = vcpkg::SourceParagraph::parse_control_file({{"Source", "zlib"}, {"Version", "1.2.8"}}); + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "zlib"}, {"Version", "1.2.8"}, + }}); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual("zlib", pgh.name.c_str()); - Assert::AreEqual("1.2.8", pgh.version.c_str()); - Assert::AreEqual("", pgh.maintainer.c_str()); - Assert::AreEqual("", pgh.description.c_str()); - Assert::AreEqual(size_t(0), pgh.depends.size()); + Assert::AreEqual("zlib", pgh.core_paragraph.name.c_str()); + Assert::AreEqual("1.2.8", pgh.core_paragraph.version.c_str()); + Assert::AreEqual("", pgh.core_paragraph.maintainer.c_str()); + Assert::AreEqual("", pgh.core_paragraph.description.c_str()); + Assert::AreEqual(size_t(0), pgh.core_paragraph.depends.size()); } TEST_METHOD(SourceParagraph_Construct_Maximum) { - auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ - {"Source", "s"}, - {"Version", "v"}, - {"Maintainer", "m"}, - {"Description", "d"}, - {"Build-Depends", "bd"}, - {"Supports", "x64"}, - }); + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "s"}, + {"Version", "v"}, + {"Maintainer", "m"}, + {"Description", "d"}, + {"Build-Depends", "bd"}, + {"Supports", "x64"}, + }}); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual("s", pgh.name.c_str()); - Assert::AreEqual("v", pgh.version.c_str()); - Assert::AreEqual("m", pgh.maintainer.c_str()); - Assert::AreEqual("d", pgh.description.c_str()); - Assert::AreEqual(size_t(1), pgh.depends.size()); - Assert::AreEqual("bd", pgh.depends[0].name.c_str()); - Assert::AreEqual(size_t(1), pgh.supports.size()); - Assert::AreEqual("x64", pgh.supports[0].c_str()); + Assert::AreEqual("s", pgh.core_paragraph.name.c_str()); + Assert::AreEqual("v", pgh.core_paragraph.version.c_str()); + Assert::AreEqual("m", pgh.core_paragraph.maintainer.c_str()); + Assert::AreEqual("d", pgh.core_paragraph.description.c_str()); + Assert::AreEqual(size_t(1), pgh.core_paragraph.depends.size()); + Assert::AreEqual("bd", pgh.core_paragraph.depends[0].name.c_str()); + Assert::AreEqual(size_t(1), pgh.core_paragraph.supports.size()); + Assert::AreEqual("x64", pgh.core_paragraph.supports[0].c_str()); } TEST_METHOD(SourceParagraph_Two_Depends) { - auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ - {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl"}, - }); + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl"}, + }}); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual(size_t(2), pgh.depends.size()); - Assert::AreEqual("z", pgh.depends[0].name.c_str()); - Assert::AreEqual("openssl", pgh.depends[1].name.c_str()); + Assert::AreEqual(size_t(2), pgh.core_paragraph.depends.size()); + Assert::AreEqual("z", pgh.core_paragraph.depends[0].name.c_str()); + Assert::AreEqual("openssl", pgh.core_paragraph.depends[1].name.c_str()); } TEST_METHOD(SourceParagraph_Three_Depends) { - auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ - {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl, xyz"}, - }); + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl, xyz"}, + }}); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual(size_t(3), pgh.depends.size()); - Assert::AreEqual("z", pgh.depends[0].name.c_str()); - Assert::AreEqual("openssl", pgh.depends[1].name.c_str()); - Assert::AreEqual("xyz", pgh.depends[2].name.c_str()); + Assert::AreEqual(size_t(3), pgh.core_paragraph.depends.size()); + Assert::AreEqual("z", pgh.core_paragraph.depends[0].name.c_str()); + Assert::AreEqual("openssl", pgh.core_paragraph.depends[1].name.c_str()); + Assert::AreEqual("xyz", pgh.core_paragraph.depends[2].name.c_str()); } TEST_METHOD(SourceParagraph_Three_Supports) { - auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ - {"Source", "zlib"}, {"Version", "1.2.8"}, {"Supports", "x64, windows, uwp"}, - }); + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "zlib"}, {"Version", "1.2.8"}, {"Supports", "x64, windows, uwp"}, + }}); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual(size_t(3), pgh.supports.size()); - Assert::AreEqual("x64", pgh.supports[0].c_str()); - Assert::AreEqual("windows", pgh.supports[1].c_str()); - Assert::AreEqual("uwp", pgh.supports[2].c_str()); + Assert::AreEqual(size_t(3), pgh.core_paragraph.supports.size()); + Assert::AreEqual("x64", pgh.core_paragraph.supports[0].c_str()); + Assert::AreEqual("windows", pgh.core_paragraph.supports[1].c_str()); + Assert::AreEqual("uwp", pgh.core_paragraph.supports[2].c_str()); } TEST_METHOD(SourceParagraph_Construct_Qualified_Depends) { - auto m_pgh = vcpkg::SourceParagraph::parse_control_file({ - {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA [windows], libB [uwp]"}, - }); + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA [windows], libB [uwp]"}, + }}); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual("zlib", pgh.name.c_str()); - Assert::AreEqual("1.2.8", pgh.version.c_str()); - Assert::AreEqual("", pgh.maintainer.c_str()); - Assert::AreEqual("", pgh.description.c_str()); - Assert::AreEqual(size_t(2), pgh.depends.size()); - Assert::AreEqual("libA", pgh.depends[0].name.c_str()); - Assert::AreEqual("windows", pgh.depends[0].qualifier.c_str()); - Assert::AreEqual("libB", pgh.depends[1].name.c_str()); - Assert::AreEqual("uwp", pgh.depends[1].qualifier.c_str()); + Assert::AreEqual("zlib", pgh.core_paragraph.name.c_str()); + Assert::AreEqual("1.2.8", pgh.core_paragraph.version.c_str()); + Assert::AreEqual("", pgh.core_paragraph.maintainer.c_str()); + Assert::AreEqual("", pgh.core_paragraph.description.c_str()); + Assert::AreEqual(size_t(2), pgh.core_paragraph.depends.size()); + Assert::AreEqual("libA", pgh.core_paragraph.depends[0].name.c_str()); + Assert::AreEqual("windows", pgh.core_paragraph.depends[0].qualifier.c_str()); + Assert::AreEqual("libB", pgh.core_paragraph.depends[1].name.c_str()); + Assert::AreEqual("uwp", pgh.core_paragraph.depends[1].qualifier.c_str()); } TEST_METHOD(BinaryParagraph_Construct_Minimum) diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index f32d92f4c..add8acb4d 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -174,12 +174,12 @@ namespace vcpkg::Dependencies if (auto bpgh = maybe_bpgh.get()) return InstallPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type}; - ExpectedT maybe_spgh = + ExpectedT source_control_file = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); - if (auto spgh = maybe_spgh.get()) - return InstallPlanAction{spec, {nullopt, nullopt, *spgh}, request_type}; + if (auto scf = source_control_file.get()) + return InstallPlanAction{spec, {nullopt, nullopt, (*scf).core_paragraph}, request_type}; - print_error_message(maybe_spgh.error()); + print_error_message(source_control_file.error()); Checks::exit_fail(VCPKG_LINE_INFO); } }; @@ -284,13 +284,13 @@ namespace vcpkg::Dependencies if (auto bpgh = maybe_bpgh.get()) return ExportPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type}; - ExpectedT maybe_spgh = + ExpectedT source_control_file = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); - if (auto spgh = maybe_spgh.get()) - return ExportPlanAction{spec, {nullopt, nullopt, *spgh}, request_type}; + if (auto scf = source_control_file.get()) + return ExportPlanAction{spec, {nullopt, nullopt, (*scf).core_paragraph}, request_type}; else - print_error_message(maybe_spgh.error()); + print_error_message(source_control_file.error()); Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); } diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp index df738315b..fdedd5507 100644 --- a/toolsrc/src/vcpkg_Input.cpp +++ b/toolsrc/src/vcpkg_Input.cpp @@ -15,7 +15,7 @@ namespace vcpkg::Input auto expected_spec = PackageSpec::from_string(as_lowercase, default_triplet); if (auto spec = expected_spec.get()) { - return *spec; + return PackageSpec{*spec}; } // Intentionally show the lowercased string @@ -34,4 +34,36 @@ namespace vcpkg::Input Checks::exit_fail(VCPKG_LINE_INFO); } } + + FullPackageSpec check_and_get_full_package_spec(const std::string& full_package_spec_as_string, + const Triplet& default_triplet, + CStringView example_text) + { + int left_pos = (int)full_package_spec_as_string.find('['); + if (left_pos == std::string::npos) + { + return FullPackageSpec{ + check_and_get_package_spec(full_package_spec_as_string, default_triplet, example_text)}; + } + int right_pos = (int)full_package_spec_as_string.find(']'); + if (left_pos >= right_pos) + { + System::println(System::Color::error, "Error: Argument is not formatted correctly \"%s\""); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + std::string package_spec_as_string = full_package_spec_as_string.substr(0, left_pos); + const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); + auto expected_spec = PackageSpec::from_string(as_lowercase, default_triplet); + if (auto&& spec = expected_spec.get()) + { + return {*spec, + parse_comma_list(full_package_spec_as_string.substr(left_pos + 1, right_pos - left_pos - 1))}; + } + + // Intentionally show the lowercased string + System::println(System::Color::error, "Error: %s: %s", vcpkg::to_string(expected_spec.error()), as_lowercase); + System::print(example_text); + Checks::exit_fail(VCPKG_LINE_INFO); + } } diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 9ba9eb700..aafed5fd3 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -68,6 +68,11 @@ namespace vcpkg::Strings [](const char a, const char b) { return details::tolower_char(a) == b; }); } + bool case_insensitive_ascii_contains(const std::string& s, const std::string& pattern) + { + return case_insensitive_ascii_find(s, pattern) != s.end(); + } + int case_insensitive_ascii_compare(const CStringView left, const CStringView right) { return _stricmp(left, right); -- cgit v1.2.3 From 8741214bf69d1209a1e6d405ed8561d27f04436a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 17 Jun 2017 02:39:14 -0700 Subject: [vcpkg] Use unique_ptr<> for paragraphs. Post-parser phase rework. --- toolsrc/src/BinaryParagraph.cpp | 46 ++++++---- toolsrc/src/Paragraphs.cpp | 38 ++++---- toolsrc/src/SourceParagraph.cpp | 149 +++++++++++++++----------------- toolsrc/src/StatusParagraph.cpp | 12 ++- toolsrc/src/commands_build.cpp | 12 +-- toolsrc/src/commands_ci.cpp | 13 ++- toolsrc/src/commands_depends.cpp | 4 +- toolsrc/src/commands_list.cpp | 3 +- toolsrc/src/commands_portsdiff.cpp | 6 +- toolsrc/src/commands_search.cpp | 28 +++--- toolsrc/src/commands_update.cpp | 7 +- toolsrc/src/tests_paragraph.cpp | 66 +++++++------- toolsrc/src/vcpkg_Build.cpp | 83 +++++++++--------- toolsrc/src/vcpkg_Build_BuildPolicy.cpp | 11 --- toolsrc/src/vcpkg_Dependencies.cpp | 19 ++-- toolsrc/src/vcpkg_Parse.cpp | 59 +++++++++++++ toolsrc/src/vcpkglib.cpp | 10 ++- toolsrc/src/vcpkglib_helpers.cpp | 56 ------------ 18 files changed, 307 insertions(+), 315 deletions(-) create mode 100644 toolsrc/src/vcpkg_Parse.cpp delete mode 100644 toolsrc/src/vcpkglib_helpers.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index 21980cd7d..af76c6b29 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -2,13 +2,11 @@ #include "BinaryParagraph.h" #include "vcpkg_Checks.h" -#include "vcpkglib_helpers.h" - -using namespace vcpkg::details; +#include "vcpkg_Parse.h" namespace vcpkg { - namespace BinaryParagraphRequiredField + namespace Fields { static const std::string PACKAGE = "Package"; static const std::string VERSION = "Version"; @@ -16,7 +14,7 @@ namespace vcpkg static const std::string MULTI_ARCH = "Multi-Arch"; } - namespace BinaryParagraphOptionalField + namespace Fields { static const std::string DESCRIPTION = "Description"; static const std::string MAINTAINER = "Maintainer"; @@ -27,22 +25,36 @@ namespace vcpkg BinaryParagraph::BinaryParagraph(std::unordered_map fields) { - const std::string name = details::remove_required_field(&fields, BinaryParagraphRequiredField::PACKAGE); - const std::string architecture = - details::remove_required_field(&fields, BinaryParagraphRequiredField::ARCHITECTURE); - const Triplet triplet = Triplet::from_canonical_name(architecture); + using namespace vcpkg::Parse; - this->spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO); - this->version = details::remove_required_field(&fields, BinaryParagraphRequiredField::VERSION); + ParagraphParser parser(std::move(fields)); - this->description = details::remove_optional_field(&fields, BinaryParagraphOptionalField::DESCRIPTION); - this->maintainer = details::remove_optional_field(&fields, BinaryParagraphOptionalField::MAINTAINER); + { + std::string name; + parser.required_field(Fields::PACKAGE, name); + std::string architecture; + parser.required_field(Fields::ARCHITECTURE, architecture); + this->spec = PackageSpec::from_name_and_triplet(name, Triplet::from_canonical_name(architecture)) + .value_or_exit(VCPKG_LINE_INFO); + } - std::string multi_arch = details::remove_required_field(&fields, BinaryParagraphRequiredField::MULTI_ARCH); - Checks::check_exit(VCPKG_LINE_INFO, multi_arch == "same", "Multi-Arch must be 'same' but was %s", multi_arch); + parser.required_field(Fields::VERSION, this->version); + this->description = parser.optional_field(Fields::DESCRIPTION); + this->maintainer = parser.optional_field(Fields::MAINTAINER); + + std::string multi_arch; + parser.required_field(Fields::MULTI_ARCH, multi_arch); - std::string deps = details::remove_optional_field(&fields, BinaryParagraphOptionalField::DEPENDS); - this->depends = parse_comma_list(deps); + this->depends = parse_comma_list(parser.optional_field(Fields::DEPENDS)); + + if (auto err = parser.error_info(this->spec.name())) + { + print_error_message(err); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + // prefer failing above when possible because it gives better information + Checks::check_exit(VCPKG_LINE_INFO, multi_arch == "same", "Multi-Arch must be 'same' but was %s", multi_arch); } BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const Triplet& triplet) diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index 440d04ce4..3749e919e 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -4,6 +4,8 @@ #include "Paragraphs.h" #include "vcpkg_Files.h" +using namespace vcpkg::Parse; + namespace vcpkg::Paragraphs { struct Parser @@ -201,9 +203,8 @@ namespace vcpkg::Paragraphs return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); } - ExpectedT try_load_port(const Files::Filesystem& fs, const fs::path& path) + ParseExpected try_load_port(const Files::Filesystem& fs, const fs::path& path) { - ParseControlErrorInfo error_info; Expected>> pghs = get_paragraphs(fs, path / "CONTROL"); if (auto vector_pghs = pghs.get()) { @@ -212,14 +213,16 @@ namespace vcpkg::Paragraphs { if (auto ptr = csf.get()) { - ptr->core_paragraph.default_features.clear(); - ptr->feature_paragraphs.clear(); + Checks::check_exit(VCPKG_LINE_INFO, ptr->get() != nullptr); + ptr->get()->core_paragraph->default_features.clear(); + ptr->get()->feature_paragraphs.clear(); } } return csf; } - error_info.name = path.filename().generic_u8string(); - error_info.error = pghs.error(); + auto error_info = std::make_unique(); + error_info->name = path.filename().generic_u8string(); + error_info->error = pghs.error(); return error_info; } @@ -241,20 +244,21 @@ namespace vcpkg::Paragraphs LoadResults ret; for (auto&& path : fs.get_files_non_recursive(ports_dir)) { - ExpectedT source_paragraph = try_load_port(fs, path); - if (auto srcpgh = source_paragraph.get()) + auto maybe_spgh = try_load_port(fs, path); + if (auto spgh = maybe_spgh.get()) { - ret.paragraphs.emplace_back(std::move(*srcpgh)); + ret.paragraphs.emplace_back(std::move(*spgh)); } else { - ret.errors.emplace_back(source_paragraph.error()); + ret.errors.emplace_back(std::move(maybe_spgh).error()); } } return ret; } - std::vector load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) + std::vector> load_all_ports(const Files::Filesystem& fs, + const fs::path& ports_dir) { auto results = try_load_all_ports(fs, ports_dir); if (!results.errors.empty()) @@ -265,14 +269,14 @@ namespace vcpkg::Paragraphs return std::move(results.paragraphs); } - std::map extract_port_names_and_versions( - const std::vector& source_paragraphs) + std::map load_all_port_names_and_versions(const Files::Filesystem& fs, + const fs::path& ports_dir) { + auto all_ports = load_all_ports(fs, ports_dir); + std::map names_and_versions; - for (const SourceParagraph& port : source_paragraphs) - { - names_and_versions.emplace(port.name, port.version); - } + for (auto&& port : all_ports) + names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version); return names_and_versions; } diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index a938feb99..83b8e2e2d 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -8,73 +8,56 @@ #include "vcpkg_Util.h" #include "vcpkg_expected.h" -#include "vcpkglib_helpers.h" - namespace vcpkg { - bool g_feature_packages = false; - namespace SourceParagraphRequiredField - { - static const std::string SOURCE = "Source"; - static const std::string VERSION = "Version"; - } + using namespace vcpkg::Parse; - namespace SourceParagraphOptionalField + bool g_feature_packages = false; + namespace Fields { + static const std::string BUILD_DEPENDS = "Build-Depends"; + static const std::string DEFAULTFEATURES = "Default-Features"; static const std::string DESCRIPTION = "Description"; + static const std::string FEATURE = "Feature"; static const std::string MAINTAINER = "Maintainer"; - static const std::string BUILD_DEPENDS = "Build-Depends"; + static const std::string SOURCE = "Source"; static const std::string SUPPORTS = "Supports"; - static const std::string DEFAULTFEATURES = "Default-Features"; + static const std::string VERSION = "Version"; } static span get_list_of_valid_fields() { - static const std::string valid_fields[] = {SourceParagraphRequiredField::SOURCE, - SourceParagraphRequiredField::VERSION, - - SourceParagraphOptionalField::DESCRIPTION, - SourceParagraphOptionalField::MAINTAINER, - SourceParagraphOptionalField::BUILD_DEPENDS, - SourceParagraphOptionalField::SUPPORTS}; + static const std::string valid_fields[] = { + Fields::SOURCE, Fields::VERSION, Fields::DESCRIPTION, Fields::MAINTAINER, Fields::BUILD_DEPENDS, + }; return valid_fields; } - namespace FeatureParagraphRequiredField - { - static const std::string FEATURE = "Feature"; - } - - namespace FeatureParagraphOptionalField - { - static const std::string DESCRIPTION = "Description"; - static const std::string BUILD_DEPENDS = "Build-Depends"; - } - - void print_error_message(span error_info_list) + void print_error_message(span> error_info_list) { Checks::check_exit(VCPKG_LINE_INFO, error_info_list.size() > 0); for (auto&& error_info : error_info_list) { - if (error_info.error) + Checks::check_exit(VCPKG_LINE_INFO, error_info != nullptr); + if (error_info->error) { System::println( - System::Color::error, "Error: while loading %s: %s", error_info.name, error_info.error.message()); + System::Color::error, "Error: while loading %s: %s", error_info->name, error_info->error.message()); } } bool have_remaining_fields = false; for (auto&& error_info : error_info_list) { - if (!error_info.remaining_fields_as_string.empty()) + if (!error_info->extra_fields.empty()) { System::println(System::Color::error, "Error: There are invalid fields in the Source Paragraph of %s", - error_info.name); + error_info->name); System::println("The following fields were not expected:\n\n %s\n\n", - error_info.remaining_fields_as_string); + Strings::join("\n ", error_info->extra_fields)); have_remaining_fields = true; } } @@ -86,71 +69,75 @@ namespace vcpkg System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); } } - std::vector getSourceParagraphs(const std::vector& control_files) + + static ParseExpected parse_source_paragraph(RawParagraph&& fields) { - return Util::fmap(control_files, [](const SourceControlFile& x) { return x.core_paragraph; }); + ParagraphParser parser(std::move(fields)); + + auto spgh = std::make_unique(); + + parser.required_field(Fields::SOURCE, spgh->name); + parser.required_field(Fields::VERSION, spgh->version); + + spgh->description = parser.optional_field(Fields::DESCRIPTION); + spgh->maintainer = parser.optional_field(Fields::MAINTAINER); + spgh->depends = expand_qualified_dependencies(parse_comma_list(parser.optional_field(Fields::BUILD_DEPENDS))); + spgh->supports = parse_comma_list(parser.optional_field(Fields::SUPPORTS)); + spgh->default_features = parse_comma_list(parser.optional_field(Fields::DEFAULTFEATURES)); + + auto err = parser.error_info(spgh->name); + if (err) + return std::move(err); + else + return std::move(spgh); } - ExpectedT SourceControlFile::parse_control_file( - std::vector>&& control_paragraphs) + static ParseExpected parse_feature_paragraph(RawParagraph&& fields) { - if (control_paragraphs.size() == 0) - { - return ExpectedT(); - } - auto&& fields = control_paragraphs.front(); + ParagraphParser parser(std::move(fields)); - SourceControlFile control_file; - SourceParagraph& sparagraph = control_file.core_paragraph; - sparagraph.name = details::remove_required_field(&fields, SourceParagraphRequiredField::SOURCE); - sparagraph.version = details::remove_required_field(&fields, SourceParagraphRequiredField::VERSION); - sparagraph.description = details::remove_optional_field(&fields, SourceParagraphOptionalField::DESCRIPTION); - sparagraph.maintainer = details::remove_optional_field(&fields, SourceParagraphOptionalField::MAINTAINER); + auto fpgh = std::make_unique(); - std::string deps = details::remove_optional_field(&fields, SourceParagraphOptionalField::BUILD_DEPENDS); - sparagraph.depends = expand_qualified_dependencies(parse_comma_list(deps)); + parser.required_field(Fields::FEATURE, fpgh->name); + parser.required_field(Fields::DESCRIPTION, fpgh->description); - std::string sups = details::remove_optional_field(&fields, SourceParagraphOptionalField::SUPPORTS); - sparagraph.supports = parse_comma_list(sups); + fpgh->depends = expand_qualified_dependencies(parse_comma_list(parser.optional_field(Fields::BUILD_DEPENDS))); - sparagraph.default_features = - details::remove_optional_field(&fields, SourceParagraphOptionalField::DEFAULTFEATURES); + auto err = parser.error_info(fpgh->name); + if (err) + return std::move(err); + else + return std::move(fpgh); + } - if (!fields.empty()) + ParseExpected SourceControlFile::parse_control_file( + std::vector>&& control_paragraphs) + { + if (control_paragraphs.size() == 0) { - const std::vector remaining_fields = Maps::extract_keys(fields); + return std::make_unique(); + } - const std::string remaining_fields_as_string = Strings::join("\n ", remaining_fields); + auto control_file = std::make_unique(); - return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string}; - } + auto maybe_source = parse_source_paragraph(std::move(control_paragraphs.front())); + if (auto source = maybe_source.get()) + control_file->core_paragraph = std::move(*source); + else + return std::move(maybe_source).error(); control_paragraphs.erase(control_paragraphs.begin()); for (auto&& feature_pgh : control_paragraphs) { - control_file.feature_paragraphs.emplace_back(std::make_unique()); - - FeatureParagraph& fparagraph = *control_file.feature_paragraphs.back(); - - fparagraph.name = details::remove_required_field(&feature_pgh, FeatureParagraphRequiredField::FEATURE); - fparagraph.description = - details::remove_required_field(&feature_pgh, FeatureParagraphOptionalField::DESCRIPTION); - std::string feature_deps = - details::remove_optional_field(&feature_pgh, FeatureParagraphOptionalField::BUILD_DEPENDS); - fparagraph.depends = expand_qualified_dependencies(parse_comma_list(feature_deps)); - - if (!feature_pgh.empty()) - { - const std::vector remaining_fields = Maps::extract_keys(feature_pgh); - - const std::string remaining_fields_as_string = Strings::join("\n ", remaining_fields); - - return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string}; - } + auto maybe_feature = parse_feature_paragraph(std::move(feature_pgh)); + if (auto feature = maybe_feature.get()) + control_file->feature_paragraphs.emplace_back(std::move(*feature)); + else + return std::move(maybe_feature).error(); } - return control_file; + return std::move(control_file); } std::vector vcpkg::expand_qualified_dependencies(const std::vector& depends) diff --git a/toolsrc/src/StatusParagraph.cpp b/toolsrc/src/StatusParagraph.cpp index b9ceed278..5b5c3978f 100644 --- a/toolsrc/src/StatusParagraph.cpp +++ b/toolsrc/src/StatusParagraph.cpp @@ -1,9 +1,8 @@ #include "pch.h" #include "StatusParagraph.h" -#include "vcpkglib_helpers.h" -using namespace vcpkg::details; +using namespace vcpkg::Parse; namespace vcpkg { @@ -24,9 +23,14 @@ namespace vcpkg .push_back('\n'); } - StatusParagraph::StatusParagraph(const std::unordered_map& fields) : package(fields) + StatusParagraph::StatusParagraph(std::unordered_map&& fields) { - std::string status_field = required_field(fields, BinaryParagraphRequiredField::STATUS); + auto status_it = fields.find(BinaryParagraphRequiredField::STATUS); + Checks::check_exit(VCPKG_LINE_INFO, status_it != fields.end(), "Expected 'Status' field in status paragraph"); + std::string status_field = std::move(status_it->second); + fields.erase(status_it); + + this->package = BinaryParagraph(std::move(fields)); auto b = status_field.begin(); auto mark = b; diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index a9e4f574e..4da9cede2 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -11,6 +11,8 @@ #include "vcpkglib.h" using vcpkg::Build::BuildResult; +using vcpkg::Parse::ParseControlErrorInfo; +using vcpkg::Parse::ParseExpected; namespace vcpkg::Commands::BuildCommand { @@ -34,7 +36,7 @@ namespace vcpkg::Commands::BuildCommand Checks::exit_success(VCPKG_LINE_INFO); } - const ExpectedT source_control_file = + const ParseExpected source_control_file = Paragraphs::try_load_port(paths.get_filesystem(), port_dir); if (!source_control_file.has_value()) @@ -47,18 +49,18 @@ namespace vcpkg::Commands::BuildCommand { System::println("%s \n", str); } - const SourceControlFile& scf = source_control_file.value_or_exit(VCPKG_LINE_INFO); + const auto& scf = source_control_file.value_or_exit(VCPKG_LINE_INFO); Checks::check_exit(VCPKG_LINE_INFO, - spec.name() == scf.core_paragraph.name, + spec.name() == scf->core_paragraph->name, "The Name: field inside the CONTROL does not match the port directory: '%s' != '%s'", - scf.core_paragraph.name, + scf->core_paragraph->name, spec.name()); StatusParagraphs status_db = database_load_check(paths); Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; const Build::BuildPackageConfig build_config{ - scf.core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options}; + *scf->core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options}; const auto result = Build::build_package(paths, build_config, status_db); if (result.code == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES) diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index 65e44e847..7ffc7577a 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -8,6 +8,7 @@ #include "vcpkg_Files.h" #include "vcpkg_Input.h" #include "vcpkg_System.h" +#include "vcpkg_Util.h" #include "vcpkglib.h" namespace vcpkg::Commands::CI @@ -21,14 +22,10 @@ namespace vcpkg::Commands::CI const Triplet& triplet) { auto ports = Paragraphs::load_all_ports(fs, ports_directory); - std::vector specs; - for (const SourceControlFile& control_file : ports) - { - const SourceParagraph& p = control_file.core_paragraph; - specs.push_back(PackageSpec::from_name_and_triplet(p.name, triplet).value_or_exit(VCPKG_LINE_INFO)); - } - - return specs; + return Util::fmap(ports, [&](auto&& control_file) -> PackageSpec { + return PackageSpec::from_name_and_triplet(control_file->core_paragraph->name, triplet) + .value_or_exit(VCPKG_LINE_INFO); + }); } void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index 468bf5d72..ccfe58e4e 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -15,9 +15,9 @@ namespace vcpkg::Commands::DependInfo const auto source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - for (const SourceControlFile& source_control_file : source_control_files) + for (auto&& source_control_file : source_control_files) { - const SourceParagraph& source_paragraph = source_control_file.core_paragraph; + const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name; }); System::println("%s: %s", source_paragraph.name, s); } diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp index d21883fc2..9bc9bcc08 100644 --- a/toolsrc/src/commands_list.cpp +++ b/toolsrc/src/commands_list.cpp @@ -3,7 +3,6 @@ #include "vcpkg_Commands.h" #include "vcpkg_System.h" #include "vcpkglib.h" -#include "vcpkglib_helpers.h" namespace vcpkg::Commands::List { @@ -20,7 +19,7 @@ namespace vcpkg::Commands::List System::println("%-27s %-16s %s", pgh.package.displayname(), pgh.package.version, - details::shorten_description(pgh.package.description)); + vcpkg::shorten_description(pgh.package.description)); } } diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp index e872c394d..83d62896f 100644 --- a/toolsrc/src/commands_portsdiff.cpp +++ b/toolsrc/src/commands_portsdiff.cpp @@ -97,10 +97,8 @@ namespace vcpkg::Commands::PortsDiff L".vcpkg-root", git_exe.native()); System::cmd_execute_clean(cmd); - const std::vector source_control_files = - Paragraphs::load_all_ports(paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); - const std::map names_and_versions = - Paragraphs::extract_port_names_and_versions(getSourceParagraphs(source_control_files)); + const std::map names_and_versions = Paragraphs::load_all_port_names_and_versions( + paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); fs.remove_all(temp_checkout_path, ec); return names_and_versions; } diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index b39d21887..fee99a5db 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -5,7 +5,6 @@ #include "vcpkg_Commands.h" #include "vcpkg_System.h" #include "vcpkglib.h" -#include "vcpkglib_helpers.h" namespace vcpkg::Commands::Search { @@ -19,16 +18,17 @@ namespace vcpkg::Commands::Search return output; } - static std::string create_graph_as_string(const std::vector& source_control_files) + static std::string create_graph_as_string( + const std::vector>& source_control_files) { int empty_node_count = 0; std::string s; s.append("digraph G{ rankdir=LR; edge [minlen=3]; overlap=false;"); - for (const SourceControlFile& source_control_file : source_control_files) + for (const auto& source_control_file : source_control_files) { - const SourceParagraph& source_paragraph = source_control_file.core_paragraph; + const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; if (source_paragraph.depends.empty()) { empty_node_count++; @@ -59,7 +59,7 @@ namespace vcpkg::Commands::Search System::println("%-20s %-16s %s", source_paragraph.name, source_paragraph.version, - details::shorten_description(source_paragraph.description)); + vcpkg::shorten_description(source_paragraph.description)); } } @@ -73,7 +73,7 @@ namespace vcpkg::Commands::Search { System::println("%-37s %s", name + "[" + feature_paragraph.name + "]", - details::shorten_description(feature_paragraph.description)); + vcpkg::shorten_description(feature_paragraph.description)); } } @@ -99,7 +99,7 @@ namespace vcpkg::Commands::Search for (auto&& error : sources_and_errors.errors) { System::println( - System::Color::warning, "Warning: an error occurred while parsing '%s'", error.name); + System::Color::warning, "Warning: an error occurred while parsing '%s'", error->name); } System::println(System::Color::warning, "Use '--debug' to get more information about the parse failures.\n"); @@ -116,12 +116,12 @@ namespace vcpkg::Commands::Search if (args.command_arguments.empty()) { - for (const SourceControlFile& source_control_file : source_paragraphs) + for (const auto& source_control_file : source_paragraphs) { - do_print(source_control_file.core_paragraph, options.find(OPTION_FULLDESC) != options.cend()); - for (auto&& feature_paragraph : source_control_file.feature_paragraphs) + do_print(*source_control_file->core_paragraph, options.find(OPTION_FULLDESC) != options.cend()); + for (auto&& feature_paragraph : source_control_file->feature_paragraphs) { - do_print(source_control_file.core_paragraph.name, + do_print(source_control_file->core_paragraph->name, *feature_paragraph, options.find(OPTION_FULLDESC) != options.cend()); } @@ -133,9 +133,9 @@ namespace vcpkg::Commands::Search // At this point there is 1 argument auto&& args_zero = args.command_arguments[0]; - for (const SourceControlFile& source_control_file : source_paragraphs) + for (const auto& source_control_file : source_paragraphs) { - auto&& sp = source_control_file.core_paragraph; + auto&& sp = *source_control_file->core_paragraph; bool contains_name = icontains(sp.name, args_zero); if (contains_name || icontains(sp.description, args_zero)) @@ -143,7 +143,7 @@ namespace vcpkg::Commands::Search do_print(sp, options.find(OPTION_FULLDESC) != options.cend()); } - for (auto&& feature_paragraph : source_control_file.feature_paragraphs) + for (auto&& feature_paragraph : source_control_file->feature_paragraphs) { if (contains_name || icontains(feature_paragraph->name, args_zero) || icontains(feature_paragraph->description, args_zero)) diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp index f00a89da4..35f24af12 100644 --- a/toolsrc/src/commands_update.cpp +++ b/toolsrc/src/commands_update.cpp @@ -15,10 +15,8 @@ namespace vcpkg::Commands::Update std::vector find_outdated_packages(const VcpkgPaths& paths, const StatusParagraphs& status_db) { - auto source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - const std::vector source_paragraphs = getSourceParagraphs(source_control_files); const std::map src_names_to_versions = - Paragraphs::extract_port_names_and_versions(source_paragraphs); + Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports); const std::vector installed_packages = get_installed_ports(status_db); std::vector output; @@ -67,7 +65,8 @@ namespace vcpkg::Commands::Update System::println("\n" "To update these packages, run\n" " .\\vcpkg remove --outdated\n" - " .\\vcpkg install " + install_line); + " .\\vcpkg install " + + install_line); } auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt"); diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index 8dff520fb..2a53cc8b4 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -33,11 +33,11 @@ namespace UnitTest1 Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual("zlib", pgh.core_paragraph.name.c_str()); - Assert::AreEqual("1.2.8", pgh.core_paragraph.version.c_str()); - Assert::AreEqual("", pgh.core_paragraph.maintainer.c_str()); - Assert::AreEqual("", pgh.core_paragraph.description.c_str()); - Assert::AreEqual(size_t(0), pgh.core_paragraph.depends.size()); + Assert::AreEqual("zlib", pgh->core_paragraph->name.c_str()); + Assert::AreEqual("1.2.8", pgh->core_paragraph->version.c_str()); + Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str()); + Assert::AreEqual("", pgh->core_paragraph->description.c_str()); + Assert::AreEqual(size_t(0), pgh->core_paragraph->depends.size()); } TEST_METHOD(SourceParagraph_Construct_Maximum) @@ -54,14 +54,14 @@ namespace UnitTest1 Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual("s", pgh.core_paragraph.name.c_str()); - Assert::AreEqual("v", pgh.core_paragraph.version.c_str()); - Assert::AreEqual("m", pgh.core_paragraph.maintainer.c_str()); - Assert::AreEqual("d", pgh.core_paragraph.description.c_str()); - Assert::AreEqual(size_t(1), pgh.core_paragraph.depends.size()); - Assert::AreEqual("bd", pgh.core_paragraph.depends[0].name.c_str()); - Assert::AreEqual(size_t(1), pgh.core_paragraph.supports.size()); - Assert::AreEqual("x64", pgh.core_paragraph.supports[0].c_str()); + Assert::AreEqual("s", pgh->core_paragraph->name.c_str()); + Assert::AreEqual("v", pgh->core_paragraph->version.c_str()); + Assert::AreEqual("m", pgh->core_paragraph->maintainer.c_str()); + Assert::AreEqual("d", pgh->core_paragraph->description.c_str()); + Assert::AreEqual(size_t(1), pgh->core_paragraph->depends.size()); + Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name.c_str()); + Assert::AreEqual(size_t(1), pgh->core_paragraph->supports.size()); + Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str()); } TEST_METHOD(SourceParagraph_Two_Depends) @@ -73,9 +73,9 @@ namespace UnitTest1 Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual(size_t(2), pgh.core_paragraph.depends.size()); - Assert::AreEqual("z", pgh.core_paragraph.depends[0].name.c_str()); - Assert::AreEqual("openssl", pgh.core_paragraph.depends[1].name.c_str()); + Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); + Assert::AreEqual("z", pgh->core_paragraph->depends[0].name.c_str()); + Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name.c_str()); } TEST_METHOD(SourceParagraph_Three_Depends) @@ -87,10 +87,10 @@ namespace UnitTest1 Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual(size_t(3), pgh.core_paragraph.depends.size()); - Assert::AreEqual("z", pgh.core_paragraph.depends[0].name.c_str()); - Assert::AreEqual("openssl", pgh.core_paragraph.depends[1].name.c_str()); - Assert::AreEqual("xyz", pgh.core_paragraph.depends[2].name.c_str()); + Assert::AreEqual(size_t(3), pgh->core_paragraph->depends.size()); + Assert::AreEqual("z", pgh->core_paragraph->depends[0].name.c_str()); + Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name.c_str()); + Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name.c_str()); } TEST_METHOD(SourceParagraph_Three_Supports) @@ -102,10 +102,10 @@ namespace UnitTest1 Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual(size_t(3), pgh.core_paragraph.supports.size()); - Assert::AreEqual("x64", pgh.core_paragraph.supports[0].c_str()); - Assert::AreEqual("windows", pgh.core_paragraph.supports[1].c_str()); - Assert::AreEqual("uwp", pgh.core_paragraph.supports[2].c_str()); + Assert::AreEqual(size_t(3), pgh->core_paragraph->supports.size()); + Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str()); + Assert::AreEqual("windows", pgh->core_paragraph->supports[1].c_str()); + Assert::AreEqual("uwp", pgh->core_paragraph->supports[2].c_str()); } TEST_METHOD(SourceParagraph_Construct_Qualified_Depends) @@ -117,15 +117,15 @@ namespace UnitTest1 Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); - Assert::AreEqual("zlib", pgh.core_paragraph.name.c_str()); - Assert::AreEqual("1.2.8", pgh.core_paragraph.version.c_str()); - Assert::AreEqual("", pgh.core_paragraph.maintainer.c_str()); - Assert::AreEqual("", pgh.core_paragraph.description.c_str()); - Assert::AreEqual(size_t(2), pgh.core_paragraph.depends.size()); - Assert::AreEqual("libA", pgh.core_paragraph.depends[0].name.c_str()); - Assert::AreEqual("windows", pgh.core_paragraph.depends[0].qualifier.c_str()); - Assert::AreEqual("libB", pgh.core_paragraph.depends[1].name.c_str()); - Assert::AreEqual("uwp", pgh.core_paragraph.depends[1].qualifier.c_str()); + Assert::AreEqual("zlib", pgh->core_paragraph->name.c_str()); + Assert::AreEqual("1.2.8", pgh->core_paragraph->version.c_str()); + Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str()); + Assert::AreEqual("", pgh->core_paragraph->description.c_str()); + Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); + Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name.c_str()); + Assert::AreEqual("windows", pgh->core_paragraph->depends[0].qualifier.c_str()); + Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name.c_str()); + Assert::AreEqual("uwp", pgh->core_paragraph->depends[1].qualifier.c_str()); } TEST_METHOD(BinaryParagraph_Construct_Minimum) diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index 0ca6dc243..a73d59910 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -11,7 +11,6 @@ #include "vcpkg_System.h" #include "vcpkg_optional.h" #include "vcpkglib.h" -#include "vcpkglib_helpers.h" namespace vcpkg::Build { @@ -218,56 +217,52 @@ namespace vcpkg::Build static BuildInfo inner_create_buildinfo(std::unordered_map pgh) { + Parse::ParagraphParser parser(std::move(pgh)); + BuildInfo build_info; - const std::string crt_linkage_as_string = - details::remove_required_field(&pgh, BuildInfoRequiredField::CRT_LINKAGE); - - auto crtlinkage = to_linkage_type(crt_linkage_as_string); - if (auto p = crtlinkage.get()) - build_info.crt_linkage = *p; - else - Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid crt linkage type: [%s]", crt_linkage_as_string); - - const std::string library_linkage_as_string = - details::remove_required_field(&pgh, BuildInfoRequiredField::LIBRARY_LINKAGE); - auto liblinkage = to_linkage_type(library_linkage_as_string); - if (auto p = liblinkage.get()) - build_info.library_linkage = *p; - else - Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid library linkage type: [%s]", library_linkage_as_string); - - auto it_version = pgh.find("Version"); - if (it_version != pgh.end()) + { - build_info.version = it_version->second; - pgh.erase(it_version); + std::string crt_linkage_as_string; + parser.required_field(BuildInfoRequiredField::CRT_LINKAGE, crt_linkage_as_string); + + auto crtlinkage = to_linkage_type(crt_linkage_as_string); + if (auto p = crtlinkage.get()) + build_info.crt_linkage = *p; + else + Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid crt linkage type: [%s]", crt_linkage_as_string); } - std::map policies; + { + std::string library_linkage_as_string; + parser.required_field(BuildInfoRequiredField::LIBRARY_LINKAGE, library_linkage_as_string); + auto liblinkage = to_linkage_type(library_linkage_as_string); + if (auto p = liblinkage.get()) + build_info.library_linkage = *p; + else + Checks::exit_with_message( + VCPKG_LINE_INFO, "Invalid library linkage type: [%s]", library_linkage_as_string); + } + build_info.version = parser.optional_field("Version"); - // The remaining entries are policies - for (const std::unordered_map::value_type& p : pgh) + std::map policies; + for (auto policy : g_all_policies) { - auto maybe_policy = to_build_policy(p.first); - if (auto policy = maybe_policy.get()) - { - Checks::check_exit(VCPKG_LINE_INFO, - policies.find(*policy) == policies.end(), - "Policy specified multiple times: %s", - p.first); - - if (p.second == "enabled") - policies.emplace(*policy, true); - else if (p.second == "disabled") - policies.emplace(*policy, false); - else - Checks::exit_with_message( - VCPKG_LINE_INFO, "Unknown setting for policy '%s': %s", p.first, p.second); - } + const auto setting = parser.optional_field(to_string(policy)); + if (setting.empty()) + continue; + else if (setting == "enabled") + policies.emplace(policy, true); + else if (setting == "disabled") + policies.emplace(policy, false); else - { - Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown policy found: %s", p.first); - } + Checks::exit_with_message( + VCPKG_LINE_INFO, "Unknown setting for policy '%s': %s", to_string(policy), setting); + } + + if (auto err = parser.error_info("PostBuildInformation")) + { + print_error_message(err); + Checks::exit_fail(VCPKG_LINE_INFO); } build_info.policies = BuildPolicies(std::move(policies)); diff --git a/toolsrc/src/vcpkg_Build_BuildPolicy.cpp b/toolsrc/src/vcpkg_Build_BuildPolicy.cpp index e75e176a2..b3bb778dc 100644 --- a/toolsrc/src/vcpkg_Build_BuildPolicy.cpp +++ b/toolsrc/src/vcpkg_Build_BuildPolicy.cpp @@ -12,17 +12,6 @@ namespace vcpkg::Build static const std::string NAME_EMPTY_INCLUDE_FOLDER = "PolicyEmptyIncludeFolder"; static const std::string NAME_ALLOW_OBSOLETE_MSVCRT = "PolicyAllowObsoleteMsvcrt"; - Optional to_build_policy(const std::string& s) - { - if (s == NAME_EMPTY_PACKAGE) return BuildPolicy::EMPTY_PACKAGE; - if (s == NAME_DLLS_WITHOUT_LIBS) return BuildPolicy::DLLS_WITHOUT_LIBS; - if (s == NAME_ONLY_RELEASE_CRT) return BuildPolicy::ONLY_RELEASE_CRT; - if (s == NAME_EMPTY_INCLUDE_FOLDER) return BuildPolicy::EMPTY_INCLUDE_FOLDER; - if (s == NAME_ALLOW_OBSOLETE_MSVCRT) return BuildPolicy::ALLOW_OBSOLETE_MSVCRT; - - return nullopt; - } - const std::string& to_string(BuildPolicy policy) { switch (policy) diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index add8acb4d..bbf807c95 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -174,12 +174,11 @@ namespace vcpkg::Dependencies if (auto bpgh = maybe_bpgh.get()) return InstallPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type}; - ExpectedT source_control_file = - Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); - if (auto scf = source_control_file.get()) - return InstallPlanAction{spec, {nullopt, nullopt, (*scf).core_paragraph}, request_type}; + auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); + if (auto scf = maybe_scf.get()) + return InstallPlanAction{spec, {nullopt, nullopt, *scf->get()->core_paragraph}, request_type}; - print_error_message(source_control_file.error()); + print_error_message(maybe_scf.error()); Checks::exit_fail(VCPKG_LINE_INFO); } }; @@ -284,13 +283,11 @@ namespace vcpkg::Dependencies if (auto bpgh = maybe_bpgh.get()) return ExportPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type}; - ExpectedT source_control_file = - Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); - if (auto scf = source_control_file.get()) - return ExportPlanAction{spec, {nullopt, nullopt, (*scf).core_paragraph}, request_type}; - + auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); + if (auto scf = maybe_scf.get()) + return ExportPlanAction{spec, {nullopt, nullopt, *scf->get()->core_paragraph}, request_type}; else - print_error_message(source_control_file.error()); + print_error_message(maybe_scf.error()); Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); } diff --git a/toolsrc/src/vcpkg_Parse.cpp b/toolsrc/src/vcpkg_Parse.cpp new file mode 100644 index 000000000..b63ce41a9 --- /dev/null +++ b/toolsrc/src/vcpkg_Parse.cpp @@ -0,0 +1,59 @@ +#include "pch.h" + +#include "vcpkg_Checks.h" +#include "vcpkg_Maps.h" +#include "vcpkg_Parse.h" + +namespace vcpkg::Parse +{ + static Optional get_field(const std::unordered_map& fields, + const std::string& fieldname) + { + auto it = fields.find(fieldname); + if (it == fields.end()) + { + return nullopt; + } + + return it->second; + } + + static Optional remove_field(std::unordered_map* fields, + const std::string& fieldname) + { + auto it = fields->find(fieldname); + if (it == fields->end()) + { + return nullopt; + } + + const std::string value = std::move(it->second); + fields->erase(it); + return value; + } + + void ParagraphParser::required_field(const std::string& fieldname, std::string& out) + { + auto maybe_field = remove_field(&fields, fieldname); + if (auto field = maybe_field.get()) + out = std::move(*field); + else + missing_fields.push_back(fieldname); + } + std::string ParagraphParser::optional_field(const std::string& fieldname) + { + return remove_field(&fields, fieldname).value_or(""); + } + std::unique_ptr ParagraphParser::error_info(const std::string& name) const + { + if (!fields.empty() || !missing_fields.empty()) + { + auto err = std::make_unique(); + err->name = name; + err->extra_fields = Maps::extract_keys(fields); + err->missing_fields = std::move(missing_fields); + return err; + } + return nullptr; + } +} diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 15130f77e..6b180b532 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -31,7 +31,7 @@ namespace vcpkg std::vector> status_pghs; for (auto&& p : pghs) { - status_pghs.push_back(std::make_unique(p)); + status_pghs.push_back(std::make_unique(std::move(p))); } return StatusParagraphs(std::move(status_pghs)); @@ -69,7 +69,7 @@ namespace vcpkg auto pghs = Paragraphs::get_paragraphs(fs, file).value_or_exit(VCPKG_LINE_INFO); for (auto&& p : pghs) { - current_status_db.insert(std::make_unique(p)); + current_status_db.insert(std::make_unique(std::move(p))); } } @@ -239,4 +239,10 @@ namespace vcpkg return Strings::wformat( LR"("%s" %s -P "%s")", cmake_exe.native(), cmd_cmake_pass_variables, cmake_script.generic_wstring()); } + + std::string shorten_description(const std::string& desc) + { + auto simple_desc = std::regex_replace(desc, std::regex("\\s+"), " "); + return simple_desc.size() <= 52 ? simple_desc : simple_desc.substr(0, 49) + "..."; + } } diff --git a/toolsrc/src/vcpkglib_helpers.cpp b/toolsrc/src/vcpkglib_helpers.cpp deleted file mode 100644 index 9f992d320..000000000 --- a/toolsrc/src/vcpkglib_helpers.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Checks.h" -#include "vcpkglib_helpers.h" - -namespace vcpkg::details -{ - std::string optional_field(const std::unordered_map& fields, const std::string& fieldname) - { - auto it = fields.find(fieldname); - if (it == fields.end()) - { - return std::string(); - } - - return it->second; - } - - std::string remove_optional_field(std::unordered_map* fields, - const std::string& fieldname) - { - auto it = fields->find(fieldname); - if (it == fields->end()) - { - return std::string(); - } - - const std::string value = std::move(it->second); - fields->erase(it); - return value; - } - - std::string required_field(const std::unordered_map& fields, const std::string& fieldname) - { - auto it = fields.find(fieldname); - Checks::check_exit(VCPKG_LINE_INFO, it != fields.end(), "Required field not present: %s", fieldname); - return it->second; - } - - std::string remove_required_field(std::unordered_map* fields, - const std::string& fieldname) - { - auto it = fields->find(fieldname); - Checks::check_exit(VCPKG_LINE_INFO, it != fields->end(), "Required field not present: %s", fieldname); - - const std::string value = std::move(it->second); - fields->erase(it); - return value; - } - - std::string shorten_description(const std::string& desc) - { - auto simple_desc = std::regex_replace(desc, std::regex("\\s+"), " "); - return simple_desc.size() <= 52 ? simple_desc : simple_desc.substr(0, 49) + "..."; - } -} -- cgit v1.2.3 From befe2531f620471e1b2c5562c9994420e03c008a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 20 Jun 2017 09:53:22 -0700 Subject: [vcpkg] Handle missing fields in print_error_message() --- toolsrc/src/SourceParagraph.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 83b8e2e2d..9289edb38 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -56,7 +56,7 @@ namespace vcpkg System::println(System::Color::error, "Error: There are invalid fields in the Source Paragraph of %s", error_info->name); - System::println("The following fields were not expected:\n\n %s\n\n", + System::println("The following fields were not expected:\n\n %s\n", Strings::join("\n ", error_info->extra_fields)); have_remaining_fields = true; } @@ -68,6 +68,18 @@ namespace vcpkg Strings::join("\n ", get_list_of_valid_fields())); System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); } + + for (auto&& error_info : error_info_list) + { + if (!error_info->missing_fields.empty()) + { + System::println(System::Color::error, + "Error: There are missing fields in the Source Paragraphs of %s", + error_info->name); + System::println("The following fields were missing:\n\n %s\n", + Strings::join("\n ", error_info->missing_fields)); + } + } } static ParseExpected parse_source_paragraph(RawParagraph&& fields) -- cgit v1.2.3 From e72b0ec9a2ac23300c39d7bc8217dfd5cfa6ab63 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 20 Jun 2017 16:26:25 -0700 Subject: [vcpkg] Hotfix regression in 8741214. Fixes #1325. --- toolsrc/src/vcpkg_Build.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index a73d59910..c794b5ede 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -242,7 +242,8 @@ namespace vcpkg::Build Checks::exit_with_message( VCPKG_LINE_INFO, "Invalid library linkage type: [%s]", library_linkage_as_string); } - build_info.version = parser.optional_field("Version"); + std::string version = parser.optional_field("Version"); + if (!version.empty()) build_info.version = std::move(version); std::map policies; for (auto policy : g_all_policies) -- cgit v1.2.3 From b188fefecaf03c1f30ee4752c2235975058553e2 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 21 Jun 2017 15:27:34 -0700 Subject: [triplet] Use pointer to instance-controlled strings and cache hashcode --- toolsrc/src/triplet.cpp | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/triplet.cpp b/toolsrc/src/triplet.cpp index ff41ce77d..451deb040 100644 --- a/toolsrc/src/triplet.cpp +++ b/toolsrc/src/triplet.cpp @@ -6,31 +6,50 @@ namespace vcpkg { + struct TripletInstance + { + TripletInstance(std::string&& s) : value(std::move(s)), hash(std::hash()(value)) {} + + const std::string value; + const size_t hash = 0; + + bool operator==(const TripletInstance& o) const { return o.value == value; } + }; + const TripletInstance Triplet::default_instance({}); +} + +template<> +struct std::hash +{ + size_t operator()(const vcpkg::TripletInstance& t) const { return t.hash; } +}; + +namespace vcpkg +{ + static std::unordered_set g_triplet_instances; + const Triplet Triplet::X86_WINDOWS = from_canonical_name("x86-windows"); const Triplet Triplet::X64_WINDOWS = from_canonical_name("x64-windows"); const Triplet Triplet::X86_UWP = from_canonical_name("x86-uwp"); const Triplet Triplet::X64_UWP = from_canonical_name("x64-uwp"); const Triplet Triplet::ARM_UWP = from_canonical_name("arm-uwp"); - bool operator==(const Triplet& left, const Triplet& right) - { - return left.canonical_name() == right.canonical_name(); - } + bool Triplet::operator==(const Triplet& other) const { return this->m_instance == other.m_instance; } bool operator!=(const Triplet& left, const Triplet& right) { return !(left == right); } Triplet Triplet::from_canonical_name(const std::string& triplet_as_string) { - const std::string s(Strings::ascii_to_lowercase(triplet_as_string)); + std::string s(Strings::ascii_to_lowercase(triplet_as_string)); auto it = std::find(s.cbegin(), s.cend(), '-'); Checks::check_exit(VCPKG_LINE_INFO, it != s.cend(), "Invalid triplet: %s", triplet_as_string); - Triplet t; - t.m_canonical_name = s; - return t; + auto p = g_triplet_instances.emplace(std::move(s)); + return &*p.first; } - const std::string& Triplet::canonical_name() const { return this->m_canonical_name; } + const std::string& Triplet::canonical_name() const { return this->m_instance->value; } - const std::string& Triplet::to_string() const { return this->m_canonical_name; } + const std::string& Triplet::to_string() const { return this->canonical_name(); } + size_t Triplet::hash_code() const { return m_instance->hash; } } -- cgit v1.2.3 From 8461bc1913df1a7db287999c33876291cd25be61 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 21 Jun 2017 17:41:31 -0700 Subject: [vcpkg-export] Fix nuget export. Fixes #1223. --- toolsrc/src/commands_export.cpp | 4 ++++ toolsrc/src/vcpkg_Files.cpp | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index e46001b06..cbb3a7733 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -122,6 +122,10 @@ namespace vcpkg::Commands::Export const std::string targets_redirect_content = create_targets_redirect("../../scripts/buildsystems/msbuild/vcpkg.targets"); const fs::path targets_redirect = paths.buildsystems / "tmp" / "vcpkg.export.nuget.targets"; + + std::error_code ec; + fs.create_directories(paths.buildsystems / "tmp", ec); + fs.write_contents(targets_redirect, targets_redirect_content); const std::string nuspec_file_content = diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp index 7b12ea699..29da7e684 100644 --- a/toolsrc/src/vcpkg_Files.cpp +++ b/toolsrc/src/vcpkg_Files.cpp @@ -164,7 +164,8 @@ namespace vcpkg::Files { FILE* f = nullptr; auto ec = _wfopen_s(&f, file_path.native().c_str(), L"wb"); - Checks::check_exit(VCPKG_LINE_INFO, ec == 0); + Checks::check_exit( + VCPKG_LINE_INFO, ec == 0, "Error: Could not open file for writing: %s", file_path.u8string().c_str()); auto count = fwrite(data.data(), sizeof(data[0]), data.size(), f); fclose(f); -- cgit v1.2.3 From 838e8783d659456037c0e8e89dcc689e626b6816 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Mon, 26 Jun 2017 13:48:04 -0700 Subject: adding tests for install plans --- toolsrc/src/commands_ci.cpp | 3 +- toolsrc/src/commands_install.cpp | 3 +- toolsrc/src/test_install_plan.cpp | 155 +++++++++++++++++++++++++++++++++++++ toolsrc/src/vcpkg_Dependencies.cpp | 79 ++++++++++++++++++- 4 files changed, 237 insertions(+), 3 deletions(-) create mode 100644 toolsrc/src/test_install_plan.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index 7ffc7577a..85febd580 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -40,7 +40,8 @@ namespace vcpkg::Commands::CI const std::vector specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet); StatusParagraphs status_db = database_load_check(paths); - const std::vector install_plan = Dependencies::create_install_plan(paths, specs, status_db); + const std::vector install_plan /* = + Dependencies::create_install_plan(Dependencies::PathsPortFile(paths), specs, status_db)*/; Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); std::vector results; diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 73b3e9eab..a58432eef 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -359,7 +359,8 @@ namespace vcpkg::Commands::Install // create the plan StatusParagraphs status_db = database_load_check(paths); - std::vector install_plan = Dependencies::create_install_plan(paths, specs, status_db); + std::vector install_plan = + Dependencies::create_install_plan(Dependencies::PathsPortFile(paths), specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); // log the plan diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp new file mode 100644 index 000000000..90aaa532f --- /dev/null +++ b/toolsrc/src/test_install_plan.cpp @@ -0,0 +1,155 @@ +#include "CppUnitTest.h" +#include "vcpkg_Dependencies.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +using namespace vcpkg; + +namespace UnitTest1 +{ + class InstallPlanTests : public TestClass + { + TEST_METHOD(basic_install_scheme) + { + std::vector> status_paragraphs; + + std::unordered_map map; + auto add_scf = [&](std::vector>&& fields) -> PackageSpec { + auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(fields)); + Assert::IsTrue(m_pgh.has_value()); + auto& scf = *m_pgh.get(); + + auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph.name, Triplet::X86_WINDOWS); + Assert::IsTrue(spec.has_value()); + map.emplace(*spec.get(), std::move(*m_pgh.get())); + return PackageSpec{*spec.get()}; + }; + + auto spec_a = add_scf({{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "b"}}}); + auto spec_b = add_scf({{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", "c"}}}); + auto spec_c = add_scf({{{"Source", "c"}, {"Version", "2.5.3"}, {"Build-Depends", ""}}}); + + auto map_port = Dependencies::MapPortFile(map); + auto install_plan = + Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(3), install_plan.size()); + Assert::AreEqual("c", install_plan[0].spec.name().c_str()); + Assert::AreEqual("b", install_plan[1].spec.name().c_str()); + Assert::AreEqual("a", install_plan[2].spec.name().c_str()); + } + + TEST_METHOD(multiple_install_scheme) + { + std::vector> status_paragraphs; + + std::unordered_map map; + auto add_scf = [&](std::vector>&& fields) -> PackageSpec { + auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(fields)); + Assert::IsTrue(m_pgh.has_value()); + auto& scf = *m_pgh.get(); + + auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph.name, Triplet::X86_WINDOWS); + Assert::IsTrue(spec.has_value()); + map.emplace(*spec.get(), std::move(*m_pgh.get())); + return PackageSpec{*spec.get()}; + }; + + auto spec_a = add_scf({{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "d"}}}); + auto spec_b = add_scf({{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", "d, e"}}}); + auto spec_c = add_scf({{{"Source", "c"}, {"Version", "2.5.3"}, {"Build-Depends", "e, h"}}}); + auto spec_d = add_scf({{{"Source", "d"}, {"Version", "4.0"}, {"Build-Depends", "f, g, h"}}}); + auto spec_e = add_scf({{{"Source", "e"}, {"Version", "1.0"}, {"Build-Depends", "g"}}}); + auto spec_f = add_scf({{{"Source", "f"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); + auto spec_g = add_scf({{{"Source", "g"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); + auto spec_h = add_scf({{{"Source", "h"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); + + auto map_port = Dependencies::MapPortFile(map); + auto install_plan = Dependencies::create_install_plan( + map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); + + auto iterator_pos = [&](const PackageSpec& spec) -> int { + int counter = 0; + for (auto&& install_p : install_plan) + { + if (install_p.spec == spec) + { + return counter; + } + counter++; + } + return -1; + }; + int a_pos = iterator_pos(spec_a), b_pos = iterator_pos(spec_b), c_pos = iterator_pos(spec_c), + d_pos = iterator_pos(spec_d), e_pos = iterator_pos(spec_e), f_pos = iterator_pos(spec_f), + g_pos = iterator_pos(spec_g), h_pos = iterator_pos(spec_h); + + Assert::IsTrue(a_pos > d_pos); + Assert::IsTrue(b_pos > e_pos); + Assert::IsTrue(b_pos > d_pos); + Assert::IsTrue(c_pos > e_pos); + Assert::IsTrue(c_pos > h_pos); + Assert::IsTrue(d_pos > f_pos); + Assert::IsTrue(d_pos > g_pos); + Assert::IsTrue(d_pos > h_pos); + Assert::IsTrue(e_pos > g_pos); + } + + TEST_METHOD(long_install_scheme) + { + using Pgh = std::unordered_map; + std::vector> status_paragraphs; + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "j"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Build-Depends", "k"}, + {"Status", "install ok installed"}})); + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "k"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Build-Depends", ""}, + {"Status", "install ok installed"}})); + + std::unordered_map map; + auto add_scf = [&](std::vector>&& fields) -> PackageSpec { + auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(fields)); + Assert::IsTrue(m_pgh.has_value()); + auto& scf = *m_pgh.get(); + + auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph.name, Triplet::X86_WINDOWS); + Assert::IsTrue(spec.has_value()); + map.emplace(*spec.get(), std::move(*m_pgh.get())); + return PackageSpec{*spec.get()}; + }; + + auto spec_h = add_scf({{{"Source", "h"}, {"Version", "1.2.8"}, {"Build-Depends", "j, k"}}}); + auto spec_c = add_scf({{{"Source", "c"}, {"Version", "1.2.8"}, {"Build-Depends", "d, e, f, g, h, j, k"}}}); + auto spec_k = add_scf({{{"Source", "k"}, {"Version", "1.2.8"}, {"Build-Depends", ""}}}); + auto spec_b = + add_scf({{{"Source", "b"}, {"Version", "1.2.8"}, {"Build-Depends", "c, d, e, f, g, h, j, k"}}}); + auto spec_d = add_scf({{{"Source", "d"}, {"Version", "1.2.8"}, {"Build-Depends", "e, f, g, h, j, k"}}}); + auto spec_j = add_scf({{{"Source", "j"}, {"Version", "1.2.8"}, {"Build-Depends", "k"}}}); + auto spec_f = add_scf({{{"Source", "f"}, {"Version", "1.2.8"}, {"Build-Depends", "g, h, j, k"}}}); + auto spec_e = add_scf({{{"Source", "e"}, {"Version", "1.2.8"}, {"Build-Depends", "f, g, h, j, k"}}}); + auto spec_a = + add_scf({{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "b, c, d, e, f, g, h, j, k"}}}); + auto spec_g = add_scf({{{"Source", "g"}, {"Version", "1.2.8"}, {"Build-Depends", "h, j, k"}}}); + + auto map_port = Dependencies::MapPortFile(map); + auto install_plan = + Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(8), install_plan.size()); + Assert::AreEqual("h", install_plan[0].spec.name().c_str()); + Assert::AreEqual("g", install_plan[1].spec.name().c_str()); + Assert::AreEqual("f", install_plan[2].spec.name().c_str()); + Assert::AreEqual("e", install_plan[3].spec.name().c_str()); + Assert::AreEqual("d", install_plan[4].spec.name().c_str()); + Assert::AreEqual("c", install_plan[5].spec.name().c_str()); + Assert::AreEqual("b", install_plan[6].spec.name().c_str()); + Assert::AreEqual("a", install_plan[7].spec.name().c_str()); + } + }; +} \ No newline at end of file diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index bbf807c95..79f572496 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -139,9 +139,86 @@ namespace vcpkg::Dependencies return left->spec.name() < right->spec.name(); } - std::vector create_install_plan(const VcpkgPaths& paths, + MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map){}; + const SourceControlFile* MapPortFile::get_control_file(const PackageSpec& spec) const + { + auto scf = ports.find(spec); + if (scf == ports.end()) + { + Checks::exit_fail(VCPKG_LINE_INFO); + } + return &scf->second; + } + + PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths){}; + const SourceControlFile* PathsPortFile::get_control_file(const PackageSpec& spec) const + { + std::unordered_map::iterator cache_it = cache.find(spec); + if (cache_it != cache.end()) + { + return &cache_it->second; + } + ExpectedT source_control_file = + Paragraphs::try_load_port(ports.get_filesystem(), ports.port_dir(spec)); + + if (auto scf = source_control_file.get()) + { + auto it = cache.emplace(spec, std::move(*scf)); + return &it.first->second; + } + + Checks::exit_fail(VCPKG_LINE_INFO); + } + + std::vector create_install_plan(const PortFileProvider& port_file_provider, const std::vector& specs, const StatusParagraphs& status_db) + { + struct InstallAdjacencyProvider final : Graphs::AdjacencyProvider + { + const PortFileProvider& port_file_provider; + const StatusParagraphs& status_db; + const std::unordered_set& specs_as_set; + + InstallAdjacencyProvider(const PortFileProvider& port_file_provider, + const StatusParagraphs& s, + const std::unordered_set& specs_as_set) + : port_file_provider(port_file_provider), status_db(s), specs_as_set(specs_as_set) + { + } + + std::vector adjacency_list(const InstallPlanAction& plan) const override + { + if (plan.any_paragraph.status_paragraph.get()) return std::vector{}; + return plan.any_paragraph.dependencies(plan.spec.triplet()); + } + + InstallPlanAction load_vertex_data(const PackageSpec& spec) const override + { + const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() + ? RequestType::USER_REQUESTED + : RequestType::AUTO_SELECTED; + auto it = status_db.find_installed(spec); + if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type}; + return InstallPlanAction{ + spec, {nullopt, nullopt, port_file_provider.get_control_file(spec)->core_paragraph}, request_type}; + } + }; + + const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); + std::vector toposort = + Graphs::topological_sort(specs, InstallAdjacencyProvider{port_file_provider, status_db, specs_as_set}); + Util::erase_remove_if(toposort, [](const InstallPlanAction& plan) { + return plan.request_type == RequestType::AUTO_SELECTED && + plan.plan_type == InstallPlanType::ALREADY_INSTALLED; + }); + + return toposort; + } + + std::vector create_full_install_plan(const VcpkgPaths& paths, + const std::vector& specs, + const StatusParagraphs& status_db) { struct InstallAdjacencyProvider final : Graphs::AdjacencyProvider { -- cgit v1.2.3 From cc06f978914917622904a0326094c1d5fba4118e Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Mon, 26 Jun 2017 15:45:31 -0700 Subject: Merge branch 'master' into create_install_tests --- toolsrc/src/commands_ci.cpp | 4 +-- toolsrc/src/test_install_plan.cpp | 16 +++++----- toolsrc/src/vcpkg_Dependencies.cpp | 61 ++------------------------------------ 3 files changed, 13 insertions(+), 68 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index 85febd580..5f6fc95b5 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -40,8 +40,8 @@ namespace vcpkg::Commands::CI const std::vector specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet); StatusParagraphs status_db = database_load_check(paths); - const std::vector install_plan /* = - Dependencies::create_install_plan(Dependencies::PathsPortFile(paths), specs, status_db)*/; + const std::vector install_plan = + Dependencies::create_install_plan(Dependencies::PathsPortFile(paths), specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); std::vector results; diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 90aaa532f..2404e30f7 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -19,9 +19,9 @@ namespace UnitTest1 Assert::IsTrue(m_pgh.has_value()); auto& scf = *m_pgh.get(); - auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph.name, Triplet::X86_WINDOWS); + auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, Triplet::X86_WINDOWS); Assert::IsTrue(spec.has_value()); - map.emplace(*spec.get(), std::move(*m_pgh.get())); + map.emplace(*spec.get(), std::move(*scf.get())); return PackageSpec{*spec.get()}; }; @@ -49,9 +49,9 @@ namespace UnitTest1 Assert::IsTrue(m_pgh.has_value()); auto& scf = *m_pgh.get(); - auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph.name, Triplet::X86_WINDOWS); + auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, Triplet::X86_WINDOWS); Assert::IsTrue(spec.has_value()); - map.emplace(*spec.get(), std::move(*m_pgh.get())); + map.emplace(*spec.get(), std::move(*scf.get())); return PackageSpec{*spec.get()}; }; @@ -103,13 +103,13 @@ namespace UnitTest1 {"Version", "1.2.8"}, {"Architecture", "x86-windows"}, {"Multi-Arch", "same"}, - {"Build-Depends", "k"}, + {"Depends", "k"}, {"Status", "install ok installed"}})); status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "k"}, {"Version", "1.2.8"}, {"Architecture", "x86-windows"}, {"Multi-Arch", "same"}, - {"Build-Depends", ""}, + {"Depends", ""}, {"Status", "install ok installed"}})); std::unordered_map map; @@ -118,9 +118,9 @@ namespace UnitTest1 Assert::IsTrue(m_pgh.has_value()); auto& scf = *m_pgh.get(); - auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph.name, Triplet::X86_WINDOWS); + auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, Triplet::X86_WINDOWS); Assert::IsTrue(spec.has_value()); - map.emplace(*spec.get(), std::move(*m_pgh.get())); + map.emplace(*spec.get(), std::move(*scf.get())); return PackageSpec{*spec.get()}; }; diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 79f572496..726c147fd 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -158,12 +158,12 @@ namespace vcpkg::Dependencies { return &cache_it->second; } - ExpectedT source_control_file = + Parse::ParseExpected source_control_file = Paragraphs::try_load_port(ports.get_filesystem(), ports.port_dir(spec)); if (auto scf = source_control_file.get()) { - auto it = cache.emplace(spec, std::move(*scf)); + auto it = cache.emplace(spec, std::move(*scf->get())); return &it.first->second; } @@ -201,7 +201,7 @@ namespace vcpkg::Dependencies auto it = status_db.find_installed(spec); if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type}; return InstallPlanAction{ - spec, {nullopt, nullopt, port_file_provider.get_control_file(spec)->core_paragraph}, request_type}; + spec, {nullopt, nullopt, *port_file_provider.get_control_file(spec)->core_paragraph}, request_type}; } }; @@ -216,61 +216,6 @@ namespace vcpkg::Dependencies return toposort; } - std::vector create_full_install_plan(const VcpkgPaths& paths, - const std::vector& specs, - const StatusParagraphs& status_db) - { - struct InstallAdjacencyProvider final : Graphs::AdjacencyProvider - { - const VcpkgPaths& paths; - const StatusParagraphs& status_db; - const std::unordered_set& specs_as_set; - - InstallAdjacencyProvider(const VcpkgPaths& p, - const StatusParagraphs& s, - const std::unordered_set& specs_as_set) - : paths(p), status_db(s), specs_as_set(specs_as_set) - { - } - - std::vector adjacency_list(const InstallPlanAction& plan) const override - { - if (plan.any_paragraph.status_paragraph.get()) return std::vector{}; - return plan.any_paragraph.dependencies(plan.spec.triplet()); - } - - InstallPlanAction load_vertex_data(const PackageSpec& spec) const override - { - const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() - ? RequestType::USER_REQUESTED - : RequestType::AUTO_SELECTED; - auto it = status_db.find_installed(spec); - if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type}; - - Expected maybe_bpgh = Paragraphs::try_load_cached_package(paths, spec); - if (auto bpgh = maybe_bpgh.get()) - return InstallPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type}; - - auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); - if (auto scf = maybe_scf.get()) - return InstallPlanAction{spec, {nullopt, nullopt, *scf->get()->core_paragraph}, request_type}; - - print_error_message(maybe_scf.error()); - Checks::exit_fail(VCPKG_LINE_INFO); - } - }; - - const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); - std::vector toposort = - Graphs::topological_sort(specs, InstallAdjacencyProvider{paths, status_db, specs_as_set}); - Util::erase_remove_if(toposort, [](const InstallPlanAction& plan) { - return plan.request_type == RequestType::AUTO_SELECTED && - plan.plan_type == InstallPlanType::ALREADY_INSTALLED; - }); - - return toposort; - } - std::vector create_remove_plan(const std::vector& specs, const StatusParagraphs& status_db) { -- cgit v1.2.3 From 7944f9f7779ebbc0923efd27cff268ac23b1c312 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Tue, 27 Jun 2017 14:52:26 -0700 Subject: refactor create_install_plan tests --- toolsrc/src/commands_ci.cpp | 3 +- toolsrc/src/commands_install.cpp | 3 +- toolsrc/src/test_install_plan.cpp | 118 +++++++++++++++++-------------------- toolsrc/src/vcpkg_Dependencies.cpp | 14 ++--- 4 files changed, 64 insertions(+), 74 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index 5f6fc95b5..95d722302 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -40,8 +40,9 @@ namespace vcpkg::Commands::CI const std::vector specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet); StatusParagraphs status_db = database_load_check(paths); + auto paths_port_file = Dependencies::PathsPortFile(paths); const std::vector install_plan = - Dependencies::create_install_plan(Dependencies::PathsPortFile(paths), specs, status_db); + Dependencies::create_install_plan(paths_port_file, specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); std::vector results; diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index a58432eef..d340a9cf8 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -359,8 +359,9 @@ namespace vcpkg::Commands::Install // create the plan StatusParagraphs status_db = database_load_check(paths); + auto paths_port_file = Dependencies::PathsPortFile(paths); std::vector install_plan = - Dependencies::create_install_plan(Dependencies::PathsPortFile(paths), specs, status_db); + Dependencies::create_install_plan(paths_port_file, specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); // log the plan diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 2404e30f7..93a1436d8 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -9,12 +9,11 @@ namespace UnitTest1 { class InstallPlanTests : public TestClass { - TEST_METHOD(basic_install_scheme) + struct PackageSpecMap { - std::vector> status_paragraphs; - std::unordered_map map; - auto add_scf = [&](std::vector>&& fields) -> PackageSpec { + PackageSpec get_package_spec(std::vector>&& fields) + { auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(fields)); Assert::IsTrue(m_pgh.has_value()); auto& scf = *m_pgh.get(); @@ -23,13 +22,19 @@ namespace UnitTest1 Assert::IsTrue(spec.has_value()); map.emplace(*spec.get(), std::move(*scf.get())); return PackageSpec{*spec.get()}; - }; + } + }; + TEST_METHOD(basic_install_scheme) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map; - auto spec_a = add_scf({{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "b"}}}); - auto spec_b = add_scf({{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", "c"}}}); - auto spec_c = add_scf({{{"Source", "c"}, {"Version", "2.5.3"}, {"Build-Depends", ""}}}); + auto spec_a = spec_map.get_package_spec({{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "b"}}}); + auto spec_b = spec_map.get_package_spec({{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", "c"}}}); + auto spec_c = spec_map.get_package_spec({{{"Source", "c"}, {"Version", "2.5.3"}, {"Build-Depends", ""}}}); - auto map_port = Dependencies::MapPortFile(map); + auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); @@ -43,43 +48,30 @@ namespace UnitTest1 { std::vector> status_paragraphs; - std::unordered_map map; - auto add_scf = [&](std::vector>&& fields) -> PackageSpec { - auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(fields)); - Assert::IsTrue(m_pgh.has_value()); - auto& scf = *m_pgh.get(); - - auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, Triplet::X86_WINDOWS); - Assert::IsTrue(spec.has_value()); - map.emplace(*spec.get(), std::move(*scf.get())); - return PackageSpec{*spec.get()}; - }; + PackageSpecMap spec_map; - auto spec_a = add_scf({{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "d"}}}); - auto spec_b = add_scf({{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", "d, e"}}}); - auto spec_c = add_scf({{{"Source", "c"}, {"Version", "2.5.3"}, {"Build-Depends", "e, h"}}}); - auto spec_d = add_scf({{{"Source", "d"}, {"Version", "4.0"}, {"Build-Depends", "f, g, h"}}}); - auto spec_e = add_scf({{{"Source", "e"}, {"Version", "1.0"}, {"Build-Depends", "g"}}}); - auto spec_f = add_scf({{{"Source", "f"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); - auto spec_g = add_scf({{{"Source", "g"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); - auto spec_h = add_scf({{{"Source", "h"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); + auto spec_a = spec_map.get_package_spec({{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "d"}}}); + auto spec_b = spec_map.get_package_spec({{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", "d, e"}}}); + auto spec_c = + spec_map.get_package_spec({{{"Source", "c"}, {"Version", "2.5.3"}, {"Build-Depends", "e, h"}}}); + auto spec_d = + spec_map.get_package_spec({{{"Source", "d"}, {"Version", "4.0"}, {"Build-Depends", "f, g, h"}}}); + auto spec_e = spec_map.get_package_spec({{{"Source", "e"}, {"Version", "1.0"}, {"Build-Depends", "g"}}}); + auto spec_f = spec_map.get_package_spec({{{"Source", "f"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); + auto spec_g = spec_map.get_package_spec({{{"Source", "g"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); + auto spec_h = spec_map.get_package_spec({{{"Source", "h"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); - auto map_port = Dependencies::MapPortFile(map); + auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = Dependencies::create_install_plan( map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); auto iterator_pos = [&](const PackageSpec& spec) -> int { - int counter = 0; - for (auto&& install_p : install_plan) - { - if (install_p.spec == spec) - { - return counter; - } - counter++; - } - return -1; + auto it = std::find_if( + install_plan.begin(), install_plan.end(), [&](auto& action) { return action.spec == spec; }); + Assert::IsTrue(it != install_plan.end()); + return (int)(it - install_plan.begin()); }; + int a_pos = iterator_pos(spec_a), b_pos = iterator_pos(spec_b), c_pos = iterator_pos(spec_c), d_pos = iterator_pos(spec_d), e_pos = iterator_pos(spec_e), f_pos = iterator_pos(spec_f), g_pos = iterator_pos(spec_g), h_pos = iterator_pos(spec_h); @@ -112,32 +104,28 @@ namespace UnitTest1 {"Depends", ""}, {"Status", "install ok installed"}})); - std::unordered_map map; - auto add_scf = [&](std::vector>&& fields) -> PackageSpec { - auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(fields)); - Assert::IsTrue(m_pgh.has_value()); - auto& scf = *m_pgh.get(); - - auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, Triplet::X86_WINDOWS); - Assert::IsTrue(spec.has_value()); - map.emplace(*spec.get(), std::move(*scf.get())); - return PackageSpec{*spec.get()}; - }; - - auto spec_h = add_scf({{{"Source", "h"}, {"Version", "1.2.8"}, {"Build-Depends", "j, k"}}}); - auto spec_c = add_scf({{{"Source", "c"}, {"Version", "1.2.8"}, {"Build-Depends", "d, e, f, g, h, j, k"}}}); - auto spec_k = add_scf({{{"Source", "k"}, {"Version", "1.2.8"}, {"Build-Depends", ""}}}); - auto spec_b = - add_scf({{{"Source", "b"}, {"Version", "1.2.8"}, {"Build-Depends", "c, d, e, f, g, h, j, k"}}}); - auto spec_d = add_scf({{{"Source", "d"}, {"Version", "1.2.8"}, {"Build-Depends", "e, f, g, h, j, k"}}}); - auto spec_j = add_scf({{{"Source", "j"}, {"Version", "1.2.8"}, {"Build-Depends", "k"}}}); - auto spec_f = add_scf({{{"Source", "f"}, {"Version", "1.2.8"}, {"Build-Depends", "g, h, j, k"}}}); - auto spec_e = add_scf({{{"Source", "e"}, {"Version", "1.2.8"}, {"Build-Depends", "f, g, h, j, k"}}}); - auto spec_a = - add_scf({{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "b, c, d, e, f, g, h, j, k"}}}); - auto spec_g = add_scf({{{"Source", "g"}, {"Version", "1.2.8"}, {"Build-Depends", "h, j, k"}}}); - - auto map_port = Dependencies::MapPortFile(map); + PackageSpecMap spec_map; + + auto spec_h = + spec_map.get_package_spec({{{"Source", "h"}, {"Version", "1.2.8"}, {"Build-Depends", "j, k"}}}); + auto spec_c = spec_map.get_package_spec( + {{{"Source", "c"}, {"Version", "1.2.8"}, {"Build-Depends", "d, e, f, g, h, j, k"}}}); + auto spec_k = spec_map.get_package_spec({{{"Source", "k"}, {"Version", "1.2.8"}, {"Build-Depends", ""}}}); + auto spec_b = spec_map.get_package_spec( + {{{"Source", "b"}, {"Version", "1.2.8"}, {"Build-Depends", "c, d, e, f, g, h, j, k"}}}); + auto spec_d = spec_map.get_package_spec( + {{{"Source", "d"}, {"Version", "1.2.8"}, {"Build-Depends", "e, f, g, h, j, k"}}}); + auto spec_j = spec_map.get_package_spec({{{"Source", "j"}, {"Version", "1.2.8"}, {"Build-Depends", "k"}}}); + auto spec_f = + spec_map.get_package_spec({{{"Source", "f"}, {"Version", "1.2.8"}, {"Build-Depends", "g, h, j, k"}}}); + auto spec_e = spec_map.get_package_spec( + {{{"Source", "e"}, {"Version", "1.2.8"}, {"Build-Depends", "f, g, h, j, k"}}}); + auto spec_a = spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "b, c, d, e, f, g, h, j, k"}}}); + auto spec_g = + spec_map.get_package_spec({{{"Source", "g"}, {"Version", "1.2.8"}, {"Build-Depends", "h, j, k"}}}); + + auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 726c147fd..984d0ab4c 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -140,23 +140,23 @@ namespace vcpkg::Dependencies } MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map){}; - const SourceControlFile* MapPortFile::get_control_file(const PackageSpec& spec) const + const SourceControlFile& MapPortFile::get_control_file(const PackageSpec& spec) const { auto scf = ports.find(spec); if (scf == ports.end()) { Checks::exit_fail(VCPKG_LINE_INFO); } - return &scf->second; + return scf->second; } PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths){}; - const SourceControlFile* PathsPortFile::get_control_file(const PackageSpec& spec) const + const SourceControlFile& PathsPortFile::get_control_file(const PackageSpec& spec) const { std::unordered_map::iterator cache_it = cache.find(spec); if (cache_it != cache.end()) { - return &cache_it->second; + return cache_it->second; } Parse::ParseExpected source_control_file = Paragraphs::try_load_port(ports.get_filesystem(), ports.port_dir(spec)); @@ -164,9 +164,9 @@ namespace vcpkg::Dependencies if (auto scf = source_control_file.get()) { auto it = cache.emplace(spec, std::move(*scf->get())); - return &it.first->second; + return it.first->second; } - + print_error_message(source_control_file.error()); Checks::exit_fail(VCPKG_LINE_INFO); } @@ -201,7 +201,7 @@ namespace vcpkg::Dependencies auto it = status_db.find_installed(spec); if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type}; return InstallPlanAction{ - spec, {nullopt, nullopt, *port_file_provider.get_control_file(spec)->core_paragraph}, request_type}; + spec, {nullopt, nullopt, *port_file_provider.get_control_file(spec).core_paragraph}, request_type}; } }; -- cgit v1.2.3 From 4267c86b1f7cfe20e88fe7a1eaaa4caaca8c5d77 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 7 Jul 2017 17:19:19 -0700 Subject: [grpc] Use vcpkg_copy_tool_dependencies --- toolsrc/src/PostBuildLint.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 82d50a68f..8e11ae5b1 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -775,15 +775,15 @@ namespace vcpkg::PostBuildLint error_count += check_lib_architecture(pre_build_info.target_architecture, libs); } + std::vector debug_dlls = fs.get_files_recursive(debug_bin_dir); + Util::unstable_keep_if(debug_dlls, has_extension_pred(fs, ".dll")); + std::vector release_dlls = fs.get_files_recursive(release_bin_dir); + Util::unstable_keep_if(release_dlls, has_extension_pred(fs, ".dll")); + switch (build_info.library_linkage) { case Build::LinkageType::DYNAMIC: { - std::vector debug_dlls = fs.get_files_recursive(debug_bin_dir); - Util::unstable_keep_if(debug_dlls, has_extension_pred(fs, ".dll")); - std::vector release_dlls = fs.get_files_recursive(release_bin_dir); - Util::unstable_keep_if(release_dlls, has_extension_pred(fs, ".dll")); - error_count += check_matching_debug_and_release_binaries(debug_dlls, release_dlls); error_count += check_lib_files_are_available_if_dlls_are_available( @@ -804,8 +804,8 @@ namespace vcpkg::PostBuildLint } case Build::LinkageType::STATIC: { - std::vector dlls = fs.get_files_recursive(package_dir); - Util::unstable_keep_if(dlls, has_extension_pred(fs, ".dll")); + auto dlls = release_dlls; + dlls.insert(dlls.end(), debug_dlls.begin(), debug_dlls.end()); error_count += check_no_dlls_present(dlls); error_count += check_bin_folders_are_not_present_in_static_build(fs, package_dir); -- cgit v1.2.3 From 6f31f2d1b92f19cf8972dff67a5ef79905942a8d Mon Sep 17 00:00:00 2001 From: Maktm Date: Sun, 9 Jul 2017 01:28:51 -0500 Subject: Adds a missing new line statement --- toolsrc/src/commands_help.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_help.cpp b/toolsrc/src/commands_help.cpp index a9f9956fe..e4be11a77 100644 --- a/toolsrc/src/commands_help.cpp +++ b/toolsrc/src/commands_help.cpp @@ -56,7 +56,7 @@ namespace vcpkg::Commands::Help std::string create_example_string(const std::string& command_and_arguments) { std::string cs = Strings::format("Example:\n" - " vcpkg %s", + " vcpkg %s\n", command_and_arguments); return cs; } -- cgit v1.2.3 From fe602fc3581e3e9d99a64d759a45fc63d49f7f59 Mon Sep 17 00:00:00 2001 From: atkawa7 Date: Tue, 11 Jul 2017 08:58:15 -0700 Subject: [vcpkg] remove flushall --- toolsrc/src/vcpkg_System.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index c91c6be78..883fe6612 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -94,7 +94,7 @@ namespace vcpkg::System }; // Flush stdout before launching external process - _flushall(); + fflush(nullptr); std::vector env_cstr; env_cstr.reserve(env_wstrings.size() + 2); @@ -125,7 +125,7 @@ namespace vcpkg::System int cmd_execute(const CWStringView cmd_line) { // Flush stdout before launching external process - _flushall(); + fflush(nullptr); // Basically we are wrapping it in quotes const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); -- cgit v1.2.3 From e9ba08be3aeaaea3cfc5a8455fac41384e2d7f93 Mon Sep 17 00:00:00 2001 From: atkawa7 Date: Wed, 12 Jul 2017 20:28:14 -0700 Subject: [vcpkg] remove platform dependency of string format --- toolsrc/src/vcpkg_Strings.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index aafed5fd3..77ff1a106 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -19,26 +19,36 @@ namespace vcpkg::Strings::details std::string format_internal(const char* fmtstr, ...) { - va_list lst; - va_start(lst, fmtstr); + va_list args; + va_start(args, fmtstr); - const int sz = _vscprintf_l(fmtstr, c_locale(), lst); - std::string output(sz, '\0'); - _vsnprintf_s_l(&output[0], output.size() + 1, output.size() + 1, fmtstr, c_locale(), lst); - va_end(lst); + int sz = vsnprintf(nullptr, 0, fmtstr, args) + 1; + + char* buffer = new char[sz]; + + vsnprintf(buffer, sz, fmtstr, args); + va_end(args); + + std::string output(buffer); + delete[] buffer; return output; } std::wstring wformat_internal(const wchar_t* fmtstr, ...) { - va_list lst; - va_start(lst, fmtstr); + va_list args; + va_start(args, fmtstr); + + int sz = vswprintf(nullptr, 0, fmtstr, args) + 1; + + wchar_t* buffer = new wchar_t[sz]; + + vswprintf(buffer, sz, fmtstr, args); + va_end(args); - const int sz = _vscwprintf_l(fmtstr, c_locale(), lst); - std::wstring output(sz, '\0'); - _vsnwprintf_s_l(&output[0], output.size() + 1, output.size() + 1, fmtstr, c_locale(), lst); - va_end(lst); + std::wstring output(buffer); + delete[] buffer; return output; } -- cgit v1.2.3 From 336e25218a73f9b54120e3c35b3d28e6426deeb1 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Wed, 12 Jul 2017 17:40:41 -0700 Subject: feature packages graph traversal --- toolsrc/src/BinaryParagraph.cpp | 11 +- toolsrc/src/PackageSpec.cpp | 5 +- toolsrc/src/test_install_plan.cpp | 308 +++++++++++++++++++++++++++++++++++++ toolsrc/src/vcpkg_Dependencies.cpp | 244 +++++++++++++++++++++++++++++ 4 files changed, 566 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index af76c6b29..e126054a8 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -16,9 +16,11 @@ namespace vcpkg namespace Fields { + static const std::string FEATURE = "Feature"; static const std::string DESCRIPTION = "Description"; static const std::string MAINTAINER = "Maintainer"; static const std::string DEPENDS = "Depends"; + static const std::string DEFAULTFEATURES = "Default-Features"; } BinaryParagraph::BinaryParagraph() = default; @@ -38,7 +40,10 @@ namespace vcpkg .value_or_exit(VCPKG_LINE_INFO); } - parser.required_field(Fields::VERSION, this->version); + // one or the other + this->version = parser.optional_field(Fields::VERSION); + this->feature = parser.optional_field(Fields::FEATURE); + this->description = parser.optional_field(Fields::DESCRIPTION); this->maintainer = parser.optional_field(Fields::MAINTAINER); @@ -46,6 +51,10 @@ namespace vcpkg parser.required_field(Fields::MULTI_ARCH, multi_arch); this->depends = parse_comma_list(parser.optional_field(Fields::DEPENDS)); + if (this->feature.empty()) + { + this->default_features = parse_comma_list(parser.optional_field(Fields::DEFAULTFEATURES)); + } if (auto err = parser.error_info(this->spec.name())) { diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index ab005f255..12217ac98 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -5,7 +5,10 @@ namespace vcpkg { - static bool is_valid_package_spec_char(char c) { return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)); } + static bool is_valid_package_spec_char(char c) + { + return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)) || (c == '[') || (c == ']'); + } ExpectedT PackageSpec::from_string(const std::string& spec_as_string, const Triplet& default_triplet) diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 93a1436d8..d90e1e523 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -1,5 +1,6 @@ #include "CppUnitTest.h" #include "vcpkg_Dependencies.h" +#include "vcpkg_Util.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; @@ -24,6 +25,35 @@ namespace UnitTest1 return PackageSpec{*spec.get()}; } }; + + static void features_check(Dependencies::AnyAction* install_action, + std::string pkg_name, + std::vector vec) + { + const auto& plan = *install_action->install_plan.get(); + const auto& feature_list = plan.feature_list; + + Assert::AreEqual(pkg_name.c_str(), + (*plan.any_paragraph.source_control_file.get())->core_paragraph->name.c_str()); + Assert::AreEqual(size_t(vec.size()), feature_list.size()); + + for (auto&& feature_name : vec) + { + if (feature_name == "core" || feature_name == "") + { + Assert::IsTrue(Util::find(feature_list, "core") != feature_list.end() || + Util::find(feature_list, "") != feature_list.end()); + continue; + } + Assert::IsTrue(Util::find(feature_list, feature_name) != feature_list.end()); + } + } + + static void remove_plan_check(Dependencies::AnyAction* install_action, std::string pkg_name) + { + Assert::AreEqual(pkg_name.c_str(), install_action->remove_plan.get()->spec.name().c_str()); + } + TEST_METHOD(basic_install_scheme) { std::vector> status_paragraphs; @@ -139,5 +169,283 @@ namespace UnitTest1 Assert::AreEqual("b", install_plan[6].spec.name().c_str()); Assert::AreEqual("a", install_plan[7].spec.name().c_str()); } + + TEST_METHOD(basic_feature_test_1) + { + using Pgh = std::unordered_map; + + std::vector> status_paragraphs; + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, + {"Default-Features", ""}, + {"Version", "1.3.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", "b, b[beefeatureone]"}, + {"Status", "install ok installed"}})); + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, + {"Feature", "beefeatureone"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", ""}, + {"Status", "install ok installed"}})); + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, + {"Default-Features", "beefeatureone"}, + {"Version", "1.3"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", ""}, + {"Status", "install ok installed"}})); + + PackageSpecMap spec_map; + + auto spec_a = + FullPackageSpec{spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b, b[beefeatureone]"}}, + {{"Feature", "featureone"}, + {"Description", "the first feature for a"}, + {"Build-Depends", "b[beefeaturetwo]"}} + + }), + {"featureone"}}; + auto spec_b = FullPackageSpec{spec_map.get_package_spec( + {{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, + {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, + {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}} + + })}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(4), install_plan.size()); + remove_plan_check(&install_plan[0], "a"); + remove_plan_check(&install_plan[1], "b"); + features_check(&install_plan[2], "b", {"beefeatureone", "core", "beefeatureone"}); + features_check(&install_plan[3], "a", {"featureone", "core"}); + } + + TEST_METHOD(basic_feature_test_2) + { + using Pgh = std::unordered_map; + + std::vector> status_paragraphs; + + PackageSpecMap spec_map; + + auto spec_a = + FullPackageSpec{spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b[beefeatureone]"}}, + {{"Feature", "featureone"}, + {"Description", "the first feature for a"}, + {"Build-Depends", "b[beefeaturetwo]"}} + + }), + {"featureone"}}; + auto spec_b = FullPackageSpec{spec_map.get_package_spec( + {{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, + {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, + {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}} + + })}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(2), install_plan.size()); + features_check(&install_plan[0], "b", {"beefeatureone", "beefeaturetwo", "core"}); + features_check(&install_plan[1], "a", {"featureone", "core"}); + } + + TEST_METHOD(basic_feature_test_3) + { + using Pgh = std::unordered_map; + + std::vector> status_paragraphs; + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, + {"Default-Features", ""}, + {"Version", "1.3"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", ""}, + {"Status", "install ok installed"}})); + + PackageSpecMap spec_map; + + auto spec_a = FullPackageSpec{ + spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, + {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), + {"core"}}; + auto spec_b = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + })}; + auto spec_c = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, + }), + {"core"}}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, {spec_c, spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(4), install_plan.size()); + remove_plan_check(&install_plan[0], "a"); + features_check(&install_plan[1], "b", {"core"}); + features_check(&install_plan[2], "a", {"one", "core"}); + features_check(&install_plan[3], "c", {"core"}); + } + + TEST_METHOD(basic_feature_test_4) + { + using Pgh = std::unordered_map; + + std::vector> status_paragraphs; + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, + {"Default-Features", ""}, + {"Version", "1.3"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", ""}, + {"Status", "install ok installed"}})); + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, + {"Feature", "one"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", ""}, + {"Status", "install ok installed"}})); + + PackageSpecMap spec_map; + + auto spec_a = FullPackageSpec{ + spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, + {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), + }; + auto spec_b = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + })}; + auto spec_c = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, + }), + {"core"}}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, {spec_c}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(1), install_plan.size()); + features_check(&install_plan[0], "c", {"core"}); + } + + TEST_METHOD(basic_feature_test_5) + { + using Pgh = std::unordered_map; + + std::vector> status_paragraphs; + + PackageSpecMap spec_map; + + auto spec_a = FullPackageSpec{ + spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[1]"}}, + {{"Feature", "2"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[2]"}}, + {{"Feature", "3"}, {"Description", "the first feature for a"}, {"Build-Depends", "a[2]"}}}), + {"3"}}; + auto spec_b = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, + {{"Feature", "2"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, + })}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(2), install_plan.size()); + features_check(&install_plan[0], "b", {"core", "2"}); + features_check(&install_plan[1], "a", {"core", "3", "2"}); + } + + TEST_METHOD(basic_feature_test_6) + { + using Pgh = std::unordered_map; + + std::vector> status_paragraphs; + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, + {"Default-Features", ""}, + {"Version", "1.3"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", ""}, + {"Status", "install ok installed"}})); + PackageSpecMap spec_map; + + auto spec_a = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b[core]"}}, + }), + {"core"}}; + auto spec_b = FullPackageSpec{ + spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, + }), + {"1"}}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, {spec_a, spec_b}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(3), install_plan.size()); + remove_plan_check(&install_plan[0], "b"); + features_check(&install_plan[1], "b", {"core", "1"}); + features_check(&install_plan[2], "a", {"core"}); + } + + TEST_METHOD(basic_feature_test_7) + { + using Pgh = std::unordered_map; + + std::vector> status_paragraphs; + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "x"}, + {"Default-Features", ""}, + {"Version", "1.3"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", "b"}, + {"Status", "install ok installed"}})); + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, + {"Default-Features", ""}, + {"Version", "1.3"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", ""}, + {"Status", "install ok installed"}})); + PackageSpecMap spec_map; + + auto spec_a = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + })}; + auto spec_x = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "x"}, {"Version", "1.3"}, {"Build-Depends", "a"}}, + }), + {"core"}}; + auto spec_b = FullPackageSpec{ + spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}, {"Default-Features", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, + }), + {"1"}}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, {spec_b, spec_x}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(5), install_plan.size()); + remove_plan_check(&install_plan[0], "x"); + remove_plan_check(&install_plan[1], "b"); + + // order here may change but A < X, and B anywhere + features_check(&install_plan[2], "a", {"core"}); + features_check(&install_plan[3], "x", {"core"}); + features_check(&install_plan[4], "b", {"core", "1"}); + } }; } \ No newline at end of file diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 984d0ab4c..824de15e1 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -54,6 +54,20 @@ namespace vcpkg::Dependencies { } + InstallPlanAction::InstallPlanAction(const PackageSpec& spec, + const SourceControlFile& any_paragraph, + std::unordered_set features, + const RequestType& request_type) + : InstallPlanAction() + { + this->spec = spec; + this->request_type = request_type; + + this->plan_type = InstallPlanType::BUILD_AND_INSTALL; + this->any_paragraph.source_control_file = &any_paragraph; + this->feature_list = features; + } + InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const AnyParagraph& any_paragraph, const RequestType& request_type) @@ -320,4 +334,234 @@ namespace vcpkg::Dependencies Graphs::topological_sort(specs, ExportAdjacencyProvider{paths, status_db, specs_as_set}); return toposort; } + + std::vector to_feature_specs(const std::vector depends, + const std::unordered_map str_to_spec) + { + std::vector f_specs; + for (auto&& depend : depends) + { + int end = (int)depend.find(']'); + if (end != std::string::npos) + { + int start = (int)depend.find('['); + + auto feature_name = depend.substr(start + 1, end - start - 1); + auto package_name = depend.substr(0, start); + auto p_spec = str_to_spec.find(package_name); + if (p_spec != str_to_spec.end()) + { + auto feature_spec = FeatureSpec{p_spec->second, feature_name}; + f_specs.emplace_back(std::move(feature_spec)); + } + } + else + { + auto p_spec = str_to_spec.find(depend); + if (p_spec != str_to_spec.end()) + { + auto feature_spec = FeatureSpec{p_spec->second, ""}; + f_specs.emplace_back(std::move(feature_spec)); + } + } + } + return f_specs; + } + + bool mark_plus(const std::string& feature, + Cluster& cluster, + std::unordered_map& pkg_to_cluster, + GraphPlan& graph_plan) + { + auto it = cluster.edges.find(feature); + std::string updated_feature = feature; + if (updated_feature == "") + { + updated_feature = "core"; + it = cluster.edges.find("core"); + } + if (it == cluster.edges.end()) + { + Checks::exit_fail(VCPKG_LINE_INFO); + } + + if (cluster.edges[updated_feature].plus) return true; + + if (cluster.original_nodes.find(updated_feature) == cluster.original_nodes.end()) + { + cluster.zero = true; + } + + if (!cluster.zero) + { + return false; + } + cluster.edges[updated_feature].plus = true; + + if (!cluster.original_nodes.empty()) + { + mark_minus(cluster, pkg_to_cluster, graph_plan); + } + + graph_plan.install_graph.add_vertex(&cluster); + auto& tracked = cluster.tracked_nodes; + tracked.insert(updated_feature); + if (tracked.find("core") == tracked.end() && tracked.find("") == tracked.end()) + { + cluster.tracked_nodes.insert("core"); + for (auto&& depend : cluster.edges["core"].dashed) + { + auto& depend_cluster = pkg_to_cluster[depend.spec]; + mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); + graph_plan.install_graph.add_edge(&cluster, &depend_cluster); + } + } + + for (auto&& depend : cluster.edges[updated_feature].dashed) + { + auto& depend_cluster = pkg_to_cluster[depend.spec]; + mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); + if (&depend_cluster == &cluster) continue; + graph_plan.install_graph.add_edge(&cluster, &depend_cluster); + } + return true; + } + + void mark_minus(Cluster& cluster, std::unordered_map& pkg_to_cluster, GraphPlan& graph_plan) + { + if (cluster.minus) return; + cluster.minus = true; + + graph_plan.remove_graph.add_vertex(&cluster); + for (auto&& pair : cluster.edges) + { + auto& dotted_edges = pair.second.dotted; + for (auto&& depend : dotted_edges) + { + auto& depend_cluster = pkg_to_cluster[depend.spec]; + graph_plan.remove_graph.add_edge(&cluster, &depend_cluster); + depend_cluster.zero = true; + mark_minus(depend_cluster, pkg_to_cluster, graph_plan); + } + } + for (auto&& original_feature : cluster.original_nodes) + { + cluster.zero = true; + mark_plus(original_feature, cluster, pkg_to_cluster, graph_plan); + } + } + + std::vector create_feature_install_plan(const std::unordered_map& map, + const std::vector& specs, + const StatusParagraphs& status_db) + { + const auto triplet = Triplet::X86_WINDOWS; + std::unordered_map pkg_spec_to_package_node; + std::unordered_map str_to_spec; + + for (const auto& it : map) + { + str_to_spec.emplace(it.first.name(), it.first); + } + + for (const auto& it : map) + { + Cluster& node = pkg_spec_to_package_node[it.first]; + FeatureNodeEdges core_dependencies; + core_dependencies.dashed = + to_feature_specs(filter_dependencies(it.second.core_paragraph->depends, triplet), str_to_spec); + node.edges["core"] = std::move(core_dependencies); + + for (const auto& feature : it.second.feature_paragraphs) + { + FeatureNodeEdges added_edges; + added_edges.dashed = to_feature_specs(filter_dependencies(feature->depends, triplet), str_to_spec); + node.edges.emplace(feature->name, std::move(added_edges)); + } + node.cluster_node.source_paragraph = &it.second; + } + + for (auto&& status_paragraph : status_db) + { + auto& spec = status_paragraph->package.spec; + auto& status_paragraph_feature = status_paragraph->package.feature; + Cluster& cluster = pkg_spec_to_package_node[spec]; + + cluster.zero = false; + auto reverse_edges = to_feature_specs(status_paragraph->package.depends, str_to_spec); + + for (auto&& dependency : reverse_edges) + { + auto pkg_node = pkg_spec_to_package_node.find(dependency.spec); + auto depends_name = dependency.feature_name; + if (depends_name == "") + { + for (auto&& default_feature : status_paragraph->package.default_features) + { + auto& target_node = pkg_node->second.edges[default_feature]; + target_node.dotted.emplace_back(FeatureSpec{spec, status_paragraph_feature}); + } + depends_name = "core"; + } + auto& target_node = pkg_node->second.edges[depends_name]; + target_node.dotted.emplace_back(FeatureSpec{spec, status_paragraph_feature}); + } + cluster.cluster_node.status_paragraphs.emplace_back(*status_paragraph); + if (status_paragraph_feature == "") + { + cluster.original_nodes.insert("core"); + } + else + { + cluster.original_nodes.insert(status_paragraph_feature); + } + } + + GraphPlan graph_plan; + for (auto&& spec : specs) + { + Cluster& spec_cluster = pkg_spec_to_package_node[spec.package_spec]; + for (auto&& feature : spec.features) + { + mark_plus(feature, spec_cluster, pkg_spec_to_package_node, graph_plan); + } + } + + Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); + auto remove_vertex_list = graph_plan.remove_graph.vertex_list(); + auto remove_toposort = Graphs::topological_sort(remove_vertex_list, adjacency_remove_graph); + + Graphs::GraphAdjacencyProvider adjacency_install_graph(graph_plan.install_graph.adjacency_list()); + auto insert_vertex_list = graph_plan.install_graph.vertex_list(); + auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph); + + std::vector install_plan; + + for (auto&& cluster : remove_toposort) + { + auto scf = *cluster->cluster_node.source_paragraph.get(); + + AnyAction any_plan; + any_plan.remove_plan = RemovePlanAction{ + str_to_spec[scf->core_paragraph->name], RemovePlanType::REMOVE, RequestType::AUTO_SELECTED}; + + install_plan.emplace_back(std::move(any_plan)); + } + + for (auto&& cluster : insert_toposort) + { + if (!cluster->zero) continue; + + auto scf = *cluster->cluster_node.source_paragraph.get(); + auto& pkg_spec = str_to_spec[scf->core_paragraph->name]; + auto action = InstallPlanAction{ + pkg_spec, map.find(pkg_spec)->second, cluster->tracked_nodes, RequestType::AUTO_SELECTED}; + + AnyAction any_plan; + any_plan.install_plan = std::move(action); + install_plan.emplace_back(std::move(any_plan)); + } + + return install_plan; + } } -- cgit v1.2.3 From 7cca4a2d59124070661d69912288d73758ed4f94 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Mon, 17 Jul 2017 13:36:33 -0700 Subject: clean tests --- toolsrc/src/test_install_plan.cpp | 98 +++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 55 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index d90e1e523..19cede6df 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -24,6 +24,10 @@ namespace UnitTest1 map.emplace(*spec.get(), std::move(*scf.get())); return PackageSpec{*spec.get()}; } + PackageSpec set_package_map(std::string source, std::string version, std::string build_depends) + { + return get_package_spec({{{"Source", source}, {"Version", version}, {"Build-Depends", build_depends}}}); + } }; static void features_check(Dependencies::AnyAction* install_action, @@ -59,10 +63,9 @@ namespace UnitTest1 std::vector> status_paragraphs; PackageSpecMap spec_map; - - auto spec_a = spec_map.get_package_spec({{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "b"}}}); - auto spec_b = spec_map.get_package_spec({{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", "c"}}}); - auto spec_c = spec_map.get_package_spec({{{"Source", "c"}, {"Version", "2.5.3"}, {"Build-Depends", ""}}}); + auto spec_a = spec_map.set_package_map("a", "1.2.8", "b"); + auto spec_b = spec_map.set_package_map("b", "1.3", "c"); + auto spec_c = spec_map.set_package_map("c", "2.5.3", ""); auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = @@ -79,17 +82,14 @@ namespace UnitTest1 std::vector> status_paragraphs; PackageSpecMap spec_map; - - auto spec_a = spec_map.get_package_spec({{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "d"}}}); - auto spec_b = spec_map.get_package_spec({{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", "d, e"}}}); - auto spec_c = - spec_map.get_package_spec({{{"Source", "c"}, {"Version", "2.5.3"}, {"Build-Depends", "e, h"}}}); - auto spec_d = - spec_map.get_package_spec({{{"Source", "d"}, {"Version", "4.0"}, {"Build-Depends", "f, g, h"}}}); - auto spec_e = spec_map.get_package_spec({{{"Source", "e"}, {"Version", "1.0"}, {"Build-Depends", "g"}}}); - auto spec_f = spec_map.get_package_spec({{{"Source", "f"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); - auto spec_g = spec_map.get_package_spec({{{"Source", "g"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); - auto spec_h = spec_map.get_package_spec({{{"Source", "h"}, {"Version", "1.0"}, {"Build-Depends", ""}}}); + auto spec_a = spec_map.set_package_map("a", "1.2.8", "d"); + auto spec_b = spec_map.set_package_map("b", "1.3", "d, e"); + auto spec_c = spec_map.set_package_map("c", "2.5.3", "e, h"); + auto spec_d = spec_map.set_package_map("d", "4.0", "f, g, h"); + auto spec_e = spec_map.set_package_map("e", "1.0", "g"); + auto spec_f = spec_map.set_package_map("f", "1.0", ""); + auto spec_g = spec_map.set_package_map("g", "1.0", ""); + auto spec_h = spec_map.set_package_map("h", "1.0", ""); auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = Dependencies::create_install_plan( @@ -136,24 +136,16 @@ namespace UnitTest1 PackageSpecMap spec_map; - auto spec_h = - spec_map.get_package_spec({{{"Source", "h"}, {"Version", "1.2.8"}, {"Build-Depends", "j, k"}}}); - auto spec_c = spec_map.get_package_spec( - {{{"Source", "c"}, {"Version", "1.2.8"}, {"Build-Depends", "d, e, f, g, h, j, k"}}}); - auto spec_k = spec_map.get_package_spec({{{"Source", "k"}, {"Version", "1.2.8"}, {"Build-Depends", ""}}}); - auto spec_b = spec_map.get_package_spec( - {{{"Source", "b"}, {"Version", "1.2.8"}, {"Build-Depends", "c, d, e, f, g, h, j, k"}}}); - auto spec_d = spec_map.get_package_spec( - {{{"Source", "d"}, {"Version", "1.2.8"}, {"Build-Depends", "e, f, g, h, j, k"}}}); - auto spec_j = spec_map.get_package_spec({{{"Source", "j"}, {"Version", "1.2.8"}, {"Build-Depends", "k"}}}); - auto spec_f = - spec_map.get_package_spec({{{"Source", "f"}, {"Version", "1.2.8"}, {"Build-Depends", "g, h, j, k"}}}); - auto spec_e = spec_map.get_package_spec( - {{{"Source", "e"}, {"Version", "1.2.8"}, {"Build-Depends", "f, g, h, j, k"}}}); - auto spec_a = spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.2.8"}, {"Build-Depends", "b, c, d, e, f, g, h, j, k"}}}); - auto spec_g = - spec_map.get_package_spec({{{"Source", "g"}, {"Version", "1.2.8"}, {"Build-Depends", "h, j, k"}}}); + auto spec_a = spec_map.set_package_map("a", "1.2.8", "b, c, d, e, f, g, h, j, k"); + auto spec_b = spec_map.set_package_map("b", "1.2.8", "c, d, e, f, g, h, j, k"); + auto spec_c = spec_map.set_package_map("c", "1.2.8", "d, e, f, g, h, j, k"); + auto spec_d = spec_map.set_package_map("d", "1.2.8", "e, f, g, h, j, k"); + auto spec_e = spec_map.set_package_map("e", "1.2.8", "f, g, h, j, k"); + auto spec_f = spec_map.set_package_map("f", "1.2.8", "g, h, j, k"); + auto spec_g = spec_map.set_package_map("g", "1.2.8", "h, j, k"); + auto spec_h = spec_map.set_package_map("h", "1.2.8", "j, k"); + auto spec_j = spec_map.set_package_map("j", "1.2.8", "k"); + auto spec_k = spec_map.set_package_map("k", "1.2.8", ""); auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = @@ -197,23 +189,20 @@ namespace UnitTest1 {"Status", "install ok installed"}})); PackageSpecMap spec_map; - auto spec_a = - FullPackageSpec{spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b, b[beefeatureone]"}}, - {{"Feature", "featureone"}, - {"Description", "the first feature for a"}, - {"Build-Depends", "b[beefeaturetwo]"}} - - }), + FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b, b[beefeatureone]"}}, + {{"Feature", "featureone"}, + {"Description", "the first feature for a"}, + {"Build-Depends", "b[beefeaturetwo]"}}, + }), {"featureone"}}; - auto spec_b = FullPackageSpec{spec_map.get_package_spec( - {{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}} - - })}; + auto spec_b = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, + {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, + {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}}, + })}; auto install_plan = Dependencies::create_feature_install_plan( spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); @@ -242,13 +231,12 @@ namespace UnitTest1 }), {"featureone"}}; - auto spec_b = FullPackageSpec{spec_map.get_package_spec( - {{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}} - - })}; + auto spec_b = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, + {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, + {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}}, + })}; auto install_plan = Dependencies::create_feature_install_plan( spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); -- cgit v1.2.3 From 1445115906139f5c6d14bcbbacdcc0cfb543fd80 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Wed, 19 Jul 2017 14:19:11 -0700 Subject: refactor feature packages --- toolsrc/src/commands_ci.cpp | 2 +- toolsrc/src/test_install_plan.cpp | 2 +- toolsrc/src/vcpkg_Dependencies.cpp | 67 +++++++++++++++++++------------------- 3 files changed, 36 insertions(+), 35 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index 95d722302..f781adf69 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -40,7 +40,7 @@ namespace vcpkg::Commands::CI const std::vector specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet); StatusParagraphs status_db = database_load_check(paths); - auto paths_port_file = Dependencies::PathsPortFile(paths); + const auto& paths_port_file = Dependencies::PathsPortFile(paths); const std::vector install_plan = Dependencies::create_install_plan(paths_port_file, specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 19cede6df..671b6ed67 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -430,7 +430,7 @@ namespace UnitTest1 remove_plan_check(&install_plan[0], "x"); remove_plan_check(&install_plan[1], "b"); - // order here may change but A < X, and B anywhere + // TODO: order here may change but A < X, and B anywhere features_check(&install_plan[2], "a", {"core"}); features_check(&install_plan[3], "x", {"core"}); features_check(&install_plan[4], "b", {"core", "1"}); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 824de15e1..90168813e 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -56,7 +56,7 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const SourceControlFile& any_paragraph, - std::unordered_set features, + const std::unordered_set& features, const RequestType& request_type) : InstallPlanAction() { @@ -153,7 +153,8 @@ namespace vcpkg::Dependencies return left->spec.name() < right->spec.name(); } - MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map){}; + MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map) {} + const SourceControlFile& MapPortFile::get_control_file(const PackageSpec& spec) const { auto scf = ports.find(spec); @@ -164,7 +165,8 @@ namespace vcpkg::Dependencies return scf->second; } - PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths){}; + PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths) {} + const SourceControlFile& PathsPortFile::get_control_file(const PackageSpec& spec) const { std::unordered_map::iterator cache_it = cache.find(spec); @@ -382,34 +384,34 @@ namespace vcpkg::Dependencies } if (it == cluster.edges.end()) { - Checks::exit_fail(VCPKG_LINE_INFO); + Checks::unreachable(VCPKG_LINE_INFO); } if (cluster.edges[updated_feature].plus) return true; - if (cluster.original_nodes.find(updated_feature) == cluster.original_nodes.end()) + if (cluster.original_features.find(updated_feature) == cluster.original_features.end()) { - cluster.zero = true; + cluster.transient_uninstalled = true; } - if (!cluster.zero) + if (!cluster.transient_uninstalled) { return false; } cluster.edges[updated_feature].plus = true; - if (!cluster.original_nodes.empty()) + if (!cluster.original_features.empty()) { mark_minus(cluster, pkg_to_cluster, graph_plan); } graph_plan.install_graph.add_vertex(&cluster); - auto& tracked = cluster.tracked_nodes; + auto& tracked = cluster.to_install_features; tracked.insert(updated_feature); if (tracked.find("core") == tracked.end() && tracked.find("") == tracked.end()) { - cluster.tracked_nodes.insert("core"); - for (auto&& depend : cluster.edges["core"].dashed) + cluster.to_install_features.insert("core"); + for (auto&& depend : cluster.edges["core"].build_edges) { auto& depend_cluster = pkg_to_cluster[depend.spec]; mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); @@ -417,7 +419,7 @@ namespace vcpkg::Dependencies } } - for (auto&& depend : cluster.edges[updated_feature].dashed) + for (auto&& depend : cluster.edges[updated_feature].build_edges) { auto& depend_cluster = pkg_to_cluster[depend.spec]; mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); @@ -429,28 +431,27 @@ namespace vcpkg::Dependencies void mark_minus(Cluster& cluster, std::unordered_map& pkg_to_cluster, GraphPlan& graph_plan) { - if (cluster.minus) return; - cluster.minus = true; + if (cluster.will_remove) return; + cluster.will_remove = true; graph_plan.remove_graph.add_vertex(&cluster); for (auto&& pair : cluster.edges) { - auto& dotted_edges = pair.second.dotted; - for (auto&& depend : dotted_edges) + auto& remove_edges_edges = pair.second.remove_edges; + for (auto&& depend : remove_edges_edges) { auto& depend_cluster = pkg_to_cluster[depend.spec]; graph_plan.remove_graph.add_edge(&cluster, &depend_cluster); - depend_cluster.zero = true; + depend_cluster.transient_uninstalled = true; mark_minus(depend_cluster, pkg_to_cluster, graph_plan); } } - for (auto&& original_feature : cluster.original_nodes) + for (auto&& original_feature : cluster.original_features) { - cluster.zero = true; + cluster.transient_uninstalled = true; mark_plus(original_feature, cluster, pkg_to_cluster, graph_plan); } } - std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db) @@ -468,17 +469,17 @@ namespace vcpkg::Dependencies { Cluster& node = pkg_spec_to_package_node[it.first]; FeatureNodeEdges core_dependencies; - core_dependencies.dashed = + core_dependencies.build_edges = to_feature_specs(filter_dependencies(it.second.core_paragraph->depends, triplet), str_to_spec); node.edges["core"] = std::move(core_dependencies); for (const auto& feature : it.second.feature_paragraphs) { FeatureNodeEdges added_edges; - added_edges.dashed = to_feature_specs(filter_dependencies(feature->depends, triplet), str_to_spec); + added_edges.build_edges = to_feature_specs(filter_dependencies(feature->depends, triplet), str_to_spec); node.edges.emplace(feature->name, std::move(added_edges)); } - node.cluster_node.source_paragraph = &it.second; + node.cluster_data.source_paragraph = &it.second; } for (auto&& status_paragraph : status_db) @@ -487,7 +488,7 @@ namespace vcpkg::Dependencies auto& status_paragraph_feature = status_paragraph->package.feature; Cluster& cluster = pkg_spec_to_package_node[spec]; - cluster.zero = false; + cluster.transient_uninstalled = false; auto reverse_edges = to_feature_specs(status_paragraph->package.depends, str_to_spec); for (auto&& dependency : reverse_edges) @@ -499,21 +500,21 @@ namespace vcpkg::Dependencies for (auto&& default_feature : status_paragraph->package.default_features) { auto& target_node = pkg_node->second.edges[default_feature]; - target_node.dotted.emplace_back(FeatureSpec{spec, status_paragraph_feature}); + target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); } depends_name = "core"; } auto& target_node = pkg_node->second.edges[depends_name]; - target_node.dotted.emplace_back(FeatureSpec{spec, status_paragraph_feature}); + target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); } - cluster.cluster_node.status_paragraphs.emplace_back(*status_paragraph); + cluster.cluster_data.status_paragraphs.emplace_back(*status_paragraph); if (status_paragraph_feature == "") { - cluster.original_nodes.insert("core"); + cluster.original_features.insert("core"); } else { - cluster.original_nodes.insert(status_paragraph_feature); + cluster.original_features.insert(status_paragraph_feature); } } @@ -539,7 +540,7 @@ namespace vcpkg::Dependencies for (auto&& cluster : remove_toposort) { - auto scf = *cluster->cluster_node.source_paragraph.get(); + auto scf = *cluster->cluster_data.source_paragraph.get(); AnyAction any_plan; any_plan.remove_plan = RemovePlanAction{ @@ -550,12 +551,12 @@ namespace vcpkg::Dependencies for (auto&& cluster : insert_toposort) { - if (!cluster->zero) continue; + if (!cluster->transient_uninstalled) continue; - auto scf = *cluster->cluster_node.source_paragraph.get(); + auto scf = *cluster->cluster_data.source_paragraph.get(); auto& pkg_spec = str_to_spec[scf->core_paragraph->name]; auto action = InstallPlanAction{ - pkg_spec, map.find(pkg_spec)->second, cluster->tracked_nodes, RequestType::AUTO_SELECTED}; + pkg_spec, map.find(pkg_spec)->second, cluster->to_install_features, RequestType::AUTO_SELECTED}; AnyAction any_plan; any_plan.install_plan = std::move(action); -- cgit v1.2.3 From 8097e2f3c29eb05f707ad86c712e8523cca9421f Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 24 Jul 2017 09:03:03 -0700 Subject: [vcpkg] ALLOW_OBSOLETE_MSVCRT policy should enable use of all CRTs. --- toolsrc/src/PostBuildLint.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 8e11ae5b1..a5d923ad2 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -38,7 +38,7 @@ namespace vcpkg::PostBuildLint } }; - const std::vector& get_outdated_dynamic_crts(const Build::BuildPolicies& policies) + const std::vector& get_outdated_dynamic_crts() { static const std::vector v_no_msvcrt = { {"msvcp100.dll", R"(msvcp100\.dll)"}, @@ -59,18 +59,7 @@ namespace vcpkg::PostBuildLint {"msvcrt20.dll", R"(msvcrt20\.dll)"}, {"msvcrt40.dll", R"(msvcrt40\.dll)"}}; - static const std::vector v = [&]() { - auto ret = v_no_msvcrt; - ret.push_back(OutdatedDynamicCrt{"msvcrt.dll", R"(msvcrt\.dll)"}); - return ret; - }(); - - if (policies.is_enabled(BuildPolicy::ALLOW_OBSOLETE_MSVCRT)) - { - return v_no_msvcrt; - } - - return v; + return v_no_msvcrt; } static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs, @@ -659,7 +648,7 @@ namespace vcpkg::PostBuildLint const fs::path dumpbin_exe, const BuildInfo& build_info) { - const std::vector& outdated_crts = get_outdated_dynamic_crts(build_info.policies); + if (build_info.policies.is_enabled(BuildPolicy::ALLOW_OBSOLETE_MSVCRT)) return LintStatus::SUCCESS; std::vector dlls_with_outdated_crt; @@ -673,7 +662,7 @@ namespace vcpkg::PostBuildLint "Running command:\n %s\n failed", Strings::to_utf8(cmd_line)); - for (const OutdatedDynamicCrt& outdated_crt : outdated_crts) + for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts()) { if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), outdated_crt.regex)) { -- cgit v1.2.3 From 11f540d7e9a3f43614196f45ab7e82ab3fbed03e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 24 Jul 2017 13:26:45 -0700 Subject: [vcpkg] Use _vsnprintf_s_l on Windows for locale-insensitivity. Avoid manual buffer management. --- toolsrc/src/vcpkg_Strings.cpp | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 77ff1a106..36d017f54 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -11,27 +11,49 @@ namespace vcpkg::Strings::details // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower() static char tolower_char(const char c) { return static_cast(std::tolower(c)); } +#if defined(_WIN32) static _locale_t& c_locale() { static _locale_t c_locale_impl = _create_locale(LC_ALL, "C"); return c_locale_impl; } + static int plat_vsnprintf(_Out_writes_z_(bufsz) char* const buffer, + _In_ size_t const bufsz, + _In_z_ _Printf_format_string_params_(1) char const* const fmtstr, + va_list args) + { + return _vsnprintf_s_l(buffer, bufsz, bufsz, fmtstr, c_locale(), args); + } + static int plat_vswprintf(_Out_writes_z_(bufsz) wchar_t* const buffer, + _In_ size_t const bufsz, + _In_z_ _Printf_format_string_params_(1) wchar_t const* const fmtstr, + va_list args) + { + return _vsnwprintf_s_l(buffer, bufsz, bufsz, fmtstr, c_locale(), args); + } +#else + static int plat_vsnprintf(char* buffer, size_t bufsz, const char* fmtstr, va_list args) + { + return vsnprintf(buffer, bufsz, fmtstr, args); + } + static int plat_vswprintf(char* buffer, size_t bufsz, const char* fmtstr, va_list args) + { + return vswprintf(buffer, bufsz, fmtstr, args); + } +#endif std::string format_internal(const char* fmtstr, ...) { va_list args; va_start(args, fmtstr); - int sz = vsnprintf(nullptr, 0, fmtstr, args) + 1; + int sz = plat_vsnprintf(nullptr, 0, fmtstr, args); - char* buffer = new char[sz]; + std::string output(sz, '\0'); - vsnprintf(buffer, sz, fmtstr, args); + plat_vsnprintf(&output.at(0), output.size() + 1, fmtstr, args); va_end(args); - std::string output(buffer); - delete[] buffer; - return output; } @@ -40,16 +62,13 @@ namespace vcpkg::Strings::details va_list args; va_start(args, fmtstr); - int sz = vswprintf(nullptr, 0, fmtstr, args) + 1; + int sz = plat_vswprintf(nullptr, 0, fmtstr, args); - wchar_t* buffer = new wchar_t[sz]; + std::wstring output(sz, L'\0'); - vswprintf(buffer, sz, fmtstr, args); + plat_vswprintf(&output.at(0), output.size() + 1, fmtstr, args); va_end(args); - std::wstring output(buffer); - delete[] buffer; - return output; } } -- cgit v1.2.3 From c0af06a69141b251f84f75588c18013889a99f76 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 24 Jul 2017 13:34:18 -0700 Subject: [vcpkg] Revert #1450, pending bugfix. --- toolsrc/src/vcpkg_Strings.cpp | 51 ++++++++++--------------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 36d017f54..aafed5fd3 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -11,63 +11,34 @@ namespace vcpkg::Strings::details // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower() static char tolower_char(const char c) { return static_cast(std::tolower(c)); } -#if defined(_WIN32) static _locale_t& c_locale() { static _locale_t c_locale_impl = _create_locale(LC_ALL, "C"); return c_locale_impl; } - static int plat_vsnprintf(_Out_writes_z_(bufsz) char* const buffer, - _In_ size_t const bufsz, - _In_z_ _Printf_format_string_params_(1) char const* const fmtstr, - va_list args) - { - return _vsnprintf_s_l(buffer, bufsz, bufsz, fmtstr, c_locale(), args); - } - static int plat_vswprintf(_Out_writes_z_(bufsz) wchar_t* const buffer, - _In_ size_t const bufsz, - _In_z_ _Printf_format_string_params_(1) wchar_t const* const fmtstr, - va_list args) - { - return _vsnwprintf_s_l(buffer, bufsz, bufsz, fmtstr, c_locale(), args); - } -#else - static int plat_vsnprintf(char* buffer, size_t bufsz, const char* fmtstr, va_list args) - { - return vsnprintf(buffer, bufsz, fmtstr, args); - } - static int plat_vswprintf(char* buffer, size_t bufsz, const char* fmtstr, va_list args) - { - return vswprintf(buffer, bufsz, fmtstr, args); - } -#endif std::string format_internal(const char* fmtstr, ...) { - va_list args; - va_start(args, fmtstr); - - int sz = plat_vsnprintf(nullptr, 0, fmtstr, args); + va_list lst; + va_start(lst, fmtstr); + const int sz = _vscprintf_l(fmtstr, c_locale(), lst); std::string output(sz, '\0'); - - plat_vsnprintf(&output.at(0), output.size() + 1, fmtstr, args); - va_end(args); + _vsnprintf_s_l(&output[0], output.size() + 1, output.size() + 1, fmtstr, c_locale(), lst); + va_end(lst); return output; } std::wstring wformat_internal(const wchar_t* fmtstr, ...) { - va_list args; - va_start(args, fmtstr); - - int sz = plat_vswprintf(nullptr, 0, fmtstr, args); - - std::wstring output(sz, L'\0'); + va_list lst; + va_start(lst, fmtstr); - plat_vswprintf(&output.at(0), output.size() + 1, fmtstr, args); - va_end(args); + const int sz = _vscwprintf_l(fmtstr, c_locale(), lst); + std::wstring output(sz, '\0'); + _vsnwprintf_s_l(&output[0], output.size() + 1, output.size() + 1, fmtstr, c_locale(), lst); + va_end(lst); return output; } -- cgit v1.2.3 From 3c841c6128ebfe8e99a372f2907bd985b533a799 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 24 Jul 2017 13:59:53 -0700 Subject: [vcpkg] Revert revert. Bug fixed. --- toolsrc/src/vcpkg_Strings.cpp | 49 ++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 12 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index aafed5fd3..0c1c1f9f9 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include "vcpkg_Checks.h" #include "vcpkg_Strings.h" #include "vcpkg_Util.h" @@ -11,34 +12,58 @@ namespace vcpkg::Strings::details // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower() static char tolower_char(const char c) { return static_cast(std::tolower(c)); } +#if defined(_WIN32) static _locale_t& c_locale() { static _locale_t c_locale_impl = _create_locale(LC_ALL, "C"); return c_locale_impl; } +#endif std::string format_internal(const char* fmtstr, ...) { - va_list lst; - va_start(lst, fmtstr); + va_list args; + va_start(args, fmtstr); + +#if defined(_WIN32) + const int sz = _vscprintf_l(fmtstr, c_locale(), args); +#else + const int sz = vsnprintf(nullptr, 0, fmtstr, args); +#endif + Checks::check_exit(VCPKG_LINE_INFO, sz > 0); - const int sz = _vscprintf_l(fmtstr, c_locale(), lst); std::string output(sz, '\0'); - _vsnprintf_s_l(&output[0], output.size() + 1, output.size() + 1, fmtstr, c_locale(), lst); - va_end(lst); + +#if defined(_WIN32) + _vsnprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args); +#else + vsnprintf(&output.at(0), output.size() + 1, fmtstr, args); +#endif + va_end(args); return output; } std::wstring wformat_internal(const wchar_t* fmtstr, ...) { - va_list lst; - va_start(lst, fmtstr); - - const int sz = _vscwprintf_l(fmtstr, c_locale(), lst); - std::wstring output(sz, '\0'); - _vsnwprintf_s_l(&output[0], output.size() + 1, output.size() + 1, fmtstr, c_locale(), lst); - va_end(lst); + va_list args; + va_start(args, fmtstr); + +#if defined(_WIN32) + const int sz = _vscwprintf_l(fmtstr, c_locale(), args); +#else + const int sz = vswprintf(nullptr, 0, fmtstr, args); +#endif + Checks::check_exit(VCPKG_LINE_INFO, sz > 0); + + std::wstring output(sz, L'\0'); + +#if defined(_WIN32) + _vsnwprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args); +#else + vswprintf(&output.at(0), output.size() + 1, fmtstr, args); +#endif + va_end(args); return output; } -- cgit v1.2.3 From 59389ca236b005922cf1101f66c957d2396f6371 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Wed, 19 Jul 2017 14:29:28 -0700 Subject: end to end feature pkg draft --- toolsrc/src/BinaryParagraph.cpp | 15 ++++- toolsrc/src/PackageSpec.cpp | 47 ++++++++++++--- toolsrc/src/commands_install.cpp | 38 +++++++++++- toolsrc/src/commands_remove.cpp | 2 +- toolsrc/src/test_install_plan.cpp | 118 ++++++++++++++++++++++++++++++++----- toolsrc/src/tests_paragraph.cpp | 20 ++++--- toolsrc/src/vcpkg_Build.cpp | 62 ++++++++++++++++--- toolsrc/src/vcpkg_Dependencies.cpp | 88 ++++++++++++++------------- toolsrc/src/vcpkg_Input.cpp | 27 ++------- toolsrc/src/vcpkg_Parse.cpp | 12 ---- 10 files changed, 305 insertions(+), 124 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index e126054a8..b6f3e8a87 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -75,6 +75,16 @@ namespace vcpkg this->depends = filter_dependencies(spgh.depends, triplet); } + BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, const Triplet& triplet) + { + this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); + this->version = ""; + this->feature = fpgh.name; + this->description = fpgh.description; + this->maintainer = ""; + this->depends = filter_dependencies(fpgh.depends, triplet); + } + std::string BinaryParagraph::displayname() const { return this->spec.to_string(); } std::string BinaryParagraph::dir() const { return this->spec.dir(); } @@ -87,7 +97,10 @@ namespace vcpkg void serialize(const BinaryParagraph& pgh, std::string& out_str) { out_str.append("Package: ").append(pgh.spec.name()).push_back('\n'); - out_str.append("Version: ").append(pgh.version).push_back('\n'); + if (!pgh.version.empty()) + out_str.append("Version: ").append(pgh.version).push_back('\n'); + else if (!pgh.feature.empty()) + out_str.append("Feature: ").append(pgh.feature).push_back('\n'); if (!pgh.depends.empty()) { out_str.append("Depends: "); diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index 12217ac98..a7e5648cd 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -10,13 +10,47 @@ namespace vcpkg return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)) || (c == '[') || (c == ']'); } - ExpectedT PackageSpec::from_string(const std::string& spec_as_string, - const Triplet& default_triplet) + ExpectedT FullPackageSpec::from_string(const std::string& spec_as_string, + const Triplet& default_triplet) { auto pos = spec_as_string.find(':'); - if (pos == std::string::npos) + auto pos_l_bracket = spec_as_string.find('['); + auto pos_r_bracket = spec_as_string.find(']'); + + FullPackageSpec f; + if (pos == std::string::npos && pos_l_bracket == std::string::npos) + { + f.package_spec = + PackageSpec::from_name_and_triplet(spec_as_string, default_triplet).value_or_exit(VCPKG_LINE_INFO); + return f; + } + else if (pos == std::string::npos) + { + if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) + { + return PackageSpecParseResult::INVALID_CHARACTERS; + } + const std::string name = spec_as_string.substr(0, pos_l_bracket); + f.package_spec = PackageSpec::from_name_and_triplet(name, default_triplet).value_or_exit(VCPKG_LINE_INFO); + f.features = parse_comma_list(spec_as_string.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); + return f; + } + else if (pos_l_bracket == std::string::npos && pos_r_bracket == std::string::npos) + { + const std::string name = spec_as_string.substr(0, pos); + const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1)); + f.package_spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO); + } + else { - return from_name_and_triplet(spec_as_string, default_triplet); + if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) + { + return PackageSpecParseResult::INVALID_CHARACTERS; + } + const std::string name = spec_as_string.substr(0, pos_l_bracket); + f.features = parse_comma_list(spec_as_string.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); + const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1)); + f.package_spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO); } auto pos2 = spec_as_string.find(':', pos + 1); @@ -24,10 +58,7 @@ namespace vcpkg { return PackageSpecParseResult::TOO_MANY_COLONS; } - - const std::string name = spec_as_string.substr(0, pos); - const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1)); - return from_name_and_triplet(name, triplet); + return f; } ExpectedT PackageSpec::from_name_and_triplet(const std::string& name, diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index d340a9cf8..2ce5b6c62 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -16,6 +16,8 @@ namespace vcpkg::Commands::Install using Dependencies::InstallPlanAction; using Dependencies::RequestType; using Dependencies::InstallPlanType; + using Dependencies::RemovePlanAction; + using Dependencies::RemovePlanType; InstallDir InstallDir::from_destination_root(const fs::path& destination_root, const std::string& destination_subdirectory, @@ -290,7 +292,7 @@ namespace vcpkg::Commands::Install return BuildResult::SUCCEEDED; } - if (plan_type == InstallPlanType::BUILD_AND_INSTALL) + if (plan_type == InstallPlanType::BUILD_AND_INSTALL && !g_feature_packages) { if (use_head_version) System::println("Building package %s from HEAD... ", display_name); @@ -318,7 +320,36 @@ namespace vcpkg::Commands::Install return BuildResult::SUCCEEDED; } - if (plan_type == InstallPlanType::INSTALL) + if (plan_type == InstallPlanType::BUILD_AND_INSTALL && g_feature_packages) + { + if (use_head_version) + System::println("Building package %s from HEAD... ", display_name); + else + System::println("Building package %s... ", display_name); + + const Build::BuildPackageConfig build_config{ + *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), + action.spec.triplet(), + paths.port_dir(action.spec), + build_package_options, + action.feature_list}; + const auto result = Build::build_package(paths, build_config, status_db); + if (result.code != Build::BuildResult::SUCCEEDED) + { + System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); + return result.code; + } + System::println("Building package %s... done", display_name); + + const BinaryParagraph bpgh = + Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); + System::println("Installing package %s... ", display_name); + install_package(paths, bpgh, &status_db); + System::println(System::Color::success, "Installing package %s... done", display_name); + return BuildResult::SUCCEEDED; + } + + if (plan_type == InstallPlanType::INSTALL && !g_feature_packages) { if (use_head_version && is_user_requested) { @@ -359,7 +390,8 @@ namespace vcpkg::Commands::Install // create the plan StatusParagraphs status_db = database_load_check(paths); - auto paths_port_file = Dependencies::PathsPortFile(paths); + + Dependencies::PathsPortFile paths_port_file(paths); std::vector install_plan = Dependencies::create_install_plan(paths_port_file, specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index e2b5d12a1..eabf2b9ae 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -14,7 +14,7 @@ namespace vcpkg::Commands::Remove using Dependencies::RequestType; using Update::OutdatedPackage; - static void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db) + void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db) { auto& fs = paths.get_filesystem(); StatusParagraph& pkg = **status_db->find(spec.name(), spec.triplet()); diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 671b6ed67..d02af5662 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -13,13 +13,16 @@ namespace UnitTest1 struct PackageSpecMap { std::unordered_map map; + Triplet triplet; + PackageSpecMap(const Triplet& t) { triplet = t; } + PackageSpec get_package_spec(std::vector>&& fields) { auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(fields)); Assert::IsTrue(m_pgh.has_value()); auto& scf = *m_pgh.get(); - auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, Triplet::X86_WINDOWS); + auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, triplet); Assert::IsTrue(spec.has_value()); map.emplace(*spec.get(), std::move(*scf.get())); return PackageSpec{*spec.get()}; @@ -32,11 +35,14 @@ namespace UnitTest1 static void features_check(Dependencies::AnyAction* install_action, std::string pkg_name, - std::vector vec) + std::vector vec, + const Triplet& triplet = Triplet::X86_WINDOWS) { - const auto& plan = *install_action->install_plan.get(); + const auto& plan = install_action->install_plan.value_or_exit(VCPKG_LINE_INFO); const auto& feature_list = plan.feature_list; + Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); + Assert::AreEqual(pkg_name.c_str(), (*plan.any_paragraph.source_control_file.get())->core_paragraph->name.c_str()); Assert::AreEqual(size_t(vec.size()), feature_list.size()); @@ -53,16 +59,20 @@ namespace UnitTest1 } } - static void remove_plan_check(Dependencies::AnyAction* install_action, std::string pkg_name) + static void remove_plan_check(Dependencies::AnyAction* remove_action, + std::string pkg_name, + const Triplet& triplet = Triplet::X86_WINDOWS) { - Assert::AreEqual(pkg_name.c_str(), install_action->remove_plan.get()->spec.name().c_str()); + const auto& plan = remove_action->remove_plan.value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); + Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); } TEST_METHOD(basic_install_scheme) { std::vector> status_paragraphs; - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = spec_map.set_package_map("a", "1.2.8", "b"); auto spec_b = spec_map.set_package_map("b", "1.3", "c"); auto spec_c = spec_map.set_package_map("c", "2.5.3", ""); @@ -81,7 +91,7 @@ namespace UnitTest1 { std::vector> status_paragraphs; - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = spec_map.set_package_map("a", "1.2.8", "d"); auto spec_b = spec_map.set_package_map("b", "1.3", "d, e"); auto spec_c = spec_map.set_package_map("c", "2.5.3", "e, h"); @@ -134,7 +144,7 @@ namespace UnitTest1 {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = spec_map.set_package_map("a", "1.2.8", "b, c, d, e, f, g, h, j, k"); auto spec_b = spec_map.set_package_map("b", "1.2.8", "c, d, e, f, g, h, j, k"); @@ -188,7 +198,7 @@ namespace UnitTest1 {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{spec_map.get_package_spec({ {{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b, b[beefeatureone]"}}, @@ -220,7 +230,7 @@ namespace UnitTest1 std::vector> status_paragraphs; - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{spec_map.get_package_spec( @@ -259,7 +269,7 @@ namespace UnitTest1 {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{ spec_map.get_package_spec( @@ -303,7 +313,7 @@ namespace UnitTest1 {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{ spec_map.get_package_spec( @@ -331,7 +341,7 @@ namespace UnitTest1 std::vector> status_paragraphs; - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{ spec_map.get_package_spec( @@ -366,7 +376,7 @@ namespace UnitTest1 {"Multi-Arch", "same"}, {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{spec_map.get_package_spec({ {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b[core]"}}, @@ -407,7 +417,7 @@ namespace UnitTest1 {"Multi-Arch", "same"}, {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{spec_map.get_package_spec({ {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}}, @@ -435,5 +445,83 @@ namespace UnitTest1 features_check(&install_plan[3], "x", {"core"}); features_check(&install_plan[4], "b", {"core", "1"}); } + + TEST_METHOD(basic_feature_test_8) + { + using Pgh = std::unordered_map; + + std::vector> status_paragraphs; + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, + {"Default-Features", ""}, + {"Version", "1.3"}, + {"Architecture", "x64-windows"}, + {"Multi-Arch", "same"}, + {"Depends", ""}, + {"Status", "install ok installed"}})); + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, + {"Default-Features", ""}, + {"Version", "1.3"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", ""}, + {"Status", "install ok installed"}})); + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + + auto spec_a_64 = FullPackageSpec{ + spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, + {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), + {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + })}; + auto spec_c_64 = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, + }), + {"core"}}; + + spec_map.triplet = Triplet::X86_WINDOWS; + auto spec_a_86 = FullPackageSpec{ + spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, + {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), + {"core"}}; + auto spec_b_86 = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + })}; + auto spec_c_86 = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, + }), + {"core"}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + {spec_c_64, spec_a_86, spec_a_64, spec_c_86}, + StatusParagraphs(std::move(status_paragraphs))); + + /*Assert::AreEqual(size_t(8), install_plan.size()); + auto iterator_pos = [&](const PackageSpec& spec, size_t start) -> int { + auto it = std::find_if(install_plan.begin() + start, install_plan.end(), [&](auto& action) { + return action.spec == spec; + }); + Assert::IsTrue(it != install_plan.end()); + return (int)(it - install_plan.begin()); + }; + int a_64_1 = iterator_pos(spec_a_64.package_spec, 0), a_86_1 = iterator_pos(spec_a_86.package_spec, 0), + b_64 = iterator_pos(spec_b_64.package_spec, 0), b_86 = iterator_pos(spec_b_86.package_spec, 0), + c_64 = iterator_pos(spec_c_64.package_spec, 0), c_86 = iterator_pos(spec_c_86.package_spec, 0), + a_64_2 = iterator_pos(spec_a_64.package_spec, a_64_1 + 1), + a_86_2 = iterator_pos(spec_a_86.package_spec, a_86_1 + 1);*/ + + remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); + remove_plan_check(&install_plan[1], "a"); + features_check(&install_plan[2], "b", {"core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[3], "a", {"one", "core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[4], "c", {"core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[5], "b", {"core"}); + features_check(&install_plan[6], "a", {"one", "core"}); + features_check(&install_plan[7], "c", {"core"}); + } }; } \ No newline at end of file diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index 2a53cc8b4..dd9a40160 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -372,25 +372,27 @@ namespace UnitTest1 TEST_METHOD(package_spec_parse) { - vcpkg::ExpectedT spec = - vcpkg::PackageSpec::from_string("zlib", vcpkg::Triplet::X86_WINDOWS); + vcpkg::ExpectedT spec = + vcpkg::FullPackageSpec::from_string("zlib", vcpkg::Triplet::X86_WINDOWS); Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); - Assert::AreEqual("zlib", spec.get()->name().c_str()); - Assert::AreEqual(vcpkg::Triplet::X86_WINDOWS.canonical_name(), spec.get()->triplet().canonical_name()); + Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); + Assert::AreEqual(vcpkg::Triplet::X86_WINDOWS.canonical_name(), + spec.get()->package_spec.triplet().canonical_name()); } TEST_METHOD(package_spec_parse_with_arch) { - vcpkg::ExpectedT spec = - vcpkg::PackageSpec::from_string("zlib:x64-uwp", vcpkg::Triplet::X86_WINDOWS); + vcpkg::ExpectedT spec = + vcpkg::FullPackageSpec::from_string("zlib:x64-uwp", vcpkg::Triplet::X86_WINDOWS); Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); - Assert::AreEqual("zlib", spec.get()->name().c_str()); - Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), spec.get()->triplet().canonical_name()); + Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); + Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), + spec.get()->package_spec.triplet().canonical_name()); } TEST_METHOD(package_spec_parse_with_multiple_colon) { - auto ec = vcpkg::PackageSpec::from_string("zlib:x86-uwp:", vcpkg::Triplet::X86_WINDOWS).error(); + auto ec = vcpkg::FullPackageSpec::from_string("zlib:x86-uwp:", vcpkg::Triplet::X86_WINDOWS).error(); Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); } diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index c794b5ede..a0d690f37 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -102,6 +102,17 @@ namespace vcpkg::Build paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(bpgh)); } + static void create_binary_feature_control_file(const VcpkgPaths& paths, + const SourceParagraph& source_paragraph, + const FeatureParagraph& feature_paragraph, + const Triplet& triplet, + const BuildInfo& build_info) + { + BinaryParagraph bpgh = BinaryParagraph(source_paragraph, feature_paragraph, triplet); + const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL"; + paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(bpgh)); + } + ExtendedBuildResult build_package(const VcpkgPaths& paths, const BuildPackageConfig& config, const StatusParagraphs& status_db) @@ -135,17 +146,36 @@ namespace vcpkg::Build const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); + std::string features; + if (g_feature_packages) + { + if (config.feature_list) + { + for (auto&& feature : *config.feature_list) + { + features.append(feature + ";"); + } + if (features.size() > 0) + { + features.pop_back(); + } + } + } + const std::wstring cmd_launch_cmake = make_cmake_cmd( cmake_exe_path, ports_cmake_script_path, - {{L"CMD", L"BUILD"}, - {L"PORT", config.src.name}, - {L"CURRENT_PORT_DIR", config.port_dir / "/."}, - {L"TARGET_TRIPLET", triplet.canonical_name()}, - {L"VCPKG_PLATFORM_TOOLSET", toolset.version}, - {L"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? L"1" : L"0"}, - {L"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? L"1" : L"0"}, - {L"GIT", git_exe_path}}); + { + {L"CMD", L"BUILD"}, + {L"PORT", config.src.name}, + {L"CURRENT_PORT_DIR", config.port_dir / "/."}, + {L"TARGET_TRIPLET", triplet.canonical_name()}, + {L"VCPKG_PLATFORM_TOOLSET", toolset.version}, + {L"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? L"1" : L"0"}, + {L"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? L"1" : L"0"}, + {L"GIT", git_exe_path}, + {L"FEATURES", features}, + }); const std::wstring command = Strings::wformat(LR"(%s && %s)", cmd_set_environment, cmd_launch_cmake); @@ -170,7 +200,21 @@ namespace vcpkg::Build { return {BuildResult::POST_BUILD_CHECKS_FAILED, {}}; } - + if (g_feature_packages) + { + if (config.feature_list) + { + for (auto&& feature : *config.feature_list) + { + for (auto&& f_pgh : config.scf->feature_paragraphs) + { + if (f_pgh->name == feature) + create_binary_feature_control_file( + paths, *config.scf->core_paragraph, *f_pgh, triplet, build_info); + } + } + } + } create_binary_control_file(paths, config.src, triplet, build_info); // const fs::path port_buildtrees_dir = paths.buildtrees / spec.name; diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 90168813e..820e51b33 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -12,6 +12,8 @@ namespace vcpkg::Dependencies { + bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } + std::vector AnyParagraph::dependencies(const Triplet& triplet) const { auto to_package_specs = [&](const std::vector& dependencies_as_string) { @@ -337,8 +339,7 @@ namespace vcpkg::Dependencies return toposort; } - std::vector to_feature_specs(const std::vector depends, - const std::unordered_map str_to_spec) + std::vector to_feature_specs(const std::vector& depends, const Triplet& triplet) { std::vector f_specs; for (auto&& depend : depends) @@ -350,21 +351,16 @@ namespace vcpkg::Dependencies auto feature_name = depend.substr(start + 1, end - start - 1); auto package_name = depend.substr(0, start); - auto p_spec = str_to_spec.find(package_name); - if (p_spec != str_to_spec.end()) - { - auto feature_spec = FeatureSpec{p_spec->second, feature_name}; - f_specs.emplace_back(std::move(feature_spec)); - } + auto p_spec = PackageSpec::from_name_and_triplet(package_name, triplet).value_or_exit(VCPKG_LINE_INFO); + auto feature_spec = FeatureSpec{p_spec, feature_name}; + f_specs.emplace_back(std::move(feature_spec)); } else { - auto p_spec = str_to_spec.find(depend); - if (p_spec != str_to_spec.end()) - { - auto feature_spec = FeatureSpec{p_spec->second, ""}; - f_specs.emplace_back(std::move(feature_spec)); - } + auto p_spec = PackageSpec::from_name_and_triplet(depend, triplet).value_or_exit(VCPKG_LINE_INFO); + + auto feature_spec = FeatureSpec{p_spec, ""}; + f_specs.emplace_back(std::move(feature_spec)); } } return f_specs; @@ -405,7 +401,7 @@ namespace vcpkg::Dependencies mark_minus(cluster, pkg_to_cluster, graph_plan); } - graph_plan.install_graph.add_vertex(&cluster); + graph_plan.install_graph.add_vertex({&cluster}); auto& tracked = cluster.to_install_features; tracked.insert(updated_feature); if (tracked.find("core") == tracked.end() && tracked.find("") == tracked.end()) @@ -415,7 +411,7 @@ namespace vcpkg::Dependencies { auto& depend_cluster = pkg_to_cluster[depend.spec]; mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); - graph_plan.install_graph.add_edge(&cluster, &depend_cluster); + graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); } } @@ -424,7 +420,7 @@ namespace vcpkg::Dependencies auto& depend_cluster = pkg_to_cluster[depend.spec]; mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); if (&depend_cluster == &cluster) continue; - graph_plan.install_graph.add_edge(&cluster, &depend_cluster); + graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); } return true; } @@ -434,14 +430,14 @@ namespace vcpkg::Dependencies if (cluster.will_remove) return; cluster.will_remove = true; - graph_plan.remove_graph.add_vertex(&cluster); + graph_plan.remove_graph.add_vertex({&cluster}); for (auto&& pair : cluster.edges) { auto& remove_edges_edges = pair.second.remove_edges; for (auto&& depend : remove_edges_edges) { auto& depend_cluster = pkg_to_cluster[depend.spec]; - graph_plan.remove_graph.add_edge(&cluster, &depend_cluster); + graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); depend_cluster.transient_uninstalled = true; mark_minus(depend_cluster, pkg_to_cluster, graph_plan); } @@ -456,40 +452,37 @@ namespace vcpkg::Dependencies const std::vector& specs, const StatusParagraphs& status_db) { - const auto triplet = Triplet::X86_WINDOWS; std::unordered_map pkg_spec_to_package_node; - std::unordered_map str_to_spec; - - for (const auto& it : map) - { - str_to_spec.emplace(it.first.name(), it.first); - } for (const auto& it : map) { Cluster& node = pkg_spec_to_package_node[it.first]; + + node.spec = it.first; FeatureNodeEdges core_dependencies; - core_dependencies.build_edges = - to_feature_specs(filter_dependencies(it.second.core_paragraph->depends, triplet), str_to_spec); + auto core_depends = filter_dependencies(it.second.core_paragraph->depends, node.spec.triplet()); + core_dependencies.build_edges = to_feature_specs(core_depends, node.spec.triplet()); node.edges["core"] = std::move(core_dependencies); for (const auto& feature : it.second.feature_paragraphs) { FeatureNodeEdges added_edges; - added_edges.build_edges = to_feature_specs(filter_dependencies(feature->depends, triplet), str_to_spec); + auto depends = filter_dependencies(feature->depends, node.spec.triplet()); + added_edges.build_edges = to_feature_specs(depends, node.spec.triplet()); node.edges.emplace(feature->name, std::move(added_edges)); } - node.cluster_data.source_paragraph = &it.second; + node.source_control_file = &it.second; } - for (auto&& status_paragraph : status_db) + for (auto&& status_paragraph : get_installed_ports(status_db)) { auto& spec = status_paragraph->package.spec; auto& status_paragraph_feature = status_paragraph->package.feature; Cluster& cluster = pkg_spec_to_package_node[spec]; cluster.transient_uninstalled = false; - auto reverse_edges = to_feature_specs(status_paragraph->package.depends, str_to_spec); + auto reverse_edges = + to_feature_specs(status_paragraph->package.depends, status_paragraph->package.spec.triplet()); for (auto&& dependency : reverse_edges) { @@ -507,7 +500,7 @@ namespace vcpkg::Dependencies auto& target_node = pkg_node->second.edges[depends_name]; target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); } - cluster.cluster_data.status_paragraphs.emplace_back(*status_paragraph); + cluster.status_paragraphs.emplace_back(*status_paragraph); if (status_paragraph_feature == "") { cluster.original_features.insert("core"); @@ -528,35 +521,40 @@ namespace vcpkg::Dependencies } } - Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); + Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); auto remove_vertex_list = graph_plan.remove_graph.vertex_list(); auto remove_toposort = Graphs::topological_sort(remove_vertex_list, adjacency_remove_graph); - Graphs::GraphAdjacencyProvider adjacency_install_graph(graph_plan.install_graph.adjacency_list()); + Graphs::GraphAdjacencyProvider adjacency_install_graph(graph_plan.install_graph.adjacency_list()); auto insert_vertex_list = graph_plan.install_graph.vertex_list(); auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph); std::vector install_plan; - for (auto&& cluster : remove_toposort) + for (auto&& like_cluster : remove_toposort) { - auto scf = *cluster->cluster_data.source_paragraph.get(); + auto scf = *like_cluster.ptr->source_control_file.get(); AnyAction any_plan; any_plan.remove_plan = RemovePlanAction{ - str_to_spec[scf->core_paragraph->name], RemovePlanType::REMOVE, RequestType::AUTO_SELECTED}; + PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) + .value_or_exit(VCPKG_LINE_INFO), + RemovePlanType::REMOVE, + RequestType::AUTO_SELECTED}; install_plan.emplace_back(std::move(any_plan)); } - for (auto&& cluster : insert_toposort) + for (auto&& like_cluster : insert_toposort) { - if (!cluster->transient_uninstalled) continue; - - auto scf = *cluster->cluster_data.source_paragraph.get(); - auto& pkg_spec = str_to_spec[scf->core_paragraph->name]; - auto action = InstallPlanAction{ - pkg_spec, map.find(pkg_spec)->second, cluster->to_install_features, RequestType::AUTO_SELECTED}; + if (!like_cluster.ptr->transient_uninstalled) continue; + + auto scf = *like_cluster.ptr->source_control_file.get(); + auto pkg_spec = + PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) + .value_or_exit(VCPKG_LINE_INFO); + auto action = + InstallPlanAction{pkg_spec, *scf, like_cluster.ptr->to_install_features, RequestType::AUTO_SELECTED}; AnyAction any_plan; any_plan.install_plan = std::move(action); diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp index fdedd5507..f4e9a07c2 100644 --- a/toolsrc/src/vcpkg_Input.cpp +++ b/toolsrc/src/vcpkg_Input.cpp @@ -12,10 +12,10 @@ namespace vcpkg::Input CStringView example_text) { const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); - auto expected_spec = PackageSpec::from_string(as_lowercase, default_triplet); + auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet); if (auto spec = expected_spec.get()) { - return PackageSpec{*spec}; + return PackageSpec{spec->package_spec}; } // Intentionally show the lowercased string @@ -39,26 +39,11 @@ namespace vcpkg::Input const Triplet& default_triplet, CStringView example_text) { - int left_pos = (int)full_package_spec_as_string.find('['); - if (left_pos == std::string::npos) - { - return FullPackageSpec{ - check_and_get_package_spec(full_package_spec_as_string, default_triplet, example_text)}; - } - int right_pos = (int)full_package_spec_as_string.find(']'); - if (left_pos >= right_pos) - { - System::println(System::Color::error, "Error: Argument is not formatted correctly \"%s\""); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - std::string package_spec_as_string = full_package_spec_as_string.substr(0, left_pos); - const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); - auto expected_spec = PackageSpec::from_string(as_lowercase, default_triplet); - if (auto&& spec = expected_spec.get()) + const std::string as_lowercase = Strings::ascii_to_lowercase(full_package_spec_as_string); + auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet); + if (auto spec = expected_spec.get()) { - return {*spec, - parse_comma_list(full_package_spec_as_string.substr(left_pos + 1, right_pos - left_pos - 1))}; + return *spec; } // Intentionally show the lowercased string diff --git a/toolsrc/src/vcpkg_Parse.cpp b/toolsrc/src/vcpkg_Parse.cpp index b63ce41a9..659af2939 100644 --- a/toolsrc/src/vcpkg_Parse.cpp +++ b/toolsrc/src/vcpkg_Parse.cpp @@ -6,18 +6,6 @@ namespace vcpkg::Parse { - static Optional get_field(const std::unordered_map& fields, - const std::string& fieldname) - { - auto it = fields.find(fieldname); - if (it == fields.end()) - { - return nullopt; - } - - return it->second; - } - static Optional remove_field(std::unordered_map* fields, const std::string& fieldname) { -- cgit v1.2.3 From 5d86005aa7a25f192d6a3023423e2977bcef7367 Mon Sep 17 00:00:00 2001 From: Mikhail Paulyshka Date: Tue, 25 Jul 2017 04:07:08 +0300 Subject: cmake: update to 3.9 --- toolsrc/src/VcpkgPaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 9068e3903..bc1152b9d 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -98,10 +98,10 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path scripts_folder) { - static constexpr std::array expected_version = {3, 8, 0}; + static constexpr std::array expected_version = {3, 9, 0}; static const std::wstring version_check_arguments = L"--version"; - const fs::path downloaded_copy = downloads_folder / "cmake-3.8.0-win32-x86" / "bin" / "cmake.exe"; + const fs::path downloaded_copy = downloads_folder / "cmake-3.9.0-win32-x86" / "bin" / "cmake.exe"; const std::vector from_path = find_from_PATH(L"cmake"); std::vector candidate_paths; -- cgit v1.2.3 From 60296cf16189d4cb048482a1c4476a41d9b18918 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 26 Jul 2017 13:54:28 -0700 Subject: [vcpkg] Add support for single-option arguments. --- toolsrc/src/VcpkgCmdArguments.cpp | 69 ++++++++++++++++++++++++++++++++++----- toolsrc/src/tests_arguments.cpp | 23 +++++++++++++ 2 files changed, 83 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgCmdArguments.cpp b/toolsrc/src/VcpkgCmdArguments.cpp index 62e0b114c..ebf4c5fc5 100644 --- a/toolsrc/src/VcpkgCmdArguments.cpp +++ b/toolsrc/src/VcpkgCmdArguments.cpp @@ -123,7 +123,15 @@ namespace vcpkg continue; } - args.optional_command_arguments.insert(arg); + auto eq_pos = arg.find('='); + if (eq_pos != std::string::npos) + { + args.optional_command_arguments.emplace(arg.substr(0, eq_pos), arg.substr(eq_pos + 1)); + } + else + { + args.optional_command_arguments.emplace(arg, nullopt); + } continue; } @@ -140,30 +148,73 @@ namespace vcpkg return args; } - std::unordered_set VcpkgCmdArguments::check_and_get_optional_command_arguments( - const std::vector& valid_options) const + ParsedArguments VcpkgCmdArguments::check_and_get_optional_command_arguments( + const std::vector& valid_switches, const std::vector& valid_settings) const { - std::unordered_set output; + bool failed = false; + ParsedArguments output; + auto options_copy = this->optional_command_arguments; - for (const std::string& option : valid_options) + for (const std::string& option : valid_switches) { auto it = options_copy.find(option); if (it != options_copy.end()) { - output.insert(option); - options_copy.erase(it); + if (it->second.has_value()) + { + // Having a string value indicates it was passed like '--a=xyz' + System::println(System::Color::error, "The option '%s' does not accept an argument.", option); + failed = true; + } + else + { + output.switches.insert(option); + options_copy.erase(it); + } + } + } + + for (const std::string& option : valid_settings) + { + auto it = options_copy.find(option); + if (it != options_copy.end()) + { + if (!it->second.has_value()) + { + // Not having a string value indicates it was passed like '--a' + System::println(System::Color::error, "The option '%s' must be passed an argument.", option); + failed = true; + } + else + { + output.settings.emplace(option, it->second.value_or_exit(VCPKG_LINE_INFO)); + options_copy.erase(it); + } } } if (!options_copy.empty()) { System::println(System::Color::error, "Unknown option(s) for command '%s':", this->command); - for (const std::string& option : options_copy) + for (auto&& option : options_copy) + { + System::println(" %s", option.first); + } + System::println("\nValid options are:", this->command); + for (auto&& option : valid_switches) { - System::println(option); + System::println(" %s", option); } + for (auto&& option : valid_settings) + { + System::println(" %s=...", option); + } + System::println(" --triplet "); + System::println(" --vcpkg-root "); + Checks::exit_fail(VCPKG_LINE_INFO); } + if (failed) Checks::exit_fail(VCPKG_LINE_INFO); return output; } diff --git a/toolsrc/src/tests_arguments.cpp b/toolsrc/src/tests_arguments.cpp index 624fbb910..14b3c3d4f 100644 --- a/toolsrc/src/tests_arguments.cpp +++ b/toolsrc/src/tests_arguments.cpp @@ -31,5 +31,28 @@ namespace UnitTest1 Assert::IsTrue(v.sendmetrics && v.sendmetrics.get()); Assert::IsTrue(v.printmetrics && *v.printmetrics.get()); } + + TEST_METHOD(create_from_arg_sequence_valued_options) + { + std::vector t = {"--a=b", "command", "argument"}; + auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); + auto opts = v.check_and_get_optional_command_arguments({}, {"--a"}); + Assert::AreEqual("b", opts.settings["--a"].c_str()); + Assert::AreEqual(size_t{1}, v.command_arguments.size()); + Assert::AreEqual("argument", v.command_arguments[0].c_str()); + Assert::AreEqual("command", v.command.c_str()); + } + + TEST_METHOD(create_from_arg_sequence_valued_options2) + { + std::vector t = {"--a", "--b=c"}; + auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); + auto opts = v.check_and_get_optional_command_arguments({"--a", "--c"}, {"--b", "--d"}); + Assert::AreEqual("c", opts.settings["--b"].c_str()); + Assert::IsTrue(opts.settings.find("--d") == opts.settings.end()); + Assert::IsTrue(opts.switches.find("--a") != opts.switches.end()); + Assert::IsTrue(opts.settings.find("--c") == opts.settings.end()); + Assert::AreEqual(size_t{0}, v.command_arguments.size()); + } }; } \ No newline at end of file -- cgit v1.2.3 From 06597edfb7e47ff16c60c6dbbecf7883294d8ecb Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 26 Jul 2017 16:25:24 -0700 Subject: [vcpkg-export] Add NuGet id and NuGet version options to export command. --- toolsrc/src/commands_export.cpp | 49 +++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 12 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index cbb3a7733..5e1cc2052 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -110,11 +110,10 @@ namespace vcpkg::Commands::Export static fs::path do_nuget_export(const VcpkgPaths& paths, const std::string& nuget_id, + const std::string& nuget_version, const fs::path& raw_exported_dir, const fs::path& output_dir) { - static const std::string NUPKG_VERSION = "1.0.0"; - Files::Filesystem& fs = paths.get_filesystem(); const fs::path& nuget_exe = paths.get_nuget_exe(); @@ -129,7 +128,7 @@ namespace vcpkg::Commands::Export fs.write_contents(targets_redirect, targets_redirect_content); const std::string nuspec_file_content = - create_nuspec_file_contents(raw_exported_dir.string(), targets_redirect.string(), nuget_id, NUPKG_VERSION); + create_nuspec_file_contents(raw_exported_dir.string(), targets_redirect.string(), nuget_id, nuget_version); const fs::path nuspec_file_path = paths.buildsystems / "tmp" / "vcpkg.export.nuspec"; fs.write_contents(nuspec_file_path, nuspec_file_content); @@ -203,6 +202,16 @@ namespace vcpkg::Commands::Export return exported_archive_path; } + static Optional maybe_lookup(std::unordered_map const& m, + std::string const& key) + { + auto it = m.find(key); + if (it != m.end()) + return it->second; + else + return nullopt; + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { static const std::string OPTION_DRY_RUN = "--dry-run"; @@ -210,6 +219,8 @@ namespace vcpkg::Commands::Export static const std::string OPTION_NUGET = "--nuget"; static const std::string OPTION_ZIP = "--zip"; static const std::string OPTION_7ZIP = "--7zip"; + static const std::string OPTION_NUGET_ID = "--nuget-id"; + static const std::string OPTION_NUGET_VERSION = "--nuget-version"; // input sanitization static const std::string example = @@ -222,18 +233,30 @@ namespace vcpkg::Commands::Export for (auto&& spec : specs) Input::check_triplet(spec.triplet(), paths); - const std::unordered_set options = args.check_and_get_optional_command_arguments( - {OPTION_DRY_RUN, OPTION_RAW, OPTION_NUGET, OPTION_ZIP, OPTION_7ZIP}); - const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend(); - const bool raw = options.find(OPTION_RAW) != options.cend(); - const bool nuget = options.find(OPTION_NUGET) != options.cend(); - const bool zip = options.find(OPTION_ZIP) != options.cend(); - const bool _7zip = options.find(OPTION_7ZIP) != options.cend(); + const auto options = args.check_and_get_optional_command_arguments( + { + OPTION_DRY_RUN, OPTION_RAW, OPTION_NUGET, OPTION_ZIP, OPTION_7ZIP, + }, + { + OPTION_NUGET_ID, OPTION_NUGET_VERSION, + }); + const bool dryRun = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); + const bool raw = options.switches.find(OPTION_RAW) != options.switches.cend(); + const bool nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); + const bool zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); + const bool _7zip = options.switches.find(OPTION_7ZIP) != options.switches.cend(); Checks::check_exit(VCPKG_LINE_INFO, raw || nuget || zip || _7zip, "Must provide at least one of the following options: --raw --nuget --zip --7zip"); + auto maybe_nuget_id = maybe_lookup(options.settings, OPTION_NUGET_ID); + auto maybe_nuget_version = maybe_lookup(options.settings, OPTION_NUGET_VERSION); + + Checks::check_exit(VCPKG_LINE_INFO, !maybe_nuget_id || nuget, "--nuget-id is only valid with --nuget"); + Checks::check_exit( + VCPKG_LINE_INFO, !maybe_nuget_version || nuget, "--nuget-version is only valid with --nuget"); + // create the plan StatusParagraphs status_db = database_load_check(paths); std::vector export_plan = Dependencies::create_export_plan(paths, specs, status_db); @@ -352,8 +375,10 @@ namespace vcpkg::Commands::Export { System::println("Creating nuget package... "); - const std::string nuget_id = raw_exported_dir_path.filename().string(); - const fs::path output_path = do_nuget_export(paths, nuget_id, raw_exported_dir_path, export_to_path); + const std::string nuget_id = maybe_nuget_id.value_or(raw_exported_dir_path.filename().string()); + const std::string nuget_version = maybe_nuget_version.value_or("1.0.0"); + const fs::path output_path = + do_nuget_export(paths, nuget_id, nuget_version, raw_exported_dir_path, export_to_path); System::println(System::Color::success, "Creating nuget package... done"); System::println(System::Color::success, "NuGet package exported at: %s", output_path.generic_string()); -- cgit v1.2.3 From 800af576df9c632053f1e71f8c16a1c3d37caec2 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 26 Jul 2017 16:46:22 -0700 Subject: [vcpkg-help] Improve help, including a list of topics. --- toolsrc/src/commands_help.cpp | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_help.cpp b/toolsrc/src/commands_help.cpp index e4be11a77..a12f9003d 100644 --- a/toolsrc/src/commands_help.cpp +++ b/toolsrc/src/commands_help.cpp @@ -5,6 +5,14 @@ namespace vcpkg::Commands::Help { + void help_topics() + { + System::println("Available help topics:\n" + " triplet\n" + " integrate\n" + " export"); + } + void help_topic_valid_triplet(const VcpkgPaths& paths) { System::println("Available architecture triplets:"); @@ -14,6 +22,21 @@ namespace vcpkg::Commands::Help } } + void help_topic_export() + { + System::println("Summary:\n" + " vcpkg export [options] ...\n" + "\n" + "Options:\n" + " --7zip Export to a 7zip (.7z) file\n" + " --dry-run Do not actually export\n" + " --nuget Export a NuGet package\n" + " --nuget-id= Specify the id for the exported NuGet package\n" + " --nuget-version= Specify the version for the exported NuGet package\n" + " --raw Export to an uncompressed directory\n" + " --zip Export to a zip file"); + } + void print_usage() { System::println( @@ -25,6 +48,8 @@ namespace vcpkg::Commands::Help " vcpkg list List installed packages\n" " vcpkg update Display list of packages for updating\n" " vcpkg hash [alg] Hash a file by specific algorithm, default SHA512\n" + " vcpkg help topics Display the list of help topics\n" + " vcpkg help Display help for a specific topic\n" "\n" "%s" // Integration help "\n" @@ -77,14 +102,28 @@ namespace vcpkg::Commands::Help Checks::exit_success(VCPKG_LINE_INFO); } const auto& topic = args.command_arguments[0]; - if (topic == "triplet") + if (topic == "triplet" || topic == "triplets" || topic == "triple") { help_topic_valid_triplet(paths); } + else if (topic == "export") + { + help_topic_export(); + } + else if (topic == "integrate") + { + System::print("Commands:\n" + "%s", + Integrate::INTEGRATE_COMMAND_HELPSTRING); + } + else if (topic == "topics") + { + help_topics(); + } else { System::println(System::Color::error, "Error: unknown topic %s", topic); - print_usage(); + help_topics(); Checks::exit_fail(VCPKG_LINE_INFO); } Checks::exit_success(VCPKG_LINE_INFO); -- cgit v1.2.3 From 17b6d75d0d16d8b620e6680c0364208aa8a52651 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 26 Jul 2017 16:51:28 -0700 Subject: [vcpkg-export] Tweak error formatting --- toolsrc/src/commands_export.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index 5e1cc2052..4adfbc0f6 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -246,9 +246,12 @@ namespace vcpkg::Commands::Export const bool zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); const bool _7zip = options.switches.find(OPTION_7ZIP) != options.switches.cend(); - Checks::check_exit(VCPKG_LINE_INFO, - raw || nuget || zip || _7zip, - "Must provide at least one of the following options: --raw --nuget --zip --7zip"); + if (!raw && !nuget && !zip && !_7zip && !dryRun) + { + System::println(System::Color::error, "Must provide at least one export type: --raw --nuget --zip --7zip"); + System::print(example); + Checks::exit_fail(VCPKG_LINE_INFO); + } auto maybe_nuget_id = maybe_lookup(options.settings, OPTION_NUGET_ID); auto maybe_nuget_version = maybe_lookup(options.settings, OPTION_NUGET_VERSION); -- cgit v1.2.3 From 957cb214e92f45069f142d8b6ccf2a6425df9c51 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Tue, 1 Aug 2017 15:17:42 -0700 Subject: change qualifier bracket to parens --- toolsrc/src/SourceParagraph.cpp | 2 +- toolsrc/src/tests_dependencies.cpp | 4 ++-- toolsrc/src/tests_paragraph.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 9289edb38..cb7aeb33e 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -160,7 +160,7 @@ namespace vcpkg // expect of the form "\w+ \[\w+\]" Dependency dep; dep.name = depend_string.substr(0, pos); - if (depend_string.c_str()[pos + 1] != '[' || depend_string[depend_string.size() - 1] != ']') + if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')') { // Error, but for now just slurp the entire string. return {depend_string, ""}; diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp index 995d46873..7a49bdbd0 100644 --- a/toolsrc/src/tests_dependencies.cpp +++ b/toolsrc/src/tests_dependencies.cpp @@ -15,7 +15,7 @@ namespace UnitTest1 { TEST_METHOD(parse_depends_one) { - auto v = expand_qualified_dependencies(parse_comma_list("libA [windows]")); + auto v = expand_qualified_dependencies(parse_comma_list("libA (windows)")); Assert::AreEqual(size_t(1), v.size()); Assert::AreEqual("libA", v[0].name.c_str()); Assert::AreEqual("windows", v[0].qualifier.c_str()); @@ -23,7 +23,7 @@ namespace UnitTest1 TEST_METHOD(filter_depends) { - auto deps = expand_qualified_dependencies(parse_comma_list("libA [windows], libB, libC [uwp]")); + auto deps = expand_qualified_dependencies(parse_comma_list("libA (windows), libB, libC (uwp)")); auto v = filter_dependencies(deps, Triplet::X64_WINDOWS); Assert::AreEqual(size_t(2), v.size()); Assert::AreEqual("libA", v[0].c_str()); diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index dd9a40160..920e58c02 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -112,7 +112,7 @@ namespace UnitTest1 { auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA [windows], libB [uwp]"}, + {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA (windows), libB (uwp)"}, }}); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); -- cgit v1.2.3 From cebc7acf025e888f70e84f56941d267b2fbda70a Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 7 Aug 2017 12:26:30 -0700 Subject: Updated version of nuget to 4.1.0 --- toolsrc/src/VcpkgPaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index bc1152b9d..f3501e162 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -122,10 +122,10 @@ namespace vcpkg fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path scripts_folder) { - static constexpr std::array expected_version = {3, 3, 0}; + static constexpr std::array expected_version = {4, 1, 0}; static const std::wstring version_check_arguments = L""; - const fs::path downloaded_copy = downloads_folder / "nuget-3.5.0" / "nuget.exe"; + const fs::path downloaded_copy = downloads_folder / "nuget-4.1.0" / "nuget.exe"; const std::vector from_path = find_from_PATH(L"nuget"); std::vector candidate_paths; -- cgit v1.2.3 From d5659ea88d6bfa656f82d22f2cd186fe2ebb3b27 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 8 Aug 2017 14:00:03 -0700 Subject: [vcpkg] Improve error messages during Binary Paragraph parsing --- toolsrc/src/BinaryParagraph.cpp | 4 +++- toolsrc/src/SourceParagraph.cpp | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index b6f3e8a87..49e9d58e5 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -56,8 +56,10 @@ namespace vcpkg this->default_features = parse_comma_list(parser.optional_field(Fields::DEFAULTFEATURES)); } - if (auto err = parser.error_info(this->spec.name())) + if (auto err = parser.error_info(this->spec.to_string())) { + System::println( + System::Color::error, "Error: while parsing the Binary Paragraph for %s", this->spec.to_string()); print_error_message(err); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 9289edb38..a34167db7 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -54,7 +54,7 @@ namespace vcpkg if (!error_info->extra_fields.empty()) { System::println(System::Color::error, - "Error: There are invalid fields in the Source Paragraph of %s", + "Error: There are invalid fields in the control file of %s", error_info->name); System::println("The following fields were not expected:\n\n %s\n", Strings::join("\n ", error_info->extra_fields)); @@ -74,7 +74,7 @@ namespace vcpkg if (!error_info->missing_fields.empty()) { System::println(System::Color::error, - "Error: There are missing fields in the Source Paragraphs of %s", + "Error: There are missing fields in the control file of %s", error_info->name); System::println("The following fields were missing:\n\n %s\n", Strings::join("\n ", error_info->missing_fields)); -- cgit v1.2.3 From 052b34d4c5df0ade113514552621798ad0e32173 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 9 Aug 2017 13:16:09 -0700 Subject: Add text filtering in `vcpkg depend-info` --- toolsrc/src/commands_depends.cpp | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index ccfe58e4e..2d1fb658b 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -4,16 +4,44 @@ #include "vcpkg_Commands.h" #include "vcpkg_Strings.h" #include "vcpkg_System.h" +#include "vcpkg_Util.h" namespace vcpkg::Commands::DependInfo { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Commands::Help::create_example_string(R"###(depend-info)###"); - args.check_exact_arg_count(0, example); + static const std::string example = Commands::Help::create_example_string(R"###(depend-info [pat])###"); + args.check_max_arg_count(1, example); args.check_and_get_optional_command_arguments({}); - const auto source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + std::vector> source_control_files = + Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + + if (args.command_arguments.size() == 1) + { + const std::string filter = args.command_arguments.at(0); + + Util::erase_remove_if(source_control_files, + [&](const std::unique_ptr& source_control_file) { + + const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; + + if (Strings::case_insensitive_ascii_contains(source_paragraph.name, filter)) + { + return false; + } + + for (const Dependency& dependency : source_paragraph.depends) + { + if (Strings::case_insensitive_ascii_contains(dependency.name, filter)) + { + return false; + } + } + + return true; + }); + } for (auto&& source_control_file : source_control_files) { -- cgit v1.2.3 From 6e5ec2ff08ebb2b1e746a7f950562c50d94b01c5 Mon Sep 17 00:00:00 2001 From: atkawa7 Date: Fri, 11 Aug 2017 09:10:37 -0700 Subject: [cmake] Fix cmake path --- toolsrc/src/VcpkgPaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index f3501e162..38b11584a 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -98,10 +98,10 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path scripts_folder) { - static constexpr std::array expected_version = {3, 9, 0}; + static constexpr std::array expected_version = {3, 9, 1}; static const std::wstring version_check_arguments = L"--version"; - const fs::path downloaded_copy = downloads_folder / "cmake-3.9.0-win32-x86" / "bin" / "cmake.exe"; + const fs::path downloaded_copy = downloads_folder / "cmake-3.9.1-win32-x86" / "bin" / "cmake.exe"; const std::vector from_path = find_from_PATH(L"cmake"); std::vector candidate_paths; -- cgit v1.2.3 From 8a0a99b62a61b8efffd8a5e375900c4b572f5d3f Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 11 Aug 2017 15:40:06 -0700 Subject: Update required/downloaded git to 2.14.1 --- toolsrc/src/VcpkgPaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 38b11584a..f3513a3f3 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -143,10 +143,10 @@ namespace vcpkg fs::path get_git_path(const fs::path& downloads_folder, const fs::path scripts_folder) { - static constexpr std::array expected_version = {2, 0, 0}; + static constexpr std::array expected_version = {2, 14, 1}; static const std::wstring version_check_arguments = L"--version"; - const fs::path downloaded_copy = downloads_folder / "MinGit-2.11.1-32-bit" / "cmd" / "git.exe"; + const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.1-32-bit" / "cmd" / "git.exe"; const std::vector from_path = find_from_PATH(L"git"); std::vector candidate_paths; -- cgit v1.2.3 From 3a0ae04ee662fe2819bc7aa1e7686671d2acf4d4 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 11 Aug 2017 16:09:45 -0700 Subject: Print more info when fetchDependency fails --- toolsrc/src/VcpkgPaths.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index f3513a3f3..91f5ddb0e 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -72,14 +72,21 @@ namespace vcpkg static fs::path fetch_dependency(const fs::path scripts_folder, const std::wstring& tool_name, - const fs::path& expected_downloaded_path) + const fs::path& expected_downloaded_path, + const std::array& version) { const fs::path script = scripts_folder / "fetchDependency.ps1"; auto install_cmd = System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name)); System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd); if (rc.exit_code) { - System::println(System::Color::error, "Launching powershell failed or was denied"); + const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); + + System::println(System::Color::error, + "Launching powershell failed or was denied when trying to fetch %s version %s.\n" + "(No sufficient installed version was found)", + Strings::to_utf8(tool_name), + version_as_string); Metrics::track_property("error", "powershell install failed"); Metrics::track_property("installcmd", install_cmd); Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); @@ -117,7 +124,7 @@ namespace vcpkg return *p; } - return fetch_dependency(scripts_folder, L"cmake", downloaded_copy); + return fetch_dependency(scripts_folder, L"cmake", downloaded_copy, expected_version); } fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path scripts_folder) @@ -138,7 +145,7 @@ namespace vcpkg return *p; } - return fetch_dependency(scripts_folder, L"nuget", downloaded_copy); + return fetch_dependency(scripts_folder, L"nuget", downloaded_copy, expected_version); } fs::path get_git_path(const fs::path& downloads_folder, const fs::path scripts_folder) @@ -162,7 +169,7 @@ namespace vcpkg return *p; } - return fetch_dependency(scripts_folder, L"git", downloaded_copy); + return fetch_dependency(scripts_folder, L"git", downloaded_copy, expected_version); } Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir) -- cgit v1.2.3 From 011368ef9e1754715873eb0a298f0d069210ea6c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 11 Aug 2017 16:11:00 -0700 Subject: Take path by const& --- toolsrc/src/VcpkgPaths.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 91f5ddb0e..60204bcdd 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -70,7 +70,7 @@ namespace vcpkg return Util::fmap(Strings::split(out.output, "\n"), [](auto&& s) { return fs::path(s); }); } - static fs::path fetch_dependency(const fs::path scripts_folder, + static fs::path fetch_dependency(const fs::path& scripts_folder, const std::wstring& tool_name, const fs::path& expected_downloaded_path, const std::array& version) @@ -103,7 +103,7 @@ namespace vcpkg return actual_downloaded_path; } - static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path scripts_folder) + static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { static constexpr std::array expected_version = {3, 9, 1}; static const std::wstring version_check_arguments = L"--version"; @@ -127,7 +127,7 @@ namespace vcpkg return fetch_dependency(scripts_folder, L"cmake", downloaded_copy, expected_version); } - fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path scripts_folder) + fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { static constexpr std::array expected_version = {4, 1, 0}; static const std::wstring version_check_arguments = L""; @@ -148,7 +148,7 @@ namespace vcpkg return fetch_dependency(scripts_folder, L"nuget", downloaded_copy, expected_version); } - fs::path get_git_path(const fs::path& downloads_folder, const fs::path scripts_folder) + fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { static constexpr std::array expected_version = {2, 14, 1}; static const std::wstring version_check_arguments = L"--version"; -- cgit v1.2.3 From 561e1dd69b8f53c1a87f2e68ff347b4a60c950e1 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 15 Aug 2017 13:58:04 -0700 Subject: [vcpkg-tests] Reformat --- toolsrc/src/tests_paragraph.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index 920e58c02..af4b55498 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -27,7 +27,8 @@ namespace UnitTest1 { auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "zlib"}, {"Version", "1.2.8"}, + {"Source", "zlib"}, + {"Version", "1.2.8"}, }}); Assert::IsTrue(m_pgh.has_value()); @@ -68,7 +69,9 @@ namespace UnitTest1 { auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl"}, + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Build-Depends", "z, openssl"}, }}); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); @@ -82,7 +85,9 @@ namespace UnitTest1 { auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl, xyz"}, + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Build-Depends", "z, openssl, xyz"}, }}); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); @@ -97,7 +102,9 @@ namespace UnitTest1 { auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "zlib"}, {"Version", "1.2.8"}, {"Supports", "x64, windows, uwp"}, + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Supports", "x64, windows, uwp"}, }}); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); @@ -112,7 +119,9 @@ namespace UnitTest1 { auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA (windows), libB (uwp)"}, + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Build-Depends", "libA (windows), libB (uwp)"}, }}); Assert::IsTrue(m_pgh.has_value()); auto& pgh = *m_pgh.get(); @@ -131,7 +140,10 @@ namespace UnitTest1 TEST_METHOD(BinaryParagraph_Construct_Minimum) { vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, {"Version", "1.2.8"}, {"Architecture", "x86-windows"}, {"Multi-Arch", "same"}, + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, }); Assert::AreEqual("zlib", pgh.spec.name().c_str()); @@ -320,7 +332,10 @@ namespace UnitTest1 TEST_METHOD(BinaryParagraph_serialize_min) { vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, {"Version", "1.2.8"}, {"Architecture", "x86-windows"}, {"Multi-Arch", "same"}, + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, }); std::string ss = Strings::serialize(pgh); auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); -- cgit v1.2.3 From 307b761df4197bf9cf1b69652808530e6219a868 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Tue, 25 Jul 2017 21:29:31 -0700 Subject: partial end to end feature packages hdf5 added vcpkg feature package support to other commands remove comments change qualifier bracket to parens added features to qualified dependencies --- toolsrc/src/BinaryParagraph.cpp | 12 ++- toolsrc/src/Paragraphs.cpp | 16 ++- toolsrc/src/SourceParagraph.cpp | 57 ++++++++++- toolsrc/src/StatusParagraphs.cpp | 26 ++++- toolsrc/src/commands_depends.cpp | 2 +- toolsrc/src/commands_install.cpp | 200 ++++++++++++++++++++++++++++++++----- toolsrc/src/commands_remove.cpp | 27 +++-- toolsrc/src/commands_search.cpp | 2 +- toolsrc/src/test_install_plan.cpp | 50 +++++++++- toolsrc/src/tests_dependencies.cpp | 2 +- toolsrc/src/tests_paragraph.cpp | 28 ++++-- toolsrc/src/vcpkg_Build.cpp | 46 +++++---- toolsrc/src/vcpkg_Dependencies.cpp | 52 +++++++--- toolsrc/src/vcpkglib.cpp | 2 +- 14 files changed, 431 insertions(+), 91 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index 49e9d58e5..9abd388b9 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -87,7 +87,17 @@ namespace vcpkg this->depends = filter_dependencies(fpgh.depends, triplet); } - std::string BinaryParagraph::displayname() const { return this->spec.to_string(); } + std::string BinaryParagraph::displayname() const + { + if (this->feature == "") + { + return this->spec.name() + "[core]:" + this->spec.triplet().to_string(); + } + else + { + return this->spec.name() + "[" + this->feature + "]:" + this->spec.triplet().to_string(); + } + } std::string BinaryParagraph::dir() const { return this->spec.dir(); } diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index 3749e919e..3a30f66a3 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -3,6 +3,7 @@ #include "ParagraphParseResult.h" #include "Paragraphs.h" #include "vcpkg_Files.h" +#include "vcpkg_Util.h" using namespace vcpkg::Parse; @@ -226,14 +227,21 @@ namespace vcpkg::Paragraphs return error_info; } - Expected try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec) + Expected try_load_cached_control_package(const VcpkgPaths& paths, const PackageSpec& spec) { - Expected> pghs = - get_single_paragraph(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL"); + Expected>> pghs = + get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL"); if (auto p = pghs.get()) { - return BinaryParagraph(*p); + BinaryControlFile bcf; + bcf.core_paragraph = BinaryParagraph(p->front()); + p->erase(p->begin()); + + bcf.features = + Util::fmap(*p, [&](auto&& raw_feature) -> BinaryParagraph { return BinaryParagraph(raw_feature); }); + + return bcf; } return pghs.error(); diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index a37567f3a..2aab7c572 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -152,18 +152,61 @@ namespace vcpkg return std::move(control_file); } + Features parse_feature_list(const std::string& name) + { + Features f; + int end = (int)name.find(']'); + if (end != std::string::npos) + { + int start = (int)name.find('['); + + auto feature_name_list = name.substr(start + 1, end - start - 1); + f.name = name.substr(0, start); + f.features = parse_comma_list(feature_name_list); + } + else + { + f.name = name; + } + return f; + } + + Dependency Dependency::parse_dependency(std::string name, std::string qualifier) + { + Dependency dep; + dep.qualifier = qualifier; + dep.depend = parse_feature_list(name); + return dep; + } + + std::string Dependency::name() const + { + std::string str = this->depend.name; + if (this->depend.features.empty()) return str; + + str += "["; + for (auto&& s : this->depend.features) + { + str += s + ","; + } + str.pop_back(); + str += "]"; + return str; + } + std::vector vcpkg::expand_qualified_dependencies(const std::vector& depends) { return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency { auto pos = depend_string.find(' '); - if (pos == std::string::npos) return {depend_string, ""}; + if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, ""); // expect of the form "\w+ \[\w+\]" Dependency dep; - dep.name = depend_string.substr(0, pos); + + dep.depend.name = depend_string.substr(0, pos); if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')') { // Error, but for now just slurp the entire string. - return {depend_string, ""}; + return Dependency::parse_dependency(depend_string, ""); } dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3); return dep; @@ -210,13 +253,17 @@ namespace vcpkg { if (dep.qualifier.empty() || t.canonical_name().find(dep.qualifier) != std::string::npos) { - ret.push_back(dep.name); + ret.emplace_back(dep.name()); } } return ret; } - const std::string& to_string(const Dependency& dep) { return dep.name; } + const std::string to_string(const Dependency& dep) + { + std::string name = dep.name(); + return name; + } ExpectedT> Supports::parse(const std::vector& strs) { diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp index 27f3c30a2..02ee61f75 100644 --- a/toolsrc/src/StatusParagraphs.cpp +++ b/toolsrc/src/StatusParagraphs.cpp @@ -27,6 +27,30 @@ namespace vcpkg }); } + std::vector*> StatusParagraphs::find_all(const std::string& name, + const Triplet& triplet) + { + std::vector*> spghs; + for (auto&& p : *this) + { + if (p->package.spec.name() == name && p->package.spec.triplet() == triplet) + { + spghs.emplace_back(&p); + } + } + return spghs; + } + + StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, + const Triplet& triplet, + const std::string& feature) + { + return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { + const PackageSpec& spec = pgh->package.spec; + return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature; + }); + } + StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name, const Triplet& triplet) const { @@ -43,7 +67,7 @@ namespace vcpkg { Checks::check_exit(VCPKG_LINE_INFO, pgh != nullptr, "Inserted null paragraph"); const PackageSpec& spec = pgh->package.spec; - auto ptr = find(spec.name(), spec.triplet()); + auto ptr = find(spec.name(), spec.triplet(), pgh->package.feature); if (ptr == end()) { paragraphs.push_back(std::move(pgh)); diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index 2d1fb658b..b04af5282 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -46,7 +46,7 @@ namespace vcpkg::Commands::DependInfo for (auto&& source_control_file : source_control_files) { const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; - auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name; }); + auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name(); }); System::println("%s: %s", source_paragraph.name, s); } diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 2ce5b6c62..2965d9025 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -211,10 +211,10 @@ namespace vcpkg::Commands::Install } } - void install_package(const VcpkgPaths& paths, const BinaryParagraph& binary_paragraph, StatusParagraphs* status_db) + void install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db) { - const fs::path package_dir = paths.package_dir(binary_paragraph.spec); - const Triplet& triplet = binary_paragraph.spec.triplet(); + const fs::path package_dir = paths.package_dir(bcf.core_paragraph.spec); + const Triplet& triplet = bcf.core_paragraph.spec.triplet(); const std::vector pgh_and_files = get_installed_files(paths, *status_db); const SortedVector package_files = @@ -234,7 +234,7 @@ namespace vcpkg::Commands::Install System::println(System::Color::error, "The following files are already installed in %s and are in conflict with %s", triplet_install_path.generic_string(), - binary_paragraph.spec); + bcf.core_paragraph.spec); System::print("\n "); System::println(Strings::join("\n ", intersection)); System::println(""); @@ -242,27 +242,42 @@ namespace vcpkg::Commands::Install } StatusParagraph source_paragraph; - source_paragraph.package = binary_paragraph; + source_paragraph.package = bcf.core_paragraph; source_paragraph.want = Want::INSTALL; source_paragraph.state = InstallState::HALF_INSTALLED; - for (auto&& dep : source_paragraph.package.depends) - { - if (status_db->find_installed(dep, source_paragraph.package.spec.triplet()) == status_db->end()) - { - Checks::unreachable(VCPKG_LINE_INFO); - } - } + write_update(paths, source_paragraph); status_db->insert(std::make_unique(source_paragraph)); + std::vector features_spghs; + for (auto&& feature : bcf.features) + { + features_spghs.emplace_back(); + + StatusParagraph& feature_paragraph = features_spghs.back(); + feature_paragraph.package = feature; + feature_paragraph.want = Want::INSTALL; + feature_paragraph.state = InstallState::HALF_INSTALLED; + + write_update(paths, feature_paragraph); + status_db->insert(std::make_unique(feature_paragraph)); + } + const InstallDir install_dir = InstallDir::from_destination_root( - paths.installed, triplet.to_string(), paths.listfile_path(binary_paragraph)); + paths.installed, triplet.to_string(), paths.listfile_path(bcf.core_paragraph)); install_files_and_write_listfile(paths.get_filesystem(), package_dir, install_dir); source_paragraph.state = InstallState::INSTALLED; write_update(paths, source_paragraph); status_db->insert(std::make_unique(source_paragraph)); + + for (auto&& feature_paragraph : features_spghs) + { + feature_paragraph.state = InstallState::INSTALLED; + write_update(paths, feature_paragraph); + status_db->insert(std::make_unique(feature_paragraph)); + } } using Build::BuildResult; @@ -312,8 +327,8 @@ namespace vcpkg::Commands::Install } System::println("Building package %s... done", display_name); - const BinaryParagraph bpgh = - Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); + const BinaryControlFile bpgh = + Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); System::println("Installing package %s... ", display_name); install_package(paths, bpgh, &status_db); System::println(System::Color::success, "Installing package %s... done", display_name); @@ -322,10 +337,11 @@ namespace vcpkg::Commands::Install if (plan_type == InstallPlanType::BUILD_AND_INSTALL && g_feature_packages) { + const std::string display_name_feature = action.displayname(); if (use_head_version) - System::println("Building package %s from HEAD... ", display_name); + System::println("Building package %s from HEAD... ", display_name_feature); else - System::println("Building package %s... ", display_name); + System::println("Building package %s... ", display_name_feature); const Build::BuildPackageConfig build_config{ *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), @@ -339,13 +355,13 @@ namespace vcpkg::Commands::Install System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); return result.code; } - System::println("Building package %s... done", display_name); + System::println("Building package %s... done", display_name_feature); - const BinaryParagraph bpgh = - Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); - System::println("Installing package %s... ", display_name); - install_package(paths, bpgh, &status_db); - System::println(System::Color::success, "Installing package %s... done", display_name); + const BinaryControlFile bcf = + Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); + System::println("Installing package %s... ", display_name_feature); + install_package(paths, bcf, &status_db); + System::println(System::Color::success, "Installing package %s... done", display_name_feature); return BuildResult::SUCCEEDED; } @@ -357,7 +373,9 @@ namespace vcpkg::Commands::Install System::Color::warning, "Package %s is already built -- not building from HEAD", display_name); } System::println("Installing package %s... ", display_name); - install_package(paths, action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO), &status_db); + install_package(paths, + BinaryControlFile{action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO)}, + &status_db); System::println(System::Color::success, "Installing package %s... done", display_name); return BuildResult::SUCCEEDED; } @@ -365,11 +383,27 @@ namespace vcpkg::Commands::Install Checks::unreachable(VCPKG_LINE_INFO); } + static void print_plan(const std::vector rebuilt_plans, + const std::vector new_plans) + { + const std::string rebuilt_string = Strings::join("\n", rebuilt_plans, [](const InstallPlanAction* p) { + return Dependencies::to_output_string(p->request_type, p->displayname()); + }); + + const std::string new_string = Strings::join("\n", new_plans, [](const InstallPlanAction* p) { + return Dependencies::to_output_string(p->request_type, p->displayname()); + }); + + if (rebuilt_plans.size() > 0) System::println("The following packages will be rebuilt:\n%s", rebuilt_string); + if (new_plans.size() > 0) System::println("The following packages will be installed:\n%s", new_string); + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_USE_HEAD_VERSION = "--head"; static const std::string OPTION_NO_DOWNLOADS = "--no-downloads"; + static const std::string OPTION_RECURSE = "--recurse"; // input sanitization static const std::string example = @@ -383,14 +417,130 @@ namespace vcpkg::Commands::Install Input::check_triplet(spec.triplet(), paths); const std::unordered_set options = args.check_and_get_optional_command_arguments( - {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS}); + {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE}); const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend(); const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend(); const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); + const bool isRecursive = options.find(OPTION_RECURSE) != options.cend(); // create the plan StatusParagraphs status_db = database_load_check(paths); + if (g_feature_packages) + { + const std::vector full_specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + return Input::check_and_get_full_package_spec(arg, default_triplet, example); + }); + + std::unordered_map scf_map; + auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + for (auto&& port : all_ports.paragraphs) + { + auto pkg_spec = PackageSpec::from_name_and_triplet(port->core_paragraph->name, default_triplet) + .value_or_exit(VCPKG_LINE_INFO); + scf_map[pkg_spec] = std::move(*port); + } + std::vector action_plan = + Dependencies::create_feature_install_plan(scf_map, full_specs, status_db); + // install plan will be empty if it is already installed - need to change this at status paragraph part + Checks::check_exit( + VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty for feature packages"); + + const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), + Build::to_allow_downloads(!no_downloads)}; + + std::vector remove_plans; + + std::vector rebuilt_plans; + std::vector new_plans; + + // removal will happen before install + for (auto&& action : action_plan) + { + if (auto install_action = action.install_plan.get()) + { + auto it = Util::find_if( + remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); + if (it != remove_plans.end()) + { + rebuilt_plans.emplace_back(install_action); + } + else + { + new_plans.emplace_back(install_action); + } + } + else if (auto remove_action = action.remove_plan.get()) + { + remove_plans.emplace_back(remove_action); + } + } + + print_plan(rebuilt_plans, new_plans); + + if (remove_plans.size() > 0 && !isRecursive) + { + System::println(System::Color::warning, + "If you are sure you want to rebuild the above packages, run the command with the " + "--recurse option"); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + // execute the plan + for (const Dependencies::AnyAction& any_action : action_plan) + { + if (auto install_action = any_action.install_plan.get()) + { + const BuildResult result = + perform_install_plan_action(paths, *install_action, install_plan_options, status_db); + if (result != BuildResult::SUCCEEDED) + { + System::println(Build::create_user_troubleshooting_message(install_action->spec)); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } + else if (auto remove_action = any_action.remove_plan.get()) + { + static const std::string OPTION_PURGE = "--purge"; + static const std::string OPTION_NO_PURGE = "--no-purge"; + + const bool alsoRemoveFolderFromPackages = options.find(OPTION_NO_PURGE) == options.end(); + if (options.find(OPTION_PURGE) != options.end() && !alsoRemoveFolderFromPackages) + { + // User specified --purge and --no-purge + System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); + System::print(example); + Checks::exit_fail(VCPKG_LINE_INFO); + } + const std::string display_name = remove_action->spec.to_string(); + switch (remove_action->plan_type) + { + case RemovePlanType::NOT_INSTALLED: + System::println(System::Color::success, "Package %s is not installed", display_name); + break; + case RemovePlanType::REMOVE: + System::println("Removing package %s... ", display_name); + Commands::Remove::remove_package(paths, remove_action->spec, &status_db); + System::println(System::Color::success, "Removing package %s... done", display_name); + break; + case RemovePlanType::UNKNOWN: + default: Checks::unreachable(VCPKG_LINE_INFO); + } + + if (alsoRemoveFolderFromPackages) + { + System::println("Purging package %s... ", display_name); + Files::Filesystem& fs = paths.get_filesystem(); + std::error_code ec; + fs.remove_all(paths.packages / remove_action->spec.dir(), ec); + System::println(System::Color::success, "Purging package %s... done", display_name); + } + } + } + + Checks::exit_success(VCPKG_LINE_INFO); + } + Dependencies::PathsPortFile paths_port_file(paths); std::vector install_plan = Dependencies::create_install_plan(paths_port_file, specs, status_db); diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index eabf2b9ae..e480f02dd 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -17,13 +17,19 @@ namespace vcpkg::Commands::Remove void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db) { auto& fs = paths.get_filesystem(); - StatusParagraph& pkg = **status_db->find(spec.name(), spec.triplet()); + auto spghs = status_db->find_all(spec.name(), spec.triplet()); + auto core_pkg = **status_db->find(spec.name(), spec.triplet(), ""); - pkg.want = Want::PURGE; - pkg.state = InstallState::HALF_INSTALLED; - write_update(paths, pkg); + for (auto&& spgh : spghs) + { + StatusParagraph& pkg = **spgh; + if (pkg.state != InstallState::INSTALLED) continue; + pkg.want = Want::PURGE; + pkg.state = InstallState::HALF_INSTALLED; + write_update(paths, pkg); + } - auto maybe_lines = fs.read_lines(paths.listfile_path(pkg.package)); + auto maybe_lines = fs.read_lines(paths.listfile_path(core_pkg.package)); if (auto lines = maybe_lines.get()) { @@ -80,11 +86,16 @@ namespace vcpkg::Commands::Remove } } - fs.remove(paths.listfile_path(pkg.package)); + fs.remove(paths.listfile_path(core_pkg.package)); } - pkg.state = InstallState::NOT_INSTALLED; - write_update(paths, pkg); + for (auto&& spgh : spghs) + { + StatusParagraph& pkg = **spgh; + if (pkg.state != InstallState::HALF_INSTALLED) continue; + pkg.state = InstallState::NOT_INSTALLED; + write_update(paths, pkg); + } } static void print_plan(const std::map>& group_by_plan_type) diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index fee99a5db..f12c25fb6 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -39,7 +39,7 @@ namespace vcpkg::Commands::Search s.append(Strings::format("%s;", name)); for (const Dependency& d : source_paragraph.depends) { - const std::string dependency_name = replace_dashes_with_underscore(d.name); + const std::string dependency_name = replace_dashes_with_underscore(d.name()); s.append(Strings::format("%s -> %s;", name, dependency_name)); } } diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index d02af5662..347998723 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -347,13 +347,13 @@ namespace UnitTest1 spec_map.get_package_spec( {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}}, {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[1]"}}, - {{"Feature", "2"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[2]"}}, - {{"Feature", "3"}, {"Description", "the first feature for a"}, {"Build-Depends", "a[2]"}}}), + {{"Feature", "2"}, {"Description", "the second feature for a"}, {"Build-Depends", "b[2]"}}, + {{"Feature", "3"}, {"Description", "the third feature for a"}, {"Build-Depends", "a[2]"}}}), {"3"}}; auto spec_b = FullPackageSpec{spec_map.get_package_spec({ {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, - {{"Feature", "2"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, + {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, })}; auto install_plan = Dependencies::create_feature_install_plan( @@ -434,7 +434,7 @@ namespace UnitTest1 {"1"}}; auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_b, spec_x}, StatusParagraphs(std::move(status_paragraphs))); + spec_map.map, {spec_b}, StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(5), install_plan.size()); remove_plan_check(&install_plan[0], "x"); @@ -523,5 +523,45 @@ namespace UnitTest1 features_check(&install_plan[6], "a", {"one", "core"}); features_check(&install_plan[7], "c", {"core"}); } + + TEST_METHOD(default_features_test) + { + using Pgh = std::unordered_map; + + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = FullPackageSpec{ + spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.3"}, {"Default-Features", "1, 2"}, {"Build-Depends", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[2]"}}, + {{"Feature", "2"}, {"Description", "the second feature for a"}, {"Build-Depends", ""}}, + {{"Feature", "3"}, {"Description", "the third feature for a"}, {"Build-Depends", ""}}}), + {""}}; + auto spec_b = FullPackageSpec{ + spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Default-Features", "1, 2"}, {"Build-Depends", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for b"}, {"Build-Depends", "c[1]"}}, + {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, + }), + {""}}; + + auto spec_c = FullPackageSpec{ + spec_map.get_package_spec({ + {{"Source", "c"}, {"Version", "1.3"}, {"Default-Features", "2"}, {"Build-Depends", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for c"}, {"Build-Depends", ""}}, + {{"Feature", "2"}, {"Description", "the second feature for c"}, {"Build-Depends", ""}}, + }), + {""}}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(3), install_plan.size()); + features_check(&install_plan[0], "c", {"core", "1", "2"}); + features_check(&install_plan[1], "b", {"core", "1", "2"}); + features_check(&install_plan[2], "a", {"core", "1", "2"}); + } }; } \ No newline at end of file diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp index 7a49bdbd0..26cc1e22c 100644 --- a/toolsrc/src/tests_dependencies.cpp +++ b/toolsrc/src/tests_dependencies.cpp @@ -17,7 +17,7 @@ namespace UnitTest1 { auto v = expand_qualified_dependencies(parse_comma_list("libA (windows)")); Assert::AreEqual(size_t(1), v.size()); - Assert::AreEqual("libA", v[0].name.c_str()); + Assert::AreEqual("libA", v[0].depend.name.c_str()); Assert::AreEqual("windows", v[0].qualifier.c_str()); } diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index af4b55498..3f2760c22 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -60,7 +60,7 @@ namespace UnitTest1 Assert::AreEqual("m", pgh->core_paragraph->maintainer.c_str()); Assert::AreEqual("d", pgh->core_paragraph->description.c_str()); Assert::AreEqual(size_t(1), pgh->core_paragraph->depends.size()); - Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name.c_str()); + Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name().c_str()); Assert::AreEqual(size_t(1), pgh->core_paragraph->supports.size()); Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str()); } @@ -77,8 +77,8 @@ namespace UnitTest1 auto& pgh = *m_pgh.get(); Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); - Assert::AreEqual("z", pgh->core_paragraph->depends[0].name.c_str()); - Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name.c_str()); + Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str()); + Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str()); } TEST_METHOD(SourceParagraph_Three_Depends) @@ -93,9 +93,9 @@ namespace UnitTest1 auto& pgh = *m_pgh.get(); Assert::AreEqual(size_t(3), pgh->core_paragraph->depends.size()); - Assert::AreEqual("z", pgh->core_paragraph->depends[0].name.c_str()); - Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name.c_str()); - Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name.c_str()); + Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str()); + Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str()); + Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name().c_str()); } TEST_METHOD(SourceParagraph_Three_Supports) @@ -131,9 +131,9 @@ namespace UnitTest1 Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str()); Assert::AreEqual("", pgh->core_paragraph->description.c_str()); Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); - Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name.c_str()); + Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name().c_str()); Assert::AreEqual("windows", pgh->core_paragraph->depends[0].qualifier.c_str()); - Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name.c_str()); + Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name().c_str()); Assert::AreEqual("uwp", pgh->core_paragraph->depends[1].qualifier.c_str()); } @@ -411,6 +411,18 @@ namespace UnitTest1 Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); } + TEST_METHOD(package_spec_feature_parse_with_arch) + { + vcpkg::ExpectedT spec = + vcpkg::FullPackageSpec::from_string("zlib[feature]:x64-uwp", vcpkg::Triplet::X86_WINDOWS); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); + Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); + Assert::IsTrue(spec.get()->features.size() == 1); + Assert::AreEqual("feature", spec.get()->features.front().c_str()); + Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), + spec.get()->package_spec.triplet().canonical_name()); + } + TEST_METHOD(utf8_to_utf16) { auto str = vcpkg::Strings::to_utf16("abc"); diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index a0d690f37..124efb7f2 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -88,29 +88,37 @@ namespace vcpkg::Build return Strings::wformat(LR"("%s" %s %s %s 2>&1)", toolset.vcvarsall.native(), arch, target, tonull); } - static void create_binary_control_file(const VcpkgPaths& paths, - const SourceParagraph& source_paragraph, + static void create_binary_feature_control_file(const SourceParagraph& source_paragraph, + const FeatureParagraph& feature_paragraph, + const Triplet& triplet, + BinaryControlFile& bcf) + { + BinaryParagraph bpgh(source_paragraph, feature_paragraph, triplet); + bcf.features.emplace_back(std::move(bpgh)); + } + + static void create_binary_control_file(const SourceParagraph& source_paragraph, const Triplet& triplet, - const BuildInfo& build_info) + const BuildInfo& build_info, + BinaryControlFile& bcf) { - BinaryParagraph bpgh = BinaryParagraph(source_paragraph, triplet); + BinaryParagraph bpgh(source_paragraph, triplet); if (auto p_ver = build_info.version.get()) { bpgh.version = *p_ver; } - const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL"; - paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(bpgh)); + bcf.core_paragraph = std::move(bpgh); } - static void create_binary_feature_control_file(const VcpkgPaths& paths, - const SourceParagraph& source_paragraph, - const FeatureParagraph& feature_paragraph, - const Triplet& triplet, - const BuildInfo& build_info) + static void write_binary_control_file(const VcpkgPaths& paths, BinaryControlFile bcf) { - BinaryParagraph bpgh = BinaryParagraph(source_paragraph, feature_paragraph, triplet); - const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL"; - paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(bpgh)); + std::string start = Strings::serialize(bcf.core_paragraph); + for (auto&& feature : bcf.features) + { + start += "\n" + Strings::serialize(feature); + } + const fs::path binary_control_file = paths.packages / bcf.core_paragraph.dir() / "CONTROL"; + paths.get_filesystem().write_contents(binary_control_file, start); } ExtendedBuildResult build_package(const VcpkgPaths& paths, @@ -196,6 +204,10 @@ namespace vcpkg::Build auto build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); + BinaryControlFile bcf; + + create_binary_control_file(config.src, triplet, build_info, bcf); + if (error_count != 0) { return {BuildResult::POST_BUILD_CHECKS_FAILED, {}}; @@ -209,13 +221,13 @@ namespace vcpkg::Build for (auto&& f_pgh : config.scf->feature_paragraphs) { if (f_pgh->name == feature) - create_binary_feature_control_file( - paths, *config.scf->core_paragraph, *f_pgh, triplet, build_info); + create_binary_feature_control_file(*config.scf->core_paragraph, *f_pgh, triplet, bcf); } } } } - create_binary_control_file(paths, config.src, triplet, build_info); + + write_binary_control_file(paths, bcf); // const fs::path port_buildtrees_dir = paths.buildtrees / spec.name; // delete_directory(port_buildtrees_dir); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 820e51b33..c84ca73f3 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -101,6 +101,25 @@ namespace vcpkg::Dependencies this->plan_type = InstallPlanType::UNKNOWN; } + std::string InstallPlanAction::displayname() const + { + if (this->feature_list.empty()) + { + return this->spec.to_string(); + } + else + { + std::string features; + for (auto&& feature : this->feature_list) + { + features += feature + ","; + } + features.pop_back(); + + return this->spec.name() + "[" + features + "]:" + this->spec.triplet().to_string(); + } + } + bool InstallPlanAction::compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right) { return left->spec.name() < right->spec.name(); @@ -319,9 +338,9 @@ namespace vcpkg::Dependencies ? RequestType::USER_REQUESTED : RequestType::AUTO_SELECTED; - Expected maybe_bpgh = Paragraphs::try_load_cached_package(paths, spec); - if (auto bpgh = maybe_bpgh.get()) - return ExportPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type}; + Expected maybe_bpgh = Paragraphs::try_load_cached_control_package(paths, spec); + if (auto bcf = maybe_bpgh.get()) + return ExportPlanAction{spec, {nullopt, bcf->core_paragraph, nullopt}, request_type}; auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); if (auto scf = maybe_scf.get()) @@ -366,6 +385,20 @@ namespace vcpkg::Dependencies return f_specs; } + void mark_plus_default(Cluster& cluster, + std::unordered_map& pkg_to_cluster, + GraphPlan& graph_plan) + { + mark_plus("core", cluster, pkg_to_cluster, graph_plan); + if (auto scf = cluster.source_control_file.get()) + { + for (auto&& default_feature : (*scf)->core_paragraph->default_features) + { + mark_plus(default_feature, cluster, pkg_to_cluster, graph_plan); + } + } + } + bool mark_plus(const std::string& feature, Cluster& cluster, std::unordered_map& pkg_to_cluster, @@ -404,21 +437,12 @@ namespace vcpkg::Dependencies graph_plan.install_graph.add_vertex({&cluster}); auto& tracked = cluster.to_install_features; tracked.insert(updated_feature); - if (tracked.find("core") == tracked.end() && tracked.find("") == tracked.end()) - { - cluster.to_install_features.insert("core"); - for (auto&& depend : cluster.edges["core"].build_edges) - { - auto& depend_cluster = pkg_to_cluster[depend.spec]; - mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); - graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); - } - } for (auto&& depend : cluster.edges[updated_feature].build_edges) { auto& depend_cluster = pkg_to_cluster[depend.spec]; mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); + mark_plus_default(depend_cluster, pkg_to_cluster, graph_plan); if (&depend_cluster == &cluster) continue; graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); } @@ -448,6 +472,7 @@ namespace vcpkg::Dependencies mark_plus(original_feature, cluster, pkg_to_cluster, graph_plan); } } + std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db) @@ -515,6 +540,7 @@ namespace vcpkg::Dependencies for (auto&& spec : specs) { Cluster& spec_cluster = pkg_spec_to_package_node[spec.package_spec]; + mark_plus_default(spec_cluster, pkg_spec_to_package_node, graph_plan); for (auto&& feature : spec.features) { mark_plus(feature, spec_cluster, pkg_spec_to_package_node, graph_plan); diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 6b180b532..428ae090d 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -191,7 +191,7 @@ namespace vcpkg for (const std::unique_ptr& pgh : status_db) { - if (pgh->state != InstallState::INSTALLED) + if (pgh->state != InstallState::INSTALLED || pgh->package.feature != "") { continue; } -- cgit v1.2.3 From aab0173509c89746f8988b000854d2ed8c9115e7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 18 Aug 2017 16:22:52 -0700 Subject: [vcpkg] Fix rebase build. --- toolsrc/src/commands_depends.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index b04af5282..49e1c6c01 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -33,7 +33,7 @@ namespace vcpkg::Commands::DependInfo for (const Dependency& dependency : source_paragraph.depends) { - if (Strings::case_insensitive_ascii_contains(dependency.name, filter)) + if (Strings::case_insensitive_ascii_contains(dependency.name(), filter)) { return false; } -- cgit v1.2.3 From 4d34488649fe5d71b8a553706d960a3784c56bb1 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 18 Aug 2017 20:32:35 -0700 Subject: [vcpkg] Consolidate specifier parsing --- toolsrc/src/PackageSpec.cpp | 101 +++++++++++++++++++++---------------- toolsrc/src/SourceParagraph.cpp | 30 ++++++----- toolsrc/src/tests_paragraph.cpp | 61 +++++++++++++--------- toolsrc/src/vcpkg_Dependencies.cpp | 26 +++++----- 4 files changed, 124 insertions(+), 94 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index a7e5648cd..e243f4d89 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -13,52 +13,16 @@ namespace vcpkg ExpectedT FullPackageSpec::from_string(const std::string& spec_as_string, const Triplet& default_triplet) { - auto pos = spec_as_string.find(':'); - auto pos_l_bracket = spec_as_string.find('['); - auto pos_r_bracket = spec_as_string.find(']'); - - FullPackageSpec f; - if (pos == std::string::npos && pos_l_bracket == std::string::npos) - { - f.package_spec = - PackageSpec::from_name_and_triplet(spec_as_string, default_triplet).value_or_exit(VCPKG_LINE_INFO); - return f; - } - else if (pos == std::string::npos) - { - if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) - { - return PackageSpecParseResult::INVALID_CHARACTERS; - } - const std::string name = spec_as_string.substr(0, pos_l_bracket); - f.package_spec = PackageSpec::from_name_and_triplet(name, default_triplet).value_or_exit(VCPKG_LINE_INFO); - f.features = parse_comma_list(spec_as_string.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); - return f; - } - else if (pos_l_bracket == std::string::npos && pos_r_bracket == std::string::npos) - { - const std::string name = spec_as_string.substr(0, pos); - const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1)); - f.package_spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO); - } - else + auto res = ParsedSpecifier::from_string(spec_as_string); + if (auto p = res.get()) { - if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) - { - return PackageSpecParseResult::INVALID_CHARACTERS; - } - const std::string name = spec_as_string.substr(0, pos_l_bracket); - f.features = parse_comma_list(spec_as_string.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); - const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1)); - f.package_spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO); + FullPackageSpec fspec; + Triplet t = p->triplet.empty() ? default_triplet : Triplet::from_canonical_name(p->triplet); + fspec.package_spec = PackageSpec::from_name_and_triplet(p->name, t).value_or_exit(VCPKG_LINE_INFO); + fspec.features = std::move(p->features); + return fspec; } - - auto pos2 = spec_as_string.find(':', pos + 1); - if (pos2 != std::string::npos) - { - return PackageSpecParseResult::TOO_MANY_COLONS; - } - return f; + return res.error(); } ExpectedT PackageSpec::from_name_and_triplet(const std::string& name, @@ -93,4 +57,53 @@ namespace vcpkg } bool operator!=(const PackageSpec& left, const PackageSpec& right) { return !(left == right); } + + ExpectedT ParsedSpecifier::from_string(const std::string& input) + { + auto pos = input.find(':'); + auto pos_l_bracket = input.find('['); + auto pos_r_bracket = input.find(']'); + + ParsedSpecifier f; + if (pos == std::string::npos && pos_l_bracket == std::string::npos) + { + f.name = input; + return f; + } + else if (pos == std::string::npos) + { + if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) + { + return PackageSpecParseResult::INVALID_CHARACTERS; + } + const std::string name = input.substr(0, pos_l_bracket); + f.name = name; + f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); + return f; + } + else if (pos_l_bracket == std::string::npos && pos_r_bracket == std::string::npos) + { + const std::string name = input.substr(0, pos); + f.triplet = input.substr(pos + 1); + f.name = name; + } + else + { + if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) + { + return PackageSpecParseResult::INVALID_CHARACTERS; + } + const std::string name = input.substr(0, pos_l_bracket); + f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); + f.triplet = input.substr(pos + 1); + f.name = name; + } + + auto pos2 = input.find(':', pos + 1); + if (pos2 != std::string::npos) + { + return PackageSpecParseResult::TOO_MANY_COLONS; + } + return f; + } } diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 2aab7c572..f9ae6854a 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include "PackageSpec.h" #include "SourceParagraph.h" #include "Triplet.h" #include "vcpkg_Checks.h" @@ -28,7 +29,11 @@ namespace vcpkg static span get_list_of_valid_fields() { static const std::string valid_fields[] = { - Fields::SOURCE, Fields::VERSION, Fields::DESCRIPTION, Fields::MAINTAINER, Fields::BUILD_DEPENDS, + Fields::SOURCE, + Fields::VERSION, + Fields::DESCRIPTION, + Fields::MAINTAINER, + Fields::BUILD_DEPENDS, }; return valid_fields; @@ -154,21 +159,20 @@ namespace vcpkg Features parse_feature_list(const std::string& name) { - Features f; - int end = (int)name.find(']'); - if (end != std::string::npos) + auto maybe_spec = ParsedSpecifier::from_string(name); + if (auto spec = maybe_spec.get()) { - int start = (int)name.find('['); + Checks::check_exit( + VCPKG_LINE_INFO, spec->triplet.empty(), "error: triplet not allowed in specifier: %s", name); - auto feature_name_list = name.substr(start + 1, end - start - 1); - f.name = name.substr(0, start); - f.features = parse_comma_list(feature_name_list); + Features f; + f.name = spec->name; + f.features = spec->features; + return f; } - else - { - f.name = name; - } - return f; + + Checks::exit_with_message( + VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), name); } Dependency Dependency::parse_dependency(std::string name, std::string qualifier) diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index 3f2760c22..1fd950e19 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -385,42 +385,53 @@ namespace UnitTest1 Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str()); } - TEST_METHOD(package_spec_parse) + TEST_METHOD(parsed_specifier_from_string) { - vcpkg::ExpectedT spec = - vcpkg::FullPackageSpec::from_string("zlib", vcpkg::Triplet::X86_WINDOWS); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); - Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); - Assert::AreEqual(vcpkg::Triplet::X86_WINDOWS.canonical_name(), - spec.get()->package_spec.triplet().canonical_name()); + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::AreEqual(size_t(0), spec->features.size()); + Assert::AreEqual("", spec->triplet.c_str()); } - TEST_METHOD(package_spec_parse_with_arch) + TEST_METHOD(parsed_specifier_from_string_with_triplet) { - vcpkg::ExpectedT spec = - vcpkg::FullPackageSpec::from_string("zlib:x64-uwp", vcpkg::Triplet::X86_WINDOWS); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); - Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); - Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), - spec.get()->package_spec.triplet().canonical_name()); + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::AreEqual("x64-uwp", spec->triplet.c_str()); } - TEST_METHOD(package_spec_parse_with_multiple_colon) + TEST_METHOD(parsed_specifier_from_string_with_colons) { - auto ec = vcpkg::FullPackageSpec::from_string("zlib:x86-uwp:", vcpkg::Triplet::X86_WINDOWS).error(); + auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error(); Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); } - TEST_METHOD(package_spec_feature_parse_with_arch) + TEST_METHOD(parsed_specifier_from_string_with_feature) { - vcpkg::ExpectedT spec = - vcpkg::FullPackageSpec::from_string("zlib[feature]:x64-uwp", vcpkg::Triplet::X86_WINDOWS); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); - Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); - Assert::IsTrue(spec.get()->features.size() == 1); - Assert::AreEqual("feature", spec.get()->features.front().c_str()); - Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), - spec.get()->package_spec.triplet().canonical_name()); + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::IsTrue(spec->features.size() == 1); + Assert::AreEqual("feature", spec->features.front().c_str()); + Assert::AreEqual("x64-uwp", spec->triplet.c_str()); + } + + TEST_METHOD(parsed_specifier_from_string_with_many_features) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::IsTrue(spec->features.size() == 3); + Assert::AreEqual("0", spec->features[0].c_str()); + Assert::AreEqual("1", spec->features[1].c_str()); + Assert::AreEqual("2", spec->features[2].c_str()); + Assert::AreEqual("", spec->triplet.c_str()); } TEST_METHOD(utf8_to_utf16) diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index c84ca73f3..799bca439 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -363,23 +363,25 @@ namespace vcpkg::Dependencies std::vector f_specs; for (auto&& depend : depends) { - int end = (int)depend.find(']'); - if (end != std::string::npos) + auto maybe_spec = ParsedSpecifier::from_string(depend); + if (auto spec = maybe_spec.get()) { - int start = (int)depend.find('['); + Checks::check_exit(VCPKG_LINE_INFO, + spec->triplet.empty(), + "error: triplets cannot currently be specified in this context: %s", + depend); + PackageSpec pspec = + PackageSpec::from_name_and_triplet(spec->name, triplet).value_or_exit(VCPKG_LINE_INFO); - auto feature_name = depend.substr(start + 1, end - start - 1); - auto package_name = depend.substr(0, start); - auto p_spec = PackageSpec::from_name_and_triplet(package_name, triplet).value_or_exit(VCPKG_LINE_INFO); - auto feature_spec = FeatureSpec{p_spec, feature_name}; - f_specs.emplace_back(std::move(feature_spec)); + for (auto&& feature : spec->features) + f_specs.push_back(FeatureSpec{pspec, feature}); + + if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, ""}); } else { - auto p_spec = PackageSpec::from_name_and_triplet(depend, triplet).value_or_exit(VCPKG_LINE_INFO); - - auto feature_spec = FeatureSpec{p_spec, ""}; - f_specs.emplace_back(std::move(feature_spec)); + Checks::exit_with_message( + VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), depend); } } return f_specs; -- cgit v1.2.3 From f219ce0b8c3e84e5fc1df21ad2f2c8b13f0fe413 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 19 Aug 2017 19:27:34 -0700 Subject: [vcpkg] Reorganize some parsing functions. --- toolsrc/src/PackageSpec.cpp | 26 +++++++++++++---- toolsrc/src/SourceParagraph.cpp | 57 ++++---------------------------------- toolsrc/src/tests_dependencies.cpp | 15 ++++++++-- toolsrc/src/vcpkg_Parse.cpp | 33 ++++++++++++++++++++++ 4 files changed, 72 insertions(+), 59 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index e243f4d89..475b3e3f6 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -1,8 +1,11 @@ #include "pch.h" #include "PackageSpec.h" +#include "vcpkg_Parse.h" #include "vcpkg_Util.h" +using vcpkg::Parse::parse_comma_list; + namespace vcpkg { static bool is_valid_package_spec_char(char c) @@ -45,11 +48,7 @@ namespace vcpkg std::string PackageSpec::dir() const { return Strings::format("%s_%s", this->m_name, this->m_triplet); } - std::string PackageSpec::to_string(const std::string& name, const Triplet& triplet) - { - return Strings::format("%s:%s", name, triplet); - } - std::string PackageSpec::to_string() const { return to_string(this->name(), this->triplet()); } + std::string PackageSpec::to_string() const { return Strings::format("%s:%s", this->name(), this->triplet()); } bool operator==(const PackageSpec& left, const PackageSpec& right) { @@ -106,4 +105,21 @@ namespace vcpkg } return f; } + + ExpectedT Features::from_string(const std::string& name) + { + auto maybe_spec = ParsedSpecifier::from_string(name); + if (auto spec = maybe_spec.get()) + { + Checks::check_exit( + VCPKG_LINE_INFO, spec->triplet.empty(), "error: triplet not allowed in specifier: %s", name); + + Features f; + f.name = spec->name; + f.features = spec->features; + return f; + } + + return maybe_spec.error(); + } } diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index f9ae6854a..76c5a2004 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -157,29 +157,15 @@ namespace vcpkg return std::move(control_file); } - Features parse_feature_list(const std::string& name) - { - auto maybe_spec = ParsedSpecifier::from_string(name); - if (auto spec = maybe_spec.get()) - { - Checks::check_exit( - VCPKG_LINE_INFO, spec->triplet.empty(), "error: triplet not allowed in specifier: %s", name); - - Features f; - f.name = spec->name; - f.features = spec->features; - return f; - } - - Checks::exit_with_message( - VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), name); - } - Dependency Dependency::parse_dependency(std::string name, std::string qualifier) { Dependency dep; dep.qualifier = qualifier; - dep.depend = parse_feature_list(name); + if (auto maybe_features = Features::from_string(name)) + dep.depend = *maybe_features.get(); + else + Checks::exit_with_message( + VCPKG_LINE_INFO, "error while parsing dependency: %s: %s", to_string(maybe_features.error()), name); return dep; } @@ -217,39 +203,6 @@ namespace vcpkg }); } - std::vector parse_comma_list(const std::string& str) - { - if (str.empty()) - { - return {}; - } - - std::vector out; - - size_t cur = 0; - do - { - auto pos = str.find(',', cur); - if (pos == std::string::npos) - { - out.push_back(str.substr(cur)); - break; - } - out.push_back(str.substr(cur, pos - cur)); - - // skip comma and space - ++pos; - if (str[pos] == ' ') - { - ++pos; - } - - cur = pos; - } while (cur != std::string::npos); - - return out; - } - std::vector filter_dependencies(const std::vector& deps, const Triplet& t) { std::vector ret; diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp index 26cc1e22c..6a6981d73 100644 --- a/toolsrc/src/tests_dependencies.cpp +++ b/toolsrc/src/tests_dependencies.cpp @@ -8,6 +8,7 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace vcpkg; +using Parse::parse_comma_list; namespace UnitTest1 { @@ -41,7 +42,15 @@ namespace UnitTest1 TEST_METHOD(parse_supports_all) { auto v = Supports::parse({ - "x64", "x86", "arm", "windows", "uwp", "v140", "v141", "crt-static", "crt-dynamic", + "x64", + "x86", + "arm", + "windows", + "uwp", + "v140", + "v141", + "crt-static", + "crt-dynamic", }); Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); @@ -74,7 +83,9 @@ namespace UnitTest1 TEST_METHOD(parse_supports_some) { auto v = Supports::parse({ - "x64", "x86", "windows", + "x64", + "x86", + "windows", }); Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); diff --git a/toolsrc/src/vcpkg_Parse.cpp b/toolsrc/src/vcpkg_Parse.cpp index 659af2939..118cde900 100644 --- a/toolsrc/src/vcpkg_Parse.cpp +++ b/toolsrc/src/vcpkg_Parse.cpp @@ -44,4 +44,37 @@ namespace vcpkg::Parse } return nullptr; } + + std::vector parse_comma_list(const std::string& str) + { + if (str.empty()) + { + return {}; + } + + std::vector out; + + size_t cur = 0; + do + { + auto pos = str.find(',', cur); + if (pos == std::string::npos) + { + out.push_back(str.substr(cur)); + break; + } + out.push_back(str.substr(cur, pos - cur)); + + // skip comma and space + ++pos; + if (str[pos] == ' ') + { + ++pos; + } + + cur = pos; + } while (cur != std::string::npos); + + return out; + } } -- cgit v1.2.3 From bd222504abea410d77487e176649ae9b6989c4e0 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 20 Aug 2017 19:09:39 -0700 Subject: [vcpkg] Refactor parsing together and flatten featurespec usages --- toolsrc/src/PackageSpec.cpp | 42 +++++++++++++ toolsrc/src/commands_install.cpp | 6 +- toolsrc/src/test_install_plan.cpp | 56 ++++++++++------- toolsrc/src/tests_package_spec.cpp | 119 +++++++++++++++++++++++++++++++++++++ toolsrc/src/tests_paragraph.cpp | 63 -------------------- toolsrc/src/vcpkg_Dependencies.cpp | 56 ++++------------- 6 files changed, 212 insertions(+), 130 deletions(-) create mode 100644 toolsrc/src/tests_package_spec.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index 475b3e3f6..a5d40e998 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -13,6 +13,48 @@ namespace vcpkg return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)) || (c == '[') || (c == ']'); } + std::vector FeatureSpec::from_strings_and_triplet(const std::vector& depends, + const Triplet& triplet) + { + std::vector f_specs; + for (auto&& depend : depends) + { + auto maybe_spec = ParsedSpecifier::from_string(depend); + if (auto spec = maybe_spec.get()) + { + Checks::check_exit(VCPKG_LINE_INFO, + spec->triplet.empty(), + "error: triplets cannot currently be specified in this context: %s", + depend); + PackageSpec pspec = + PackageSpec::from_name_and_triplet(spec->name, triplet).value_or_exit(VCPKG_LINE_INFO); + + for (auto&& feature : spec->features) + f_specs.push_back(FeatureSpec{pspec, feature}); + + if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, ""}); + } + else + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), depend); + } + } + return f_specs; + } + + std::vector FullPackageSpec::to_feature_specs(const std::vector& specs) + { + std::vector ret; + for (auto&& spec : specs) + { + ret.emplace_back(spec.package_spec, ""); + for (auto&& feature : spec.features) + ret.emplace_back(spec.package_spec, feature); + } + return ret; + } + ExpectedT FullPackageSpec::from_string(const std::string& spec_as_string, const Triplet& default_triplet) { diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 2965d9025..3fc0e2563 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -14,10 +14,10 @@ namespace vcpkg::Commands::Install { using Dependencies::InstallPlanAction; - using Dependencies::RequestType; using Dependencies::InstallPlanType; using Dependencies::RemovePlanAction; using Dependencies::RemovePlanType; + using Dependencies::RequestType; InstallDir InstallDir::from_destination_root(const fs::path& destination_root, const std::string& destination_subdirectory, @@ -440,8 +440,8 @@ namespace vcpkg::Commands::Install .value_or_exit(VCPKG_LINE_INFO); scf_map[pkg_spec] = std::move(*port); } - std::vector action_plan = - Dependencies::create_feature_install_plan(scf_map, full_specs, status_db); + std::vector action_plan = Dependencies::create_feature_install_plan( + scf_map, FullPackageSpec::to_feature_specs(full_specs), status_db); // install plan will be empty if it is already installed - need to change this at status paragraph part Checks::check_exit( VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty for feature packages"); diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 347998723..e7c62813e 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -214,8 +214,10 @@ namespace UnitTest1 {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}}, })}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(4), install_plan.size()); remove_plan_check(&install_plan[0], "a"); @@ -248,8 +250,10 @@ namespace UnitTest1 {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}}, })}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(2), install_plan.size()); features_check(&install_plan[0], "b", {"beefeatureone", "beefeaturetwo", "core"}); @@ -284,8 +288,10 @@ namespace UnitTest1 }), {"core"}}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_c, spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_c, spec_a}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(4), install_plan.size()); remove_plan_check(&install_plan[0], "a"); @@ -328,8 +334,10 @@ namespace UnitTest1 }), {"core"}}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_c}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_c}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(1), install_plan.size()); features_check(&install_plan[0], "c", {"core"}); @@ -356,8 +364,10 @@ namespace UnitTest1 {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, })}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(2), install_plan.size()); features_check(&install_plan[0], "b", {"core", "2"}); @@ -389,8 +399,10 @@ namespace UnitTest1 }), {"1"}}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_a, spec_b}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a, spec_b}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(3), install_plan.size()); remove_plan_check(&install_plan[0], "b"); @@ -433,8 +445,10 @@ namespace UnitTest1 }), {"1"}}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_b}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_b}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(5), install_plan.size()); remove_plan_check(&install_plan[0], "x"); @@ -495,10 +509,10 @@ namespace UnitTest1 }), {"core"}}; - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - {spec_c_64, spec_a_86, spec_a_64, spec_c_86}, - StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({spec_c_64, spec_a_86, spec_a_64, spec_c_86}), + StatusParagraphs(std::move(status_paragraphs))); /*Assert::AreEqual(size_t(8), install_plan.size()); auto iterator_pos = [&](const PackageSpec& spec, size_t start) -> int { @@ -555,8 +569,10 @@ namespace UnitTest1 }), {""}}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(3), install_plan.size()); features_check(&install_plan[0], "c", {"core", "1", "2"}); diff --git a/toolsrc/src/tests_package_spec.cpp b/toolsrc/src/tests_package_spec.cpp new file mode 100644 index 000000000..fa201b372 --- /dev/null +++ b/toolsrc/src/tests_package_spec.cpp @@ -0,0 +1,119 @@ +#include "BinaryParagraph.h" +#include "CppUnitTest.h" +#include "Paragraphs.h" +#include "vcpkg_Strings.h" + +#pragma comment(lib, "version") +#pragma comment(lib, "winhttp") + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace Microsoft::VisualStudio::CppUnitTestFramework +{ + template<> + inline std::wstring ToString(const vcpkg::PackageSpecParseResult& t) + { + return ToString(static_cast(t)); + } + + template<> + inline std::wstring ToString(const vcpkg::PackageSpec& t) + { + return ToString(t.to_string()); + } +} + +namespace Strings = vcpkg::Strings; + +namespace UnitTest1 +{ + using namespace vcpkg; + + class SpecifierConversion : public TestClass + { + TEST_METHOD(full_package_spec_to_feature_specs) + { + auto a_spec = PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + auto b_spec = PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + auto fspecs = FullPackageSpec::to_feature_specs({{a_spec, {"0", "1"}}, {b_spec, {"2", "3"}}}); + + Assert::AreEqual(size_t(6), fspecs.size()); + + std::array features = {"", "0", "1", "", "2", "3"}; + std::array specs = {&a_spec, &a_spec, &a_spec, &b_spec, &b_spec, &b_spec}; + + for (int i = 0; i < features.size(); ++i) + { + Assert::AreEqual(features[i], fspecs[i].feature().c_str()); + Assert::AreEqual(*specs[i], fspecs[i].spec()); + } + } + }; + + class SpecifierParsing : public TestClass + { + TEST_METHOD(parsed_specifier_from_string) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::AreEqual(size_t(0), spec->features.size()); + Assert::AreEqual("", spec->triplet.c_str()); + } + + TEST_METHOD(parsed_specifier_from_string_with_triplet) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::AreEqual("x64-uwp", spec->triplet.c_str()); + } + + TEST_METHOD(parsed_specifier_from_string_with_colons) + { + auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error(); + Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); + } + + TEST_METHOD(parsed_specifier_from_string_with_feature) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::IsTrue(spec->features.size() == 1); + Assert::AreEqual("feature", spec->features.front().c_str()); + Assert::AreEqual("x64-uwp", spec->triplet.c_str()); + } + + TEST_METHOD(parsed_specifier_from_string_with_many_features) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::IsTrue(spec->features.size() == 3); + Assert::AreEqual("0", spec->features[0].c_str()); + Assert::AreEqual("1", spec->features[1].c_str()); + Assert::AreEqual("2", spec->features[2].c_str()); + Assert::AreEqual("", spec->triplet.c_str()); + } + + TEST_METHOD(utf8_to_utf16) + { + auto str = vcpkg::Strings::to_utf16("abc"); + Assert::AreEqual(L"abc", str.c_str()); + } + + TEST_METHOD(utf8_to_utf16_with_whitespace) + { + auto str = vcpkg::Strings::to_utf16("abc -x86-windows"); + Assert::AreEqual(L"abc -x86-windows", str.c_str()); + } + }; + + TEST_CLASS(Metrics){}; +} diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index 1fd950e19..47a07e12d 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -384,68 +384,5 @@ namespace UnitTest1 Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str()); } - - TEST_METHOD(parsed_specifier_from_string) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::AreEqual(size_t(0), spec->features.size()); - Assert::AreEqual("", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_triplet) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::AreEqual("x64-uwp", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_colons) - { - auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error(); - Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); - } - - TEST_METHOD(parsed_specifier_from_string_with_feature) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::IsTrue(spec->features.size() == 1); - Assert::AreEqual("feature", spec->features.front().c_str()); - Assert::AreEqual("x64-uwp", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_many_features) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::IsTrue(spec->features.size() == 3); - Assert::AreEqual("0", spec->features[0].c_str()); - Assert::AreEqual("1", spec->features[1].c_str()); - Assert::AreEqual("2", spec->features[2].c_str()); - Assert::AreEqual("", spec->triplet.c_str()); - } - - TEST_METHOD(utf8_to_utf16) - { - auto str = vcpkg::Strings::to_utf16("abc"); - Assert::AreEqual(L"abc", str.c_str()); - } - - TEST_METHOD(utf8_to_utf16_with_whitespace) - { - auto str = vcpkg::Strings::to_utf16("abc -x86-windows"); - Assert::AreEqual(L"abc -x86-windows", str.c_str()); - } }; - - TEST_CLASS(Metrics){}; } diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 799bca439..5226fac24 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -358,35 +358,6 @@ namespace vcpkg::Dependencies return toposort; } - std::vector to_feature_specs(const std::vector& depends, const Triplet& triplet) - { - std::vector f_specs; - for (auto&& depend : depends) - { - auto maybe_spec = ParsedSpecifier::from_string(depend); - if (auto spec = maybe_spec.get()) - { - Checks::check_exit(VCPKG_LINE_INFO, - spec->triplet.empty(), - "error: triplets cannot currently be specified in this context: %s", - depend); - PackageSpec pspec = - PackageSpec::from_name_and_triplet(spec->name, triplet).value_or_exit(VCPKG_LINE_INFO); - - for (auto&& feature : spec->features) - f_specs.push_back(FeatureSpec{pspec, feature}); - - if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, ""}); - } - else - { - Checks::exit_with_message( - VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), depend); - } - } - return f_specs; - } - void mark_plus_default(Cluster& cluster, std::unordered_map& pkg_to_cluster, GraphPlan& graph_plan) @@ -442,8 +413,8 @@ namespace vcpkg::Dependencies for (auto&& depend : cluster.edges[updated_feature].build_edges) { - auto& depend_cluster = pkg_to_cluster[depend.spec]; - mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); + auto& depend_cluster = pkg_to_cluster[depend.spec()]; + mark_plus(depend.feature(), depend_cluster, pkg_to_cluster, graph_plan); mark_plus_default(depend_cluster, pkg_to_cluster, graph_plan); if (&depend_cluster == &cluster) continue; graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); @@ -462,7 +433,7 @@ namespace vcpkg::Dependencies auto& remove_edges_edges = pair.second.remove_edges; for (auto&& depend : remove_edges_edges) { - auto& depend_cluster = pkg_to_cluster[depend.spec]; + auto& depend_cluster = pkg_to_cluster[depend.spec()]; graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); depend_cluster.transient_uninstalled = true; mark_minus(depend_cluster, pkg_to_cluster, graph_plan); @@ -476,7 +447,7 @@ namespace vcpkg::Dependencies } std::vector create_feature_install_plan(const std::unordered_map& map, - const std::vector& specs, + const std::vector& specs, const StatusParagraphs& status_db) { std::unordered_map pkg_spec_to_package_node; @@ -488,14 +459,14 @@ namespace vcpkg::Dependencies node.spec = it.first; FeatureNodeEdges core_dependencies; auto core_depends = filter_dependencies(it.second.core_paragraph->depends, node.spec.triplet()); - core_dependencies.build_edges = to_feature_specs(core_depends, node.spec.triplet()); + core_dependencies.build_edges = FeatureSpec::from_strings_and_triplet(core_depends, node.spec.triplet()); node.edges["core"] = std::move(core_dependencies); for (const auto& feature : it.second.feature_paragraphs) { FeatureNodeEdges added_edges; auto depends = filter_dependencies(feature->depends, node.spec.triplet()); - added_edges.build_edges = to_feature_specs(depends, node.spec.triplet()); + added_edges.build_edges = FeatureSpec::from_strings_and_triplet(depends, node.spec.triplet()); node.edges.emplace(feature->name, std::move(added_edges)); } node.source_control_file = &it.second; @@ -508,13 +479,13 @@ namespace vcpkg::Dependencies Cluster& cluster = pkg_spec_to_package_node[spec]; cluster.transient_uninstalled = false; - auto reverse_edges = - to_feature_specs(status_paragraph->package.depends, status_paragraph->package.spec.triplet()); + auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, + status_paragraph->package.spec.triplet()); for (auto&& dependency : reverse_edges) { - auto pkg_node = pkg_spec_to_package_node.find(dependency.spec); - auto depends_name = dependency.feature_name; + auto pkg_node = pkg_spec_to_package_node.find(dependency.spec()); + auto depends_name = dependency.feature(); if (depends_name == "") { for (auto&& default_feature : status_paragraph->package.default_features) @@ -541,12 +512,9 @@ namespace vcpkg::Dependencies GraphPlan graph_plan; for (auto&& spec : specs) { - Cluster& spec_cluster = pkg_spec_to_package_node[spec.package_spec]; + Cluster& spec_cluster = pkg_spec_to_package_node[spec.spec()]; mark_plus_default(spec_cluster, pkg_spec_to_package_node, graph_plan); - for (auto&& feature : spec.features) - { - mark_plus(feature, spec_cluster, pkg_spec_to_package_node, graph_plan); - } + mark_plus(spec.feature(), spec_cluster, pkg_spec_to_package_node, graph_plan); } Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); -- cgit v1.2.3 From 1ba7cef1f07e8fd8c0053694b306dcc3960f720e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 20 Aug 2017 19:36:43 -0700 Subject: [vcpkg] Remove incomplete default features implementation --- toolsrc/src/SourceParagraph.cpp | 5 ++ toolsrc/src/test_install_plan.cpp | 42 -------------- toolsrc/src/vcpkg_Dependencies.cpp | 114 ++++++++++++++++++++----------------- 3 files changed, 68 insertions(+), 93 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 76c5a2004..54f34cbd3 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -216,6 +216,11 @@ namespace vcpkg return ret; } + std::vector filter_dependencies_to_specs(const std::vector& deps, const Triplet& t) + { + return FeatureSpec::from_strings_and_triplet(filter_dependencies(deps, t), t); + } + const std::string to_string(const Dependency& dep) { std::string name = dep.name(); diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index e7c62813e..f0884c063 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -537,47 +537,5 @@ namespace UnitTest1 features_check(&install_plan[6], "a", {"one", "core"}); features_check(&install_plan[7], "c", {"core"}); } - - TEST_METHOD(default_features_test) - { - using Pgh = std::unordered_map; - - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Default-Features", "1, 2"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[2]"}}, - {{"Feature", "2"}, {"Description", "the second feature for a"}, {"Build-Depends", ""}}, - {{"Feature", "3"}, {"Description", "the third feature for a"}, {"Build-Depends", ""}}}), - {""}}; - auto spec_b = FullPackageSpec{ - spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Default-Features", "1, 2"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for b"}, {"Build-Depends", "c[1]"}}, - {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, - }), - {""}}; - - auto spec_c = FullPackageSpec{ - spec_map.get_package_spec({ - {{"Source", "c"}, {"Version", "1.3"}, {"Default-Features", "2"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for c"}, {"Build-Depends", ""}}, - {{"Feature", "2"}, {"Description", "the second feature for c"}, {"Build-Depends", ""}}, - }), - {""}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(3), install_plan.size()); - features_check(&install_plan[0], "c", {"core", "1", "2"}); - features_check(&install_plan[1], "b", {"core", "1", "2"}); - features_check(&install_plan[2], "a", {"core", "1", "2"}); - } }; } \ No newline at end of file diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 5226fac24..fa4876bd7 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -12,6 +12,10 @@ namespace vcpkg::Dependencies { + struct ClusterGraph; + void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } std::vector AnyParagraph::dependencies(const Triplet& triplet) const @@ -358,71 +362,74 @@ namespace vcpkg::Dependencies return toposort; } - void mark_plus_default(Cluster& cluster, - std::unordered_map& pkg_to_cluster, - GraphPlan& graph_plan) + struct ClusterGraph { - mark_plus("core", cluster, pkg_to_cluster, graph_plan); - if (auto scf = cluster.source_control_file.get()) + explicit ClusterGraph(std::unordered_map&& graph) : m_graph(std::move(graph)) {} + ClusterGraph(ClusterGraph&&) = default; + + Cluster& get(const PackageSpec& spec) { - for (auto&& default_feature : (*scf)->core_paragraph->default_features) - { - mark_plus(default_feature, cluster, pkg_to_cluster, graph_plan); - } + auto it = m_graph.find(spec); + if (it == m_graph.end()) Checks::unreachable(VCPKG_LINE_INFO); + return it->second; } - } - bool mark_plus(const std::string& feature, - Cluster& cluster, - std::unordered_map& pkg_to_cluster, - GraphPlan& graph_plan) + private: + ClusterGraph(const ClusterGraph&) = delete; + std::unordered_map m_graph; + }; + + void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { - auto it = cluster.edges.find(feature); - std::string updated_feature = feature; - if (updated_feature == "") + if (feature == "") { - updated_feature = "core"; - it = cluster.edges.find("core"); + // Indicates that core was not specified in the reference + return mark_plus("core", cluster, graph, graph_plan); } + auto it = cluster.edges.find(feature); if (it == cluster.edges.end()) { Checks::unreachable(VCPKG_LINE_INFO); } - if (cluster.edges[updated_feature].plus) return true; + if (cluster.edges[feature].plus) return; - if (cluster.original_features.find(updated_feature) == cluster.original_features.end()) + if (cluster.original_features.find(feature) == cluster.original_features.end()) { cluster.transient_uninstalled = true; } if (!cluster.transient_uninstalled) { - return false; + return; } - cluster.edges[updated_feature].plus = true; + cluster.edges[feature].plus = true; if (!cluster.original_features.empty()) { - mark_minus(cluster, pkg_to_cluster, graph_plan); + mark_minus(cluster, graph, graph_plan); } graph_plan.install_graph.add_vertex({&cluster}); auto& tracked = cluster.to_install_features; - tracked.insert(updated_feature); + tracked.insert(feature); + + if (feature != "core") + { + // All features implicitly depend on core + mark_plus("core", cluster, graph, graph_plan); + } - for (auto&& depend : cluster.edges[updated_feature].build_edges) + for (auto&& depend : cluster.edges[feature].build_edges) { - auto& depend_cluster = pkg_to_cluster[depend.spec()]; - mark_plus(depend.feature(), depend_cluster, pkg_to_cluster, graph_plan); - mark_plus_default(depend_cluster, pkg_to_cluster, graph_plan); + auto& depend_cluster = graph.get(depend.spec()); + mark_plus(depend.feature(), depend_cluster, graph, graph_plan); if (&depend_cluster == &cluster) continue; graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); } - return true; } - void mark_minus(Cluster& cluster, std::unordered_map& pkg_to_cluster, GraphPlan& graph_plan) + void mark_minus(Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { if (cluster.will_remove) return; cluster.will_remove = true; @@ -433,40 +440,38 @@ namespace vcpkg::Dependencies auto& remove_edges_edges = pair.second.remove_edges; for (auto&& depend : remove_edges_edges) { - auto& depend_cluster = pkg_to_cluster[depend.spec()]; + auto& depend_cluster = graph.get(depend.spec()); graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); - depend_cluster.transient_uninstalled = true; - mark_minus(depend_cluster, pkg_to_cluster, graph_plan); + mark_minus(depend_cluster, graph, graph_plan); } } + + cluster.transient_uninstalled = true; for (auto&& original_feature : cluster.original_features) { - cluster.transient_uninstalled = true; - mark_plus(original_feature, cluster, pkg_to_cluster, graph_plan); + mark_plus(original_feature, cluster, graph, graph_plan); } } - std::vector create_feature_install_plan(const std::unordered_map& map, - const std::vector& specs, - const StatusParagraphs& status_db) + static ClusterGraph create_feature_install_graph(const std::unordered_map& map, + const StatusParagraphs& status_db) { - std::unordered_map pkg_spec_to_package_node; + std::unordered_map graph; for (const auto& it : map) { - Cluster& node = pkg_spec_to_package_node[it.first]; + Cluster& node = graph[it.first]; node.spec = it.first; FeatureNodeEdges core_dependencies; - auto core_depends = filter_dependencies(it.second.core_paragraph->depends, node.spec.triplet()); - core_dependencies.build_edges = FeatureSpec::from_strings_and_triplet(core_depends, node.spec.triplet()); - node.edges["core"] = std::move(core_dependencies); + core_dependencies.build_edges = + filter_dependencies_to_specs(it.second.core_paragraph->depends, node.spec.triplet()); + node.edges.emplace("core", std::move(core_dependencies)); for (const auto& feature : it.second.feature_paragraphs) { FeatureNodeEdges added_edges; - auto depends = filter_dependencies(feature->depends, node.spec.triplet()); - added_edges.build_edges = FeatureSpec::from_strings_and_triplet(depends, node.spec.triplet()); + added_edges.build_edges = filter_dependencies_to_specs(feature->depends, node.spec.triplet()); node.edges.emplace(feature->name, std::move(added_edges)); } node.source_control_file = &it.second; @@ -476,7 +481,7 @@ namespace vcpkg::Dependencies { auto& spec = status_paragraph->package.spec; auto& status_paragraph_feature = status_paragraph->package.feature; - Cluster& cluster = pkg_spec_to_package_node[spec]; + Cluster& cluster = graph[spec]; cluster.transient_uninstalled = false; auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, @@ -484,7 +489,7 @@ namespace vcpkg::Dependencies for (auto&& dependency : reverse_edges) { - auto pkg_node = pkg_spec_to_package_node.find(dependency.spec()); + auto pkg_node = graph.find(dependency.spec()); auto depends_name = dependency.feature(); if (depends_name == "") { @@ -508,13 +513,20 @@ namespace vcpkg::Dependencies cluster.original_features.insert(status_paragraph_feature); } } + return ClusterGraph(std::move(graph)); + } + + std::vector create_feature_install_plan(const std::unordered_map& map, + const std::vector& specs, + const StatusParagraphs& status_db) + { + ClusterGraph graph = create_feature_install_graph(map, status_db); GraphPlan graph_plan; for (auto&& spec : specs) { - Cluster& spec_cluster = pkg_spec_to_package_node[spec.spec()]; - mark_plus_default(spec_cluster, pkg_spec_to_package_node, graph_plan); - mark_plus(spec.feature(), spec_cluster, pkg_spec_to_package_node, graph_plan); + Cluster& spec_cluster = graph.get(spec.spec()); + mark_plus(spec.feature(), spec_cluster, graph, graph_plan); } Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); -- cgit v1.2.3 From c7de717cbc2b6ab89dc8056984c0a4685e9cf56e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 20 Aug 2017 20:06:21 -0700 Subject: [vcpkg] Refactor features implementation. Improve error handling. --- toolsrc/src/vcpkg_Dependencies.cpp | 140 ++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 42 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index fa4876bd7..8f92179b5 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -12,11 +12,76 @@ namespace vcpkg::Dependencies { - struct ClusterGraph; - void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); - void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + struct FeatureNodeEdges + { + std::vector remove_edges; + std::vector build_edges; + bool plus = false; + }; + + struct Cluster + { + std::vector status_paragraphs; + Optional source_control_file; + PackageSpec spec; + std::unordered_map edges; + std::unordered_set to_install_features; + std::unordered_set original_features; + bool will_remove = false; + bool transient_uninstalled = true; + Cluster() = default; + + private: + Cluster(const Cluster&) = delete; + Cluster& operator=(const Cluster&) = delete; + }; + + struct ClusterPtr + { + Cluster* ptr; + }; bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } +} + +template<> +struct std::hash +{ + size_t operator()(const vcpkg::Dependencies::ClusterPtr& value) const + { + return std::hash()(value.ptr->spec); + } +}; + +namespace vcpkg::Dependencies +{ + struct GraphPlan + { + Graphs::Graph remove_graph; + Graphs::Graph install_graph; + }; + + struct ClusterGraph + { + explicit ClusterGraph(std::unordered_map&& graph) : m_graph(std::move(graph)) {} + ClusterGraph(ClusterGraph&&) = default; + + Cluster& get(const PackageSpec& spec) + { + if (auto p = try_get(spec)) return *p; + Checks::exit_with_message(VCPKG_LINE_INFO, "error: reference to missing package: %s", spec); + } + Cluster* try_get(const PackageSpec& spec) + { + auto it = m_graph.find(spec); + if (it == m_graph.end()) return nullptr; + return &it->second; + } + + private: + ClusterGraph(const ClusterGraph&) = delete; + std::unordered_map m_graph; + }; std::vector AnyParagraph::dependencies(const Triplet& triplet) const { @@ -362,22 +427,8 @@ namespace vcpkg::Dependencies return toposort; } - struct ClusterGraph - { - explicit ClusterGraph(std::unordered_map&& graph) : m_graph(std::move(graph)) {} - ClusterGraph(ClusterGraph&&) = default; - - Cluster& get(const PackageSpec& spec) - { - auto it = m_graph.find(spec); - if (it == m_graph.end()) Checks::unreachable(VCPKG_LINE_INFO); - return it->second; - } - - private: - ClusterGraph(const ClusterGraph&) = delete; - std::unordered_map m_graph; - }; + void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { @@ -477,33 +528,18 @@ namespace vcpkg::Dependencies node.source_control_file = &it.second; } - for (auto&& status_paragraph : get_installed_ports(status_db)) + auto installed_ports = get_installed_ports(status_db); + + for (auto&& status_paragraph : installed_ports) { - auto& spec = status_paragraph->package.spec; - auto& status_paragraph_feature = status_paragraph->package.feature; - Cluster& cluster = graph[spec]; + Cluster& cluster = graph[status_paragraph->package.spec]; cluster.transient_uninstalled = false; - auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, - status_paragraph->package.spec.triplet()); - for (auto&& dependency : reverse_edges) - { - auto pkg_node = graph.find(dependency.spec()); - auto depends_name = dependency.feature(); - if (depends_name == "") - { - for (auto&& default_feature : status_paragraph->package.default_features) - { - auto& target_node = pkg_node->second.edges[default_feature]; - target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); - } - depends_name = "core"; - } - auto& target_node = pkg_node->second.edges[depends_name]; - target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); - } - cluster.status_paragraphs.emplace_back(*status_paragraph); + cluster.status_paragraphs.emplace_back(status_paragraph); + + auto& status_paragraph_feature = status_paragraph->package.feature; + // In this case, empty string indicates the "core" paragraph for a package. if (status_paragraph_feature == "") { cluster.original_features.insert("core"); @@ -513,6 +549,26 @@ namespace vcpkg::Dependencies cluster.original_features.insert(status_paragraph_feature); } } + + for (auto&& status_paragraph : installed_ports) + { + auto& spec = status_paragraph->package.spec; + auto& status_paragraph_feature = status_paragraph->package.feature; + auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, + status_paragraph->package.spec.triplet()); + + for (auto&& dependency : reverse_edges) + { + auto dep_cluster = graph.find(dependency.spec()); + if (dep_cluster == graph.end()) Checks::unreachable(VCPKG_LINE_INFO); + + auto depends_name = dependency.feature(); + if (depends_name == "") depends_name = "core"; + + auto& target_node = dep_cluster->second.edges[depends_name]; + target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); + } + } return ClusterGraph(std::move(graph)); } -- cgit v1.2.3 From 27be8b5c7489ea52156669f8e556ad3db1fd11d1 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 21 Aug 2017 17:16:14 -0700 Subject: [vcpkg] Fix feature packages for non-default triplets. Reduce duplication between normal installs and feature installs. --- toolsrc/src/VcpkgPaths.cpp | 1 + toolsrc/src/commands_install.cpp | 269 +++++++++++++++++-------------------- toolsrc/src/test_install_plan.cpp | 4 +- toolsrc/src/vcpkg_Dependencies.cpp | 118 ++++++++-------- 4 files changed, 193 insertions(+), 199 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 60204bcdd..4be636650 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -214,6 +214,7 @@ namespace vcpkg fs::path VcpkgPaths::package_dir(const PackageSpec& spec) const { return this->packages / spec.dir(); } fs::path VcpkgPaths::port_dir(const PackageSpec& spec) const { return this->ports / spec.name(); } + fs::path VcpkgPaths::port_dir(const std::string& name) const { return this->ports / name; } fs::path VcpkgPaths::build_info_file_path(const PackageSpec& spec) const { diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 3fc0e2563..9e37dc057 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -13,11 +13,7 @@ namespace vcpkg::Commands::Install { - using Dependencies::InstallPlanAction; - using Dependencies::InstallPlanType; - using Dependencies::RemovePlanAction; - using Dependencies::RemovePlanType; - using Dependencies::RequestType; + using namespace Dependencies; InstallDir InstallDir::from_destination_root(const fs::path& destination_root, const std::string& destination_subdirectory, @@ -176,41 +172,6 @@ namespace vcpkg::Commands::Install return SortedVector(std::move(installed_files)); } - static void print_plan(const std::map>& group_by_plan_type) - { - static constexpr std::array order = { - InstallPlanType::ALREADY_INSTALLED, InstallPlanType::BUILD_AND_INSTALL, InstallPlanType::INSTALL}; - - for (const InstallPlanType plan_type : order) - { - auto it = group_by_plan_type.find(plan_type); - if (it == group_by_plan_type.cend()) - { - continue; - } - - std::vector cont = it->second; - std::sort(cont.begin(), cont.end(), &InstallPlanAction::compare_by_name); - const std::string as_string = Strings::join("\n", cont, [](const InstallPlanAction* p) { - return Dependencies::to_output_string(p->request_type, p->spec.to_string()); - }); - - switch (plan_type) - { - case InstallPlanType::ALREADY_INSTALLED: - System::println("The following packages are already installed:\n%s", as_string); - continue; - case InstallPlanType::BUILD_AND_INSTALL: - System::println("The following packages will be built and installed:\n%s", as_string); - continue; - case InstallPlanType::INSTALL: - System::println("The following packages will be installed:\n%s", as_string); - continue; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - } - void install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db) { const fs::path package_dir = paths.package_dir(bcf.core_paragraph.spec); @@ -383,19 +344,78 @@ namespace vcpkg::Commands::Install Checks::unreachable(VCPKG_LINE_INFO); } - static void print_plan(const std::vector rebuilt_plans, - const std::vector new_plans) + static void print_plan(const std::vector& action_plan, bool is_recursive) { + std::vector remove_plans; + std::vector rebuilt_plans; + std::vector only_install_plans; + std::vector new_plans; + + const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { + if (auto iplan = package.install_plan.get()) + return iplan->request_type != RequestType::USER_REQUESTED; + else + return false; + }) != action_plan.cend(); + + for (auto&& action : action_plan) + { + if (auto install_action = action.install_plan.get()) + { + // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at + // all. + auto it = Util::find_if( + remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); + if (it != remove_plans.end()) + { + rebuilt_plans.emplace_back(install_action); + } + else + { + if (install_action->plan_type == InstallPlanType::INSTALL) + only_install_plans.emplace_back(install_action); + else + new_plans.emplace_back(install_action); + } + } + else if (auto remove_action = action.remove_plan.get()) + { + remove_plans.emplace_back(remove_action); + } + } + + std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name); + std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); + const std::string rebuilt_string = Strings::join("\n", rebuilt_plans, [](const InstallPlanAction* p) { - return Dependencies::to_output_string(p->request_type, p->displayname()); + return to_output_string(p->request_type, p->displayname()); }); + if (rebuilt_plans.size() > 0) System::println("The following packages will be rebuilt:\n%s", rebuilt_string); const std::string new_string = Strings::join("\n", new_plans, [](const InstallPlanAction* p) { - return Dependencies::to_output_string(p->request_type, p->displayname()); + return to_output_string(p->request_type, p->displayname()); }); + if (new_plans.size() > 0) + System::println("The following packages will be built and installed:\n%s", new_string); - if (rebuilt_plans.size() > 0) System::println("The following packages will be rebuilt:\n%s", rebuilt_string); - if (new_plans.size() > 0) System::println("The following packages will be installed:\n%s", new_string); + const std::string only_install_string = Strings::join("\n", only_install_plans, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname()); + }); + if (only_install_plans.size() > 0) + System::println("The following packages will be directly installed:\n%s", only_install_string); + + if (has_non_user_requested_packages) + System::println("Additional packages (*) will be installed to complete this operation."); + + if (remove_plans.size() > 0 && !is_recursive) + { + System::println(System::Color::warning, + "If you are sure you want to rebuild the above packages, run the command with the " + "--recurse option"); + Checks::exit_fail(VCPKG_LINE_INFO); + } } void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) @@ -410,86 +430,81 @@ namespace vcpkg::Commands::Install Commands::Help::create_example_string("install zlib zlib:x64-windows curl boost"); args.check_min_arg_count(1, example); - const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, example); + const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + return Input::check_and_get_full_package_spec(arg, default_triplet, example); }); + for (auto&& spec : specs) - Input::check_triplet(spec.triplet(), paths); + { + Input::check_triplet(spec.package_spec.triplet(), paths); + if (!spec.features.empty() && !g_feature_packages) + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "Feature packages are experimentally available under the --featurepackages flag."); + } + } const std::unordered_set options = args.check_and_get_optional_command_arguments( {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE}); const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend(); const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend(); const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); - const bool isRecursive = options.find(OPTION_RECURSE) != options.cend(); + const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); // create the plan StatusParagraphs status_db = database_load_check(paths); + const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), + Build::to_allow_downloads(!no_downloads)}; + + std::vector action_plan; + if (g_feature_packages) { - const std::vector full_specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_full_package_spec(arg, default_triplet, example); - }); - - std::unordered_map scf_map; + std::unordered_map scf_map; auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); for (auto&& port : all_ports.paragraphs) { - auto pkg_spec = PackageSpec::from_name_and_triplet(port->core_paragraph->name, default_triplet) - .value_or_exit(VCPKG_LINE_INFO); - scf_map[pkg_spec] = std::move(*port); + scf_map[port->core_paragraph->name] = std::move(*port); } - std::vector action_plan = Dependencies::create_feature_install_plan( - scf_map, FullPackageSpec::to_feature_specs(full_specs), status_db); - // install plan will be empty if it is already installed - need to change this at status paragraph part - Checks::check_exit( - VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty for feature packages"); - - const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), - Build::to_allow_downloads(!no_downloads)}; + action_plan = create_feature_install_plan(scf_map, FullPackageSpec::to_feature_specs(specs), status_db); + } + else + { + Dependencies::PathsPortFile paths_port_file(paths); + auto install_plan = Dependencies::create_install_plan( + paths_port_file, Util::fmap(specs, [](auto&& spec) { return spec.package_spec; }), status_db); - std::vector remove_plans; + action_plan = Util::fmap( + install_plan, [](InstallPlanAction& install_action) { return AnyAction(std::move(install_action)); }); + } - std::vector rebuilt_plans; - std::vector new_plans; + // install plan will be empty if it is already installed - need to change this at status paragraph part + Checks::check_exit(VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty"); - // removal will happen before install - for (auto&& action : action_plan) - { - if (auto install_action = action.install_plan.get()) - { - auto it = Util::find_if( - remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); - if (it != remove_plans.end()) - { - rebuilt_plans.emplace_back(install_action); - } - else - { - new_plans.emplace_back(install_action); - } - } - else if (auto remove_action = action.remove_plan.get()) - { - remove_plans.emplace_back(remove_action); - } - } + // log the plan + const std::string specs_string = Strings::join(",", action_plan, [](const AnyAction& action) { + if (auto iaction = action.install_plan.get()) + return iaction->spec.to_string(); + else if (auto raction = action.remove_plan.get()) + return "R$" + raction->spec.to_string(); + Checks::unreachable(VCPKG_LINE_INFO); + }); + Metrics::track_property("installplan", specs_string); - print_plan(rebuilt_plans, new_plans); + print_plan(action_plan, is_recursive); - if (remove_plans.size() > 0 && !isRecursive) - { - System::println(System::Color::warning, - "If you are sure you want to rebuild the above packages, run the command with the " - "--recurse option"); - Checks::exit_fail(VCPKG_LINE_INFO); - } + if (dryRun) + { + Checks::exit_success(VCPKG_LINE_INFO); + } - // execute the plan - for (const Dependencies::AnyAction& any_action : action_plan) + // execute the plan + if (g_feature_packages) + { + for (const auto& action : action_plan) { - if (auto install_action = any_action.install_plan.get()) + if (auto install_action = action.install_plan.get()) { const BuildResult result = perform_install_plan_action(paths, *install_action, install_plan_options, status_db); @@ -499,7 +514,7 @@ namespace vcpkg::Commands::Install Checks::exit_fail(VCPKG_LINE_INFO); } } - else if (auto remove_action = any_action.remove_plan.get()) + else if (auto remove_action = action.remove_plan.get()) { static const std::string OPTION_PURGE = "--purge"; static const std::string OPTION_NO_PURGE = "--no-purge"; @@ -537,50 +552,18 @@ namespace vcpkg::Commands::Install } } } - - Checks::exit_success(VCPKG_LINE_INFO); - } - - Dependencies::PathsPortFile paths_port_file(paths); - std::vector install_plan = - Dependencies::create_install_plan(paths_port_file, specs, status_db); - Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); - - // log the plan - const std::string specs_string = - Strings::join(",", install_plan, [](const InstallPlanAction& plan) { return plan.spec.to_string(); }); - Metrics::track_property("installplan", specs_string); - - std::map> group_by_plan_type; - Util::group_by(install_plan, &group_by_plan_type, [](const InstallPlanAction& p) { return p.plan_type; }); - print_plan(group_by_plan_type); - - const bool has_non_user_requested_packages = - Util::find_if(install_plan, [](const InstallPlanAction& package) -> bool { - return package.request_type != RequestType::USER_REQUESTED; - }) != install_plan.cend(); - - if (has_non_user_requested_packages) - { - System::println("Additional packages (*) will be installed to complete this operation."); } - - if (dryRun) + else { - Checks::exit_success(VCPKG_LINE_INFO); - } - - const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), - Build::to_allow_downloads(!no_downloads)}; - - // execute the plan - for (const InstallPlanAction& action : install_plan) - { - const BuildResult result = perform_install_plan_action(paths, action, install_plan_options, status_db); - if (result != BuildResult::SUCCEEDED) + for (const auto& action : action_plan) { - System::println(Build::create_user_troubleshooting_message(action.spec)); - Checks::exit_fail(VCPKG_LINE_INFO); + const auto& iaction = action.install_plan.value_or_exit(VCPKG_LINE_INFO); + const BuildResult result = perform_install_plan_action(paths, iaction, install_plan_options, status_db); + if (result != BuildResult::SUCCEEDED) + { + System::println(Build::create_user_troubleshooting_message(iaction.spec)); + Checks::exit_fail(VCPKG_LINE_INFO); + } } } diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index f0884c063..939351872 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -12,7 +12,7 @@ namespace UnitTest1 { struct PackageSpecMap { - std::unordered_map map; + std::unordered_map map; Triplet triplet; PackageSpecMap(const Triplet& t) { triplet = t; } @@ -24,7 +24,7 @@ namespace UnitTest1 auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, triplet); Assert::IsTrue(spec.has_value()); - map.emplace(*spec.get(), std::move(*scf.get())); + map.emplace(scf->core_paragraph->name, std::move(*scf.get())); return PackageSpec{*spec.get()}; } PackageSpec set_package_map(std::string source, std::string version, std::string build_depends) diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 8f92179b5..abab359bb 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -63,24 +63,51 @@ namespace vcpkg::Dependencies struct ClusterGraph { - explicit ClusterGraph(std::unordered_map&& graph) : m_graph(std::move(graph)) {} + explicit ClusterGraph(std::unordered_map&& ports) + : m_ports(std::move(ports)) + { + } ClusterGraph(ClusterGraph&&) = default; Cluster& get(const PackageSpec& spec) - { - if (auto p = try_get(spec)) return *p; - Checks::exit_with_message(VCPKG_LINE_INFO, "error: reference to missing package: %s", spec); - } - Cluster* try_get(const PackageSpec& spec) { auto it = m_graph.find(spec); - if (it == m_graph.end()) return nullptr; - return &it->second; + if (it == m_graph.end()) + { + // Load on-demand from m_ports + auto it_ports = m_ports.find(spec.name()); + if (it_ports != m_ports.end()) + { + auto& clust = m_graph[spec]; + clust.spec = spec; + cluster_from_scf(*it_ports->second, clust); + return clust; + } + return m_graph[spec]; + } + return it->second; } private: + void cluster_from_scf(const SourceControlFile& scf, Cluster& out_cluster) + { + FeatureNodeEdges core_dependencies; + core_dependencies.build_edges = + filter_dependencies_to_specs(scf.core_paragraph->depends, out_cluster.spec.triplet()); + out_cluster.edges.emplace("core", std::move(core_dependencies)); + + for (const auto& feature : scf.feature_paragraphs) + { + FeatureNodeEdges added_edges; + added_edges.build_edges = filter_dependencies_to_specs(feature->depends, out_cluster.spec.triplet()); + out_cluster.edges.emplace(feature->name, std::move(added_edges)); + } + out_cluster.source_control_file = &scf; + } + ClusterGraph(const ClusterGraph&) = delete; std::unordered_map m_graph; + std::unordered_map m_ports; }; std::vector AnyParagraph::dependencies(const Triplet& triplet) const @@ -243,9 +270,9 @@ namespace vcpkg::Dependencies return left->spec.name() < right->spec.name(); } - MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map) {} + MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map) {} - const SourceControlFile& MapPortFile::get_control_file(const PackageSpec& spec) const + const SourceControlFile& MapPortFile::get_control_file(const std::string& spec) const { auto scf = ports.find(spec); if (scf == ports.end()) @@ -257,9 +284,9 @@ namespace vcpkg::Dependencies PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths) {} - const SourceControlFile& PathsPortFile::get_control_file(const PackageSpec& spec) const + const SourceControlFile& PathsPortFile::get_control_file(const std::string& spec) const { - std::unordered_map::iterator cache_it = cache.find(spec); + auto cache_it = cache.find(spec); if (cache_it != cache.end()) { return cache_it->second; @@ -307,7 +334,9 @@ namespace vcpkg::Dependencies auto it = status_db.find_installed(spec); if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type}; return InstallPlanAction{ - spec, {nullopt, nullopt, *port_file_provider.get_control_file(spec).core_paragraph}, request_type}; + spec, + {nullopt, nullopt, *port_file_provider.get_control_file(spec.name()).core_paragraph}, + request_type}; } }; @@ -504,35 +533,19 @@ namespace vcpkg::Dependencies } } - static ClusterGraph create_feature_install_graph(const std::unordered_map& map, + static ClusterGraph create_feature_install_graph(const std::unordered_map& map, const StatusParagraphs& status_db) { - std::unordered_map graph; - - for (const auto& it : map) - { - Cluster& node = graph[it.first]; - - node.spec = it.first; - FeatureNodeEdges core_dependencies; - core_dependencies.build_edges = - filter_dependencies_to_specs(it.second.core_paragraph->depends, node.spec.triplet()); - node.edges.emplace("core", std::move(core_dependencies)); - - for (const auto& feature : it.second.feature_paragraphs) - { - FeatureNodeEdges added_edges; - added_edges.build_edges = filter_dependencies_to_specs(feature->depends, node.spec.triplet()); - node.edges.emplace(feature->name, std::move(added_edges)); - } - node.source_control_file = &it.second; - } + std::unordered_map ptr_map; + for (auto&& p : map) + ptr_map.emplace(p.first, &p.second); + ClusterGraph graph(std::move(ptr_map)); auto installed_ports = get_installed_ports(status_db); for (auto&& status_paragraph : installed_ports) { - Cluster& cluster = graph[status_paragraph->package.spec]; + Cluster& cluster = graph.get(status_paragraph->package.spec); cluster.transient_uninstalled = false; @@ -559,20 +572,19 @@ namespace vcpkg::Dependencies for (auto&& dependency : reverse_edges) { - auto dep_cluster = graph.find(dependency.spec()); - if (dep_cluster == graph.end()) Checks::unreachable(VCPKG_LINE_INFO); + auto& dep_cluster = graph.get(dependency.spec()); auto depends_name = dependency.feature(); if (depends_name == "") depends_name = "core"; - auto& target_node = dep_cluster->second.edges[depends_name]; + auto& target_node = dep_cluster.edges[depends_name]; target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); } } - return ClusterGraph(std::move(graph)); + return graph; } - std::vector create_feature_install_plan(const std::unordered_map& map, + std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db) { @@ -598,15 +610,13 @@ namespace vcpkg::Dependencies for (auto&& like_cluster : remove_toposort) { auto scf = *like_cluster.ptr->source_control_file.get(); - - AnyAction any_plan; - any_plan.remove_plan = RemovePlanAction{ - PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) - .value_or_exit(VCPKG_LINE_INFO), + auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) + .value_or_exit(VCPKG_LINE_INFO); + install_plan.emplace_back(RemovePlanAction{ + std::move(spec), RemovePlanType::REMOVE, - RequestType::AUTO_SELECTED}; - - install_plan.emplace_back(std::move(any_plan)); + RequestType::AUTO_SELECTED, + }); } for (auto&& like_cluster : insert_toposort) @@ -617,12 +627,12 @@ namespace vcpkg::Dependencies auto pkg_spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) .value_or_exit(VCPKG_LINE_INFO); - auto action = - InstallPlanAction{pkg_spec, *scf, like_cluster.ptr->to_install_features, RequestType::AUTO_SELECTED}; - - AnyAction any_plan; - any_plan.install_plan = std::move(action); - install_plan.emplace_back(std::move(any_plan)); + install_plan.emplace_back(InstallPlanAction{ + pkg_spec, + *scf, + like_cluster.ptr->to_install_features, + RequestType::AUTO_SELECTED, + }); } return install_plan; -- cgit v1.2.3 From c0fdbfb2e813a9decd18b5f8373f09c85756d1c0 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 21 Aug 2017 17:19:40 -0700 Subject: Fix detection of 64-bit VSCode --- toolsrc/src/commands_edit.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index 4e83fcca8..12ddaad77 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -30,6 +30,15 @@ namespace vcpkg::Commands::Edit } } + if (env_EDITOR.empty()) + { + const fs::path CODE_EXE_PATH = System::get_ProgramFiles_platform_bitness() / "Microsoft VS Code/Code.exe"; + if (fs.exists(CODE_EXE_PATH)) + { + env_EDITOR = CODE_EXE_PATH; + } + } + if (env_EDITOR.empty()) { const fs::path CODE_EXE_PATH = System::get_ProgramFiles_32_bit() / "Microsoft VS Code/Code.exe"; -- cgit v1.2.3 From d708484077ef891c5a69e4d9211613dbcfacb91e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 21 Aug 2017 20:06:47 -0700 Subject: [vcpkg] Feature packages now include user requested packages even if they are already installed. --- toolsrc/src/test_install_plan.cpp | 82 ++++++++++++++++++++++++++++++++++++++ toolsrc/src/vcpkg_Dependencies.cpp | 81 ++++++++++++++++++++----------------- 2 files changed, 127 insertions(+), 36 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 939351872..d7a5014a9 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -6,6 +6,34 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace vcpkg; +namespace Microsoft::VisualStudio::CppUnitTestFramework +{ + template<> + inline std::wstring ToString(const vcpkg::Dependencies::InstallPlanType& t) + { + switch (t) + { + case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; + case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; + case Dependencies::InstallPlanType::INSTALL: return L"INSTALL"; + case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; + default: return ToString((int)t); + } + } + + template<> + inline std::wstring ToString(const vcpkg::Dependencies::RequestType& t) + { + switch (t) + { + case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED"; + case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED"; + case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN"; + default: return ToString((int)t); + } + } +} + namespace UnitTest1 { class InstallPlanTests : public TestClass @@ -127,6 +155,60 @@ namespace UnitTest1 Assert::IsTrue(e_pos > g_pos); } + TEST_METHOD(existing_package_scheme) + { + using Pgh = std::unordered_map; + std::vector> status_paragraphs; + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, + {"Version", "1"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Status", "install ok installed"}})); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.set_package_map("a", "1", ""), {""}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(1), install_plan.size()); + auto p = install_plan[0].install_plan.get(); + Assert::IsNotNull(p); + Assert::AreEqual("a", p->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type); + Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p->request_type); + } + + TEST_METHOD(user_requested_package_scheme) + { + using Pgh = std::unordered_map; + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.set_package_map("a", "1", "b"), {""}}; + auto spec_b = FullPackageSpec{spec_map.set_package_map("b", "1", ""), {""}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(2), install_plan.size()); + auto p = install_plan[0].install_plan.get(); + Assert::IsNotNull(p); + Assert::AreEqual("b", p->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type); + Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type); + + auto p2 = install_plan[1].install_plan.get(); + Assert::IsNotNull(p2); + Assert::AreEqual("a", p2->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type); + Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p2->request_type); + } + TEST_METHOD(long_install_scheme) { using Pgh = std::unordered_map; diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index abab359bb..8741e520f 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -29,6 +29,7 @@ namespace vcpkg::Dependencies std::unordered_set original_features; bool will_remove = false; bool transient_uninstalled = true; + RequestType request_type = RequestType::AUTO_SELECTED; Cluster() = default; private: @@ -39,6 +40,8 @@ namespace vcpkg::Dependencies struct ClusterPtr { Cluster* ptr; + + Cluster* operator->() { return ptr; } }; bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } @@ -147,50 +150,44 @@ namespace vcpkg::Dependencies } } - InstallPlanAction::InstallPlanAction() - : spec(), any_paragraph(), plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) - { - } + InstallPlanAction::InstallPlanAction() : plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const SourceControlFile& any_paragraph, const std::unordered_set& features, const RequestType& request_type) - : InstallPlanAction() + : spec(spec), plan_type(InstallPlanType::BUILD_AND_INSTALL), request_type(request_type), feature_list(features) { - this->spec = spec; - this->request_type = request_type; - - this->plan_type = InstallPlanType::BUILD_AND_INSTALL; this->any_paragraph.source_control_file = &any_paragraph; - this->feature_list = features; + } + + InstallPlanAction::InstallPlanAction(const PackageSpec& spec, + const std::unordered_set& features, + const RequestType& request_type) + : spec(spec), plan_type(InstallPlanType::ALREADY_INSTALLED), request_type(request_type), feature_list(features) + { } InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const AnyParagraph& any_paragraph, const RequestType& request_type) - : InstallPlanAction() + : spec(spec), request_type(request_type), any_paragraph(any_paragraph) { - this->spec = spec; - this->request_type = request_type; if (auto p = any_paragraph.status_paragraph.get()) { this->plan_type = InstallPlanType::ALREADY_INSTALLED; - this->any_paragraph.status_paragraph = *p; return; } if (auto p = any_paragraph.binary_paragraph.get()) { this->plan_type = InstallPlanType::INSTALL; - this->any_paragraph.binary_paragraph = *p; return; } if (auto p = any_paragraph.source_paragraph.get()) { this->plan_type = InstallPlanType::BUILD_AND_INSTALL; - this->any_paragraph.source_paragraph = *p; return; } @@ -594,7 +591,9 @@ namespace vcpkg::Dependencies for (auto&& spec : specs) { Cluster& spec_cluster = graph.get(spec.spec()); + spec_cluster.request_type = RequestType::USER_REQUESTED; mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster}); } Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); @@ -605,36 +604,46 @@ namespace vcpkg::Dependencies auto insert_vertex_list = graph_plan.install_graph.vertex_list(); auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph); - std::vector install_plan; + std::vector plan; - for (auto&& like_cluster : remove_toposort) + for (auto&& p_cluster : remove_toposort) { - auto scf = *like_cluster.ptr->source_control_file.get(); - auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) + auto scf = *p_cluster->source_control_file.get(); + auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, p_cluster->spec.triplet()) .value_or_exit(VCPKG_LINE_INFO); - install_plan.emplace_back(RemovePlanAction{ + plan.emplace_back(RemovePlanAction{ std::move(spec), RemovePlanType::REMOVE, - RequestType::AUTO_SELECTED, + p_cluster->request_type, }); } - for (auto&& like_cluster : insert_toposort) + for (auto&& p_cluster : insert_toposort) { - if (!like_cluster.ptr->transient_uninstalled) continue; - - auto scf = *like_cluster.ptr->source_control_file.get(); - auto pkg_spec = - PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) - .value_or_exit(VCPKG_LINE_INFO); - install_plan.emplace_back(InstallPlanAction{ - pkg_spec, - *scf, - like_cluster.ptr->to_install_features, - RequestType::AUTO_SELECTED, - }); + if (p_cluster->transient_uninstalled) + { + // If it will be transiently uninstalled, we need to issue a full installation command + auto pscf = p_cluster->source_control_file.value_or_exit(VCPKG_LINE_INFO); + Checks::check_exit(VCPKG_LINE_INFO, pscf != nullptr); + plan.emplace_back(InstallPlanAction{ + p_cluster->spec, + *pscf, + p_cluster->to_install_features, + p_cluster->request_type, + }); + } + else + { + // If the package isn't transitively installed, still include it if the user explicitly requested it + if (p_cluster->request_type != RequestType::USER_REQUESTED) continue; + plan.emplace_back(InstallPlanAction{ + p_cluster->spec, + p_cluster->original_features, + p_cluster->request_type, + }); + } } - return install_plan; + return plan; } } -- cgit v1.2.3 From 6784704638f46d89d01458b1004e588f535958aa Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 21 Aug 2017 21:08:43 -0700 Subject: [vcpkg] Improve error messages when a feature is requested that doesn't exist. --- toolsrc/src/PackageSpec.cpp | 12 +++++++-- toolsrc/src/test_install_plan.cpp | 6 ++--- toolsrc/src/vcpkg_Dependencies.cpp | 53 +++++++++++++++++++++++++++++--------- 3 files changed, 54 insertions(+), 17 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index a5d40e998..a43bc5ff5 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -13,6 +13,12 @@ namespace vcpkg return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)) || (c == '[') || (c == ']'); } + std::string FeatureSpec::to_string() const + { + if (feature().empty()) return spec().to_string(); + return Strings::format("%s[%s]:%s", name(), feature(), triplet()); + } + std::vector FeatureSpec::from_strings_and_triplet(const std::vector& depends, const Triplet& triplet) { @@ -36,8 +42,10 @@ namespace vcpkg } else { - Checks::exit_with_message( - VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), depend); + Checks::exit_with_message(VCPKG_LINE_INFO, + "error while parsing feature list: %s: %s", + vcpkg::to_string(maybe_spec.error()), + depend); } } return f_specs; diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index d7a5014a9..1c415f273 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -537,9 +537,9 @@ namespace UnitTest1 remove_plan_check(&install_plan[1], "b"); // TODO: order here may change but A < X, and B anywhere - features_check(&install_plan[2], "a", {"core"}); - features_check(&install_plan[3], "x", {"core"}); - features_check(&install_plan[4], "b", {"core", "1"}); + features_check(&install_plan[2], "b", {"core", "1"}); + features_check(&install_plan[3], "a", {"core"}); + features_check(&install_plan[4], "x", {"core"}); } TEST_METHOD(basic_feature_test_8) diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 8741e520f..512e65e28 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -453,23 +453,30 @@ namespace vcpkg::Dependencies return toposort; } - void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + enum class MarkPlusResult + { + FEATURE_NOT_FOUND, + SUCCESS, + }; + + MarkPlusResult mark_plus(const std::string& feature, + Cluster& cluster, + ClusterGraph& pkg_to_cluster, + GraphPlan& graph_plan); void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); - void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) + MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { if (feature == "") { // Indicates that core was not specified in the reference return mark_plus("core", cluster, graph, graph_plan); } + auto it = cluster.edges.find(feature); - if (it == cluster.edges.end()) - { - Checks::unreachable(VCPKG_LINE_INFO); - } + if (it == cluster.edges.end()) return MarkPlusResult::FEATURE_NOT_FOUND; - if (cluster.edges[feature].plus) return; + if (cluster.edges[feature].plus) return MarkPlusResult::SUCCESS; if (cluster.original_features.find(feature) == cluster.original_features.end()) { @@ -478,7 +485,7 @@ namespace vcpkg::Dependencies if (!cluster.transient_uninstalled) { - return; + return MarkPlusResult::SUCCESS; } cluster.edges[feature].plus = true; @@ -494,16 +501,28 @@ namespace vcpkg::Dependencies if (feature != "core") { // All features implicitly depend on core - mark_plus("core", cluster, graph, graph_plan); + auto res = mark_plus("core", cluster, graph, graph_plan); + + // Should be impossible for "core" to not exist + Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS); } for (auto&& depend : cluster.edges[feature].build_edges) { auto& depend_cluster = graph.get(depend.spec()); - mark_plus(depend.feature(), depend_cluster, graph, graph_plan); + auto res = mark_plus(depend.feature(), depend_cluster, graph, graph_plan); + + Checks::check_exit(VCPKG_LINE_INFO, + res == MarkPlusResult::SUCCESS, + "Error: Unable to satisfy dependency %s of %s", + depend, + FeatureSpec(cluster.spec, feature)); + if (&depend_cluster == &cluster) continue; graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); } + + return MarkPlusResult::SUCCESS; } void mark_minus(Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) @@ -526,7 +545,13 @@ namespace vcpkg::Dependencies cluster.transient_uninstalled = true; for (auto&& original_feature : cluster.original_features) { - mark_plus(original_feature, cluster, graph, graph_plan); + auto res = mark_plus(original_feature, cluster, graph, graph_plan); + if (res != MarkPlusResult::SUCCESS) + { + System::println(System::Color::warning, + "Warning: could not reinstall feature %s", + FeatureSpec{cluster.spec, original_feature}); + } } } @@ -592,7 +617,11 @@ namespace vcpkg::Dependencies { Cluster& spec_cluster = graph.get(spec.spec()); spec_cluster.request_type = RequestType::USER_REQUESTED; - mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + auto res = mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + + Checks::check_exit( + VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); + graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster}); } -- cgit v1.2.3 From bee29497f9e210c2b8d33edccba0d1d95188d852 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 22 Aug 2017 15:03:42 -0700 Subject: [vcpkg] Compact tests for improved maintainability. --- toolsrc/src/test_install_plan.cpp | 421 +++++++++++++------------------------- 1 file changed, 142 insertions(+), 279 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 1c415f273..836ff09ae 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -38,28 +38,30 @@ namespace UnitTest1 { class InstallPlanTests : public TestClass { - struct PackageSpecMap + static std::unique_ptr make_control_file( + const char* name, + const char* depends, + const std::vector>& features = {}) { - std::unordered_map map; - Triplet triplet; - PackageSpecMap(const Triplet& t) { triplet = t; } - - PackageSpec get_package_spec(std::vector>&& fields) - { - auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(fields)); - Assert::IsTrue(m_pgh.has_value()); - auto& scf = *m_pgh.get(); - - auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, triplet); - Assert::IsTrue(spec.has_value()); - map.emplace(scf->core_paragraph->name, std::move(*scf.get())); - return PackageSpec{*spec.get()}; - } - PackageSpec set_package_map(std::string source, std::string version, std::string build_depends) + using Pgh = std::unordered_map; + std::vector scf_pghs; + scf_pghs.push_back(Pgh{ + {"Source", name}, + {"Version", "0"}, + {"Build-Depends", depends}, + }); + for (auto&& feature : features) { - return get_package_spec({{{"Source", source}, {"Version", version}, {"Build-Depends", build_depends}}}); + scf_pghs.push_back(Pgh{ + {"Feature", feature.first}, + {"Description", "feature"}, + {"Build-Depends", feature.second}, + }); } - }; + auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(scf_pghs)); + Assert::IsTrue(m_pgh.has_value()); + return std::move(*m_pgh.get()); + } static void features_check(Dependencies::AnyAction* install_action, std::string pkg_name, @@ -96,14 +98,58 @@ namespace UnitTest1 Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); } + static std::unique_ptr make_status_pgh(const char* name, const char* depends = "") + { + using Pgh = std::unordered_map; + return std::make_unique(Pgh{{"Package", name}, + {"Version", "1"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Status", "install ok installed"}}); + } + static std::unique_ptr make_status_feature_pgh(const char* name, + const char* feature, + const char* depends = "") + { + using Pgh = std::unordered_map; + return std::make_unique(Pgh{{"Package", name}, + {"Version", "1"}, + {"Feature", feature}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Status", "install ok installed"}}); + } + struct PackageSpecMap + { + std::unordered_map map; + Triplet triplet; + PackageSpecMap(const Triplet& t) { triplet = t; } + + PackageSpec emplace(const char* name, + const char* depends = "", + const std::vector>& features = {}) + { + return emplace(std::move(*make_control_file(name, depends, features))); + } + PackageSpec emplace(vcpkg::SourceControlFile&& scf) + { + auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph->name, triplet); + Assert::IsTrue(spec.has_value()); + map.emplace(scf.core_paragraph->name, std::move(scf)); + return PackageSpec{*spec.get()}; + } + }; + TEST_METHOD(basic_install_scheme) { std::vector> status_paragraphs; PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.set_package_map("a", "1.2.8", "b"); - auto spec_b = spec_map.set_package_map("b", "1.3", "c"); - auto spec_c = spec_map.set_package_map("c", "2.5.3", ""); + auto spec_a = spec_map.emplace("a", "b"); + auto spec_b = spec_map.emplace("b", "c"); + auto spec_c = spec_map.emplace("c"); auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = @@ -120,14 +166,14 @@ namespace UnitTest1 std::vector> status_paragraphs; PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.set_package_map("a", "1.2.8", "d"); - auto spec_b = spec_map.set_package_map("b", "1.3", "d, e"); - auto spec_c = spec_map.set_package_map("c", "2.5.3", "e, h"); - auto spec_d = spec_map.set_package_map("d", "4.0", "f, g, h"); - auto spec_e = spec_map.set_package_map("e", "1.0", "g"); - auto spec_f = spec_map.set_package_map("f", "1.0", ""); - auto spec_g = spec_map.set_package_map("g", "1.0", ""); - auto spec_h = spec_map.set_package_map("h", "1.0", ""); + auto spec_a = spec_map.emplace("a", "d"); + auto spec_b = spec_map.emplace("b", "d, e"); + auto spec_c = spec_map.emplace("c", "e, h"); + auto spec_d = spec_map.emplace("d", "f, g, h"); + auto spec_e = spec_map.emplace("e", "g"); + auto spec_f = spec_map.emplace("f"); + auto spec_g = spec_map.emplace("g"); + auto spec_h = spec_map.emplace("h"); auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = Dependencies::create_install_plan( @@ -157,16 +203,11 @@ namespace UnitTest1 TEST_METHOD(existing_package_scheme) { - using Pgh = std::unordered_map; std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Version", "1"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("a")); PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.set_package_map("a", "1", ""), {""}}; + auto spec_a = FullPackageSpec{spec_map.emplace("a")}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -183,12 +224,11 @@ namespace UnitTest1 TEST_METHOD(user_requested_package_scheme) { - using Pgh = std::unordered_map; std::vector> status_paragraphs; PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.set_package_map("a", "1", "b"), {""}}; - auto spec_b = FullPackageSpec{spec_map.set_package_map("b", "1", ""), {""}}; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b")}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -211,33 +251,22 @@ namespace UnitTest1 TEST_METHOD(long_install_scheme) { - using Pgh = std::unordered_map; std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "j"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "k"}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "k"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("j", "k")); + status_paragraphs.push_back(make_status_pgh("k")); PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.set_package_map("a", "1.2.8", "b, c, d, e, f, g, h, j, k"); - auto spec_b = spec_map.set_package_map("b", "1.2.8", "c, d, e, f, g, h, j, k"); - auto spec_c = spec_map.set_package_map("c", "1.2.8", "d, e, f, g, h, j, k"); - auto spec_d = spec_map.set_package_map("d", "1.2.8", "e, f, g, h, j, k"); - auto spec_e = spec_map.set_package_map("e", "1.2.8", "f, g, h, j, k"); - auto spec_f = spec_map.set_package_map("f", "1.2.8", "g, h, j, k"); - auto spec_g = spec_map.set_package_map("g", "1.2.8", "h, j, k"); - auto spec_h = spec_map.set_package_map("h", "1.2.8", "j, k"); - auto spec_j = spec_map.set_package_map("j", "1.2.8", "k"); - auto spec_k = spec_map.set_package_map("k", "1.2.8", ""); + auto spec_a = spec_map.emplace("a", "b, c, d, e, f, g, h, j, k"); + auto spec_b = spec_map.emplace("b", "c, d, e, f, g, h, j, k"); + auto spec_c = spec_map.emplace("c", "d, e, f, g, h, j, k"); + auto spec_d = spec_map.emplace("d", "e, f, g, h, j, k"); + auto spec_e = spec_map.emplace("e", "f, g, h, j, k"); + auto spec_f = spec_map.emplace("f", "g, h, j, k"); + auto spec_g = spec_map.emplace("g", "h, j, k"); + auto spec_h = spec_map.emplace("h", "j, k"); + auto spec_j = spec_map.emplace("j", "k"); + auto spec_k = spec_map.emplace("k"); auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = @@ -256,45 +285,14 @@ namespace UnitTest1 TEST_METHOD(basic_feature_test_1) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Default-Features", ""}, - {"Version", "1.3.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "b, b[beefeatureone]"}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, - {"Feature", "beefeatureone"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, - {"Default-Features", "beefeatureone"}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("a", "b, b[b1]")); + status_paragraphs.push_back(make_status_pgh("b")); + status_paragraphs.push_back(make_status_feature_pgh("b", "b1")); PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = - FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b, b[beefeatureone]"}}, - {{"Feature", "featureone"}, - {"Description", "the first feature for a"}, - {"Build-Depends", "b[beefeaturetwo]"}}, - }), - {"featureone"}}; - auto spec_b = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}}, - })}; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -304,33 +302,18 @@ namespace UnitTest1 Assert::AreEqual(size_t(4), install_plan.size()); remove_plan_check(&install_plan[0], "a"); remove_plan_check(&install_plan[1], "b"); - features_check(&install_plan[2], "b", {"beefeatureone", "core", "beefeatureone"}); - features_check(&install_plan[3], "a", {"featureone", "core"}); + features_check(&install_plan[2], "b", {"b1", "core", "b1"}); + features_check(&install_plan[3], "a", {"a1", "core"}); } TEST_METHOD(basic_feature_test_2) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = - FullPackageSpec{spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b[beefeatureone]"}}, - {{"Feature", "featureone"}, - {"Description", "the first feature for a"}, - {"Build-Depends", "b[beefeaturetwo]"}} - - }), - {"featureone"}}; - auto spec_b = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}}, - })}; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -338,37 +321,20 @@ namespace UnitTest1 StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(2), install_plan.size()); - features_check(&install_plan[0], "b", {"beefeatureone", "beefeaturetwo", "core"}); - features_check(&install_plan[1], "a", {"featureone", "core"}); + features_check(&install_plan[0], "b", {"b1", "b2", "core"}); + features_check(&install_plan[1], "a", {"a1", "core"}); } TEST_METHOD(basic_feature_test_3) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("a")); PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, - {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), - {"core"}}; - auto spec_b = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - })}; - auto spec_c = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, - }), - {"core"}}; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -378,43 +344,21 @@ namespace UnitTest1 Assert::AreEqual(size_t(4), install_plan.size()); remove_plan_check(&install_plan[0], "a"); features_check(&install_plan[1], "b", {"core"}); - features_check(&install_plan[2], "a", {"one", "core"}); + features_check(&install_plan[2], "a", {"a1", "core"}); features_check(&install_plan[3], "c", {"core"}); } TEST_METHOD(basic_feature_test_4) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Feature", "one"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.push_back(make_status_feature_pgh("a", "a1", "")); PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, - {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), - }; - auto spec_b = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - })}; - auto spec_c = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, - }), - {"core"}}; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}})}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -427,24 +371,13 @@ namespace UnitTest1 TEST_METHOD(basic_feature_test_5) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[1]"}}, - {{"Feature", "2"}, {"Description", "the second feature for a"}, {"Build-Depends", "b[2]"}}, - {{"Feature", "3"}, {"Description", "the third feature for a"}, {"Build-Depends", "a[2]"}}}), - {"3"}}; - auto spec_b = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, - })}; + auto spec_a = + FullPackageSpec{spec_map.emplace("a", "", {{"a1", "b[b1]"}, {"a2", "b[b2]"}, {"a3", "a[a2]"}}), {"a3"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}})}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -452,34 +385,18 @@ namespace UnitTest1 StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(2), install_plan.size()); - features_check(&install_plan[0], "b", {"core", "2"}); - features_check(&install_plan[1], "a", {"core", "3", "2"}); + features_check(&install_plan[0], "b", {"core", "b2"}); + features_check(&install_plan[1], "a", {"core", "a3", "a2"}); } TEST_METHOD(basic_feature_test_6) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + status_paragraphs.push_back(make_status_pgh("b")); - auto spec_a = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b[core]"}}, - }), - {"core"}}; - auto spec_b = FullPackageSpec{ - spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, - }), - {"1"}}; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[core]"), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -488,44 +405,21 @@ namespace UnitTest1 Assert::AreEqual(size_t(3), install_plan.size()); remove_plan_check(&install_plan[0], "b"); - features_check(&install_plan[1], "b", {"core", "1"}); + features_check(&install_plan[1], "b", {"core", "b1"}); features_check(&install_plan[2], "a", {"core"}); } TEST_METHOD(basic_feature_test_7) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "x"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "b"}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("x", "b")); + status_paragraphs.push_back(make_status_pgh("b")); + PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - })}; - auto spec_x = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "x"}, {"Version", "1.3"}, {"Build-Depends", "a"}}, - }), - {"core"}}; - auto spec_b = FullPackageSpec{ - spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}, {"Default-Features", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, - }), - {"1"}}; + auto spec_a = FullPackageSpec{spec_map.emplace("a")}; + auto spec_x = FullPackageSpec{spec_map.emplace("x", "a"), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -537,59 +431,28 @@ namespace UnitTest1 remove_plan_check(&install_plan[1], "b"); // TODO: order here may change but A < X, and B anywhere - features_check(&install_plan[2], "b", {"core", "1"}); + features_check(&install_plan[2], "b", {"core", "b1"}); features_check(&install_plan[3], "a", {"core"}); features_check(&install_plan[4], "x", {"core"}); } TEST_METHOD(basic_feature_test_8) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x64-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.spec = + PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); PackageSpecMap spec_map(Triplet::X64_WINDOWS); - - auto spec_a_64 = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, - {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), - {"core"}}; - auto spec_b_64 = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - })}; - auto spec_c_64 = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, - }), - {"core"}}; + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; spec_map.triplet = Triplet::X86_WINDOWS; - auto spec_a_86 = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, - {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), - {"core"}}; - auto spec_b_86 = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - })}; - auto spec_c_86 = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, - }), - {"core"}}; + auto spec_a_86 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b_86 = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c_86 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; auto install_plan = Dependencies::create_feature_install_plan( spec_map.map, @@ -613,10 +476,10 @@ namespace UnitTest1 remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); remove_plan_check(&install_plan[1], "a"); features_check(&install_plan[2], "b", {"core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[3], "a", {"one", "core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[3], "a", {"a1", "core"}, Triplet::X64_WINDOWS); features_check(&install_plan[4], "c", {"core"}, Triplet::X64_WINDOWS); features_check(&install_plan[5], "b", {"core"}); - features_check(&install_plan[6], "a", {"one", "core"}); + features_check(&install_plan[6], "a", {"a1", "core"}); features_check(&install_plan[7], "c", {"core"}); } }; -- cgit v1.2.3 From 92dd1b77ed043da376c86874aacc1233270fedae Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 22 Aug 2017 15:14:15 -0700 Subject: [vcpkg] Add Util::ResourceBase, use MoveOnlyBase --- toolsrc/src/test_install_plan.cpp | 6 +++--- toolsrc/src/vcpkg_Dependencies.cpp | 11 ++--------- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 836ff09ae..6c9311264 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -151,7 +151,7 @@ namespace UnitTest1 auto spec_b = spec_map.emplace("b", "c"); auto spec_c = spec_map.emplace("c"); - auto map_port = Dependencies::MapPortFile(spec_map.map); + Dependencies::MapPortFile map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); @@ -175,7 +175,7 @@ namespace UnitTest1 auto spec_g = spec_map.emplace("g"); auto spec_h = spec_map.emplace("h"); - auto map_port = Dependencies::MapPortFile(spec_map.map); + Dependencies::MapPortFile map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan( map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); @@ -268,7 +268,7 @@ namespace UnitTest1 auto spec_j = spec_map.emplace("j", "k"); auto spec_k = spec_map.emplace("k"); - auto map_port = Dependencies::MapPortFile(spec_map.map); + Dependencies::MapPortFile map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 512e65e28..188b0f444 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -19,7 +19,7 @@ namespace vcpkg::Dependencies bool plus = false; }; - struct Cluster + struct Cluster : Util::MoveOnlyBase { std::vector status_paragraphs; Optional source_control_file; @@ -30,11 +30,6 @@ namespace vcpkg::Dependencies bool will_remove = false; bool transient_uninstalled = true; RequestType request_type = RequestType::AUTO_SELECTED; - Cluster() = default; - - private: - Cluster(const Cluster&) = delete; - Cluster& operator=(const Cluster&) = delete; }; struct ClusterPtr @@ -64,13 +59,12 @@ namespace vcpkg::Dependencies Graphs::Graph install_graph; }; - struct ClusterGraph + struct ClusterGraph : Util::MoveOnlyBase { explicit ClusterGraph(std::unordered_map&& ports) : m_ports(std::move(ports)) { } - ClusterGraph(ClusterGraph&&) = default; Cluster& get(const PackageSpec& spec) { @@ -108,7 +102,6 @@ namespace vcpkg::Dependencies out_cluster.source_control_file = &scf; } - ClusterGraph(const ClusterGraph&) = delete; std::unordered_map m_graph; std::unordered_map m_ports; }; -- cgit v1.2.3 From 687ea82f89504520e2a4c60feeb5c0bf6260a4de Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 22 Aug 2017 15:59:27 -0700 Subject: [vcpkg] Improve formatting of search and list. Fix gl2ps version. --- toolsrc/src/commands_list.cpp | 10 +++++----- toolsrc/src/commands_search.cpp | 10 +++++----- toolsrc/src/vcpkglib.cpp | 5 +++-- 3 files changed, 13 insertions(+), 12 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp index 9bc9bcc08..3cfa7e184 100644 --- a/toolsrc/src/commands_list.cpp +++ b/toolsrc/src/commands_list.cpp @@ -12,14 +12,14 @@ namespace vcpkg::Commands::List { if (FullDesc) { - System::println("%-27s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description); + System::println("%-30s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description); } else { - System::println("%-27s %-16s %s", - pgh.package.displayname(), - pgh.package.version, - vcpkg::shorten_description(pgh.package.description)); + System::println("%-30s %-16s %s", + vcpkg::shorten_text(pgh.package.displayname(), 30), + vcpkg::shorten_text(pgh.package.version, 16), + vcpkg::shorten_text(pgh.package.description, 71)); } } diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index f12c25fb6..b1bd7ea6f 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -57,9 +57,9 @@ namespace vcpkg::Commands::Search else { System::println("%-20s %-16s %s", - source_paragraph.name, - source_paragraph.version, - vcpkg::shorten_description(source_paragraph.description)); + vcpkg::shorten_text(source_paragraph.name, 20), + vcpkg::shorten_text(source_paragraph.version, 16), + vcpkg::shorten_text(source_paragraph.description, 81)); } } @@ -72,8 +72,8 @@ namespace vcpkg::Commands::Search else { System::println("%-37s %s", - name + "[" + feature_paragraph.name + "]", - vcpkg::shorten_description(feature_paragraph.description)); + vcpkg::shorten_text(name + "[" + feature_paragraph.name + "]", 37), + vcpkg::shorten_text(feature_paragraph.description, 81)); } } diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 428ae090d..6e90695de 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -240,9 +240,10 @@ namespace vcpkg LR"("%s" %s -P "%s")", cmake_exe.native(), cmd_cmake_pass_variables, cmake_script.generic_wstring()); } - std::string shorten_description(const std::string& desc) + std::string shorten_text(const std::string& desc, size_t length) { + Checks::check_exit(VCPKG_LINE_INFO, length >= 3); auto simple_desc = std::regex_replace(desc, std::regex("\\s+"), " "); - return simple_desc.size() <= 52 ? simple_desc : simple_desc.substr(0, 49) + "..."; + return simple_desc.size() <= length ? simple_desc : simple_desc.substr(0, length - 3) + "..."; } } -- cgit v1.2.3 From 57d078e8d1c5f5284d88e79600aa61fa06530ac4 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 22 Aug 2017 18:25:35 -0700 Subject: [vcpkg edit] Add option --buildtrees --- toolsrc/src/commands_edit.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index 12ddaad77..72005a461 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -8,11 +8,14 @@ namespace vcpkg::Commands::Edit { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { + static const std::string OPTION_BUILDTREES = "--buildtrees"; + auto& fs = paths.get_filesystem(); static const std::string example = Commands::Help::create_example_string("edit zlib"); args.check_exact_arg_count(1, example); - args.check_and_get_optional_command_arguments({}); + const std::unordered_set options = + args.check_and_get_optional_command_arguments({OPTION_BUILDTREES}); const std::string port_name = args.command_arguments.at(0); const fs::path portpath = paths.ports / port_name; @@ -84,6 +87,14 @@ namespace vcpkg::Commands::Edit VCPKG_LINE_INFO, "Visual Studio Code was not found and the environment variable EDITOR is not set"); } + if (options.find(OPTION_BUILDTREES) != options.cend()) + { + const auto buildtrees_current_dir = paths.buildtrees / port_name; + + std::wstring cmdLine = Strings::wformat(LR"("%s" "%s" -n)", env_EDITOR, buildtrees_current_dir.native()); + Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmdLine)); + } + std::wstring cmdLine = Strings::wformat( LR"("%s" "%s" "%s" -n)", env_EDITOR, portpath.native(), (portpath / "portfile.cmake").native()); Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmdLine)); -- cgit v1.2.3 From 14a99b073059d4fcae149a9085254fcb2e78e443 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 23 Aug 2017 15:47:42 -0700 Subject: [vcpkg] Deduplicate code from feature packages --- toolsrc/src/commands_export.cpp | 15 ++++-- toolsrc/src/commands_install.cpp | 107 ++++++++++++++++++------------------- toolsrc/src/vcpkg_Dependencies.cpp | 30 ++++------- 3 files changed, 72 insertions(+), 80 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index 4adfbc0f6..cbcb219b6 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -11,10 +11,10 @@ namespace vcpkg::Commands::Export { - using Install::InstallDir; using Dependencies::ExportPlanAction; - using Dependencies::RequestType; using Dependencies::ExportPlanType; + using Dependencies::RequestType; + using Install::InstallDir; static std::string create_nuspec_file_contents(const std::string& raw_exported_dir, const std::string& targets_redirect_path, @@ -235,10 +235,15 @@ namespace vcpkg::Commands::Export const auto options = args.check_and_get_optional_command_arguments( { - OPTION_DRY_RUN, OPTION_RAW, OPTION_NUGET, OPTION_ZIP, OPTION_7ZIP, + OPTION_DRY_RUN, + OPTION_RAW, + OPTION_NUGET, + OPTION_ZIP, + OPTION_7ZIP, }, { - OPTION_NUGET_ID, OPTION_NUGET_VERSION, + OPTION_NUGET_ID, + OPTION_NUGET_VERSION, }); const bool dryRun = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); const bool raw = options.switches.find(OPTION_RAW) != options.switches.cend(); @@ -323,7 +328,7 @@ namespace vcpkg::Commands::Export System::println("Exporting package %s... ", display_name); const BinaryParagraph& binary_paragraph = - action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO); + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; const InstallDir dirs = InstallDir::from_destination_root( raw_exported_dir_path / "installed", action.spec.triplet().to_string(), diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 9e37dc057..43d41bdf8 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -172,7 +172,7 @@ namespace vcpkg::Commands::Install return SortedVector(std::move(installed_files)); } - void install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db) + InstallResult install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db) { const fs::path package_dir = paths.package_dir(bcf.core_paragraph.spec); const Triplet& triplet = bcf.core_paragraph.spec.triplet(); @@ -199,7 +199,7 @@ namespace vcpkg::Commands::Install System::print("\n "); System::println(Strings::join("\n ", intersection)); System::println(""); - Checks::exit_fail(VCPKG_LINE_INFO); + return InstallResult::FILE_CONFLICTS; } StatusParagraph source_paragraph; @@ -239,6 +239,8 @@ namespace vcpkg::Commands::Install write_update(paths, feature_paragraph); status_db->insert(std::make_unique(feature_paragraph)); } + + return InstallResult::SUCCESS; } using Build::BuildResult; @@ -250,6 +252,7 @@ namespace vcpkg::Commands::Install { const InstallPlanType& plan_type = action.plan_type; const std::string display_name = action.spec.to_string(); + const std::string display_name_with_features = g_feature_packages ? action.displayname() : display_name; const bool is_user_requested = action.request_type == RequestType::USER_REQUESTED; const bool use_head_version = to_bool(build_package_options.use_head_version); @@ -257,76 +260,65 @@ namespace vcpkg::Commands::Install if (plan_type == InstallPlanType::ALREADY_INSTALLED) { if (use_head_version && is_user_requested) - { System::println( System::Color::warning, "Package %s is already installed -- not building from HEAD", display_name); - } else - { System::println(System::Color::success, "Package %s is already installed", display_name); - } return BuildResult::SUCCEEDED; } - if (plan_type == InstallPlanType::BUILD_AND_INSTALL && !g_feature_packages) + if (plan_type == InstallPlanType::BUILD_AND_INSTALL) { if (use_head_version) - System::println("Building package %s from HEAD... ", display_name); + System::println("Building package %s from HEAD... ", display_name_with_features); else - System::println("Building package %s... ", display_name); - - const Build::BuildPackageConfig build_config{ - action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO), - action.spec.triplet(), - paths.port_dir(action.spec), - build_package_options}; - const auto result = Build::build_package(paths, build_config, status_db); - if (result.code != Build::BuildResult::SUCCEEDED) - { - System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); - return result.code; - } - System::println("Building package %s... done", display_name); + System::println("Building package %s... ", display_name_with_features); - const BinaryControlFile bpgh = - Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); - System::println("Installing package %s... ", display_name); - install_package(paths, bpgh, &status_db); - System::println(System::Color::success, "Installing package %s... done", display_name); - return BuildResult::SUCCEEDED; - } + const auto result = [&]() -> Build::ExtendedBuildResult { + if (g_feature_packages) + { + const Build::BuildPackageConfig build_config{ + *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), + action.spec.triplet(), + paths.port_dir(action.spec), + build_package_options, + action.feature_list}; + return Build::build_package(paths, build_config, status_db); + } + else + { + const Build::BuildPackageConfig build_config{ + action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO), + action.spec.triplet(), + paths.port_dir(action.spec), + build_package_options}; + return Build::build_package(paths, build_config, status_db); + } + }(); - if (plan_type == InstallPlanType::BUILD_AND_INSTALL && g_feature_packages) - { - const std::string display_name_feature = action.displayname(); - if (use_head_version) - System::println("Building package %s from HEAD... ", display_name_feature); - else - System::println("Building package %s... ", display_name_feature); - - const Build::BuildPackageConfig build_config{ - *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), - action.spec.triplet(), - paths.port_dir(action.spec), - build_package_options, - action.feature_list}; - const auto result = Build::build_package(paths, build_config, status_db); if (result.code != Build::BuildResult::SUCCEEDED) { System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); return result.code; } - System::println("Building package %s... done", display_name_feature); + + System::println("Building package %s... done", display_name_with_features); const BinaryControlFile bcf = Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); - System::println("Installing package %s... ", display_name_feature); - install_package(paths, bcf, &status_db); - System::println(System::Color::success, "Installing package %s... done", display_name_feature); - return BuildResult::SUCCEEDED; + System::println("Installing package %s... ", display_name_with_features); + auto install_result = install_package(paths, bcf, &status_db); + switch (install_result) + { + case InstallResult::SUCCESS: + System::println(System::Color::success, "Installing package %s... done", display_name); + return BuildResult::SUCCEEDED; + case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS; + default: Checks::unreachable(VCPKG_LINE_INFO); + } } - if (plan_type == InstallPlanType::INSTALL && !g_feature_packages) + if (plan_type == InstallPlanType::INSTALL) { if (use_head_version && is_user_requested) { @@ -334,11 +326,16 @@ namespace vcpkg::Commands::Install System::Color::warning, "Package %s is already built -- not building from HEAD", display_name); } System::println("Installing package %s... ", display_name); - install_package(paths, - BinaryControlFile{action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO)}, - &status_db); - System::println(System::Color::success, "Installing package %s... done", display_name); - return BuildResult::SUCCEEDED; + auto install_result = install_package( + paths, action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO), &status_db); + switch (install_result) + { + case InstallResult::SUCCESS: + System::println(System::Color::success, "Installing package %s... done", display_name); + return BuildResult::SUCCEEDED; + case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS; + default: Checks::unreachable(VCPKG_LINE_INFO); + } } Checks::unreachable(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 188b0f444..4525fa02a 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -119,9 +119,11 @@ namespace vcpkg::Dependencies return to_package_specs(p->package.depends); } - if (auto p = this->binary_paragraph.get()) + if (auto p = this->binary_control_file.get()) { - return to_package_specs(p->depends); + auto deps = Util::fmap_flatten(p->features, [](const BinaryParagraph& pgh) { return pgh.depends; }); + deps.insert(deps.end(), p->core_paragraph.depends.begin(), p->core_paragraph.depends.end()); + return to_package_specs(deps); } if (auto p = this->source_paragraph.get()) @@ -164,7 +166,7 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const AnyParagraph& any_paragraph, const RequestType& request_type) - : spec(spec), request_type(request_type), any_paragraph(any_paragraph) + : spec(spec), request_type(request_type), plan_type(InstallPlanType::UNKNOWN), any_paragraph(any_paragraph) { if (auto p = any_paragraph.status_paragraph.get()) { @@ -172,7 +174,7 @@ namespace vcpkg::Dependencies return; } - if (auto p = any_paragraph.binary_paragraph.get()) + if (auto p = any_paragraph.binary_control_file.get()) { this->plan_type = InstallPlanType::INSTALL; return; @@ -183,8 +185,6 @@ namespace vcpkg::Dependencies this->plan_type = InstallPlanType::BUILD_AND_INSTALL; return; } - - this->plan_type = InstallPlanType::UNKNOWN; } std::string InstallPlanAction::displayname() const @@ -225,34 +225,24 @@ namespace vcpkg::Dependencies return left->spec.name() < right->spec.name(); } - ExportPlanAction::ExportPlanAction() - : spec(), any_paragraph(), plan_type(ExportPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) - { - } + ExportPlanAction::ExportPlanAction() : plan_type(ExportPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} ExportPlanAction::ExportPlanAction(const PackageSpec& spec, const AnyParagraph& any_paragraph, const RequestType& request_type) - : ExportPlanAction() + : spec(spec), any_paragraph(any_paragraph), plan_type(ExportPlanType::UNKNOWN), request_type(request_type) { - this->spec = spec; - this->request_type = request_type; - - if (auto p = any_paragraph.binary_paragraph.get()) + if (auto p = any_paragraph.binary_control_file.get()) { this->plan_type = ExportPlanType::ALREADY_BUILT; - this->any_paragraph.binary_paragraph = *p; return; } if (auto p = any_paragraph.source_paragraph.get()) { this->plan_type = ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT; - this->any_paragraph.source_paragraph = *p; return; } - - this->plan_type = ExportPlanType::UNKNOWN; } bool RemovePlanAction::compare_by_name(const RemovePlanAction* left, const RemovePlanAction* right) @@ -428,7 +418,7 @@ namespace vcpkg::Dependencies Expected maybe_bpgh = Paragraphs::try_load_cached_control_package(paths, spec); if (auto bcf = maybe_bpgh.get()) - return ExportPlanAction{spec, {nullopt, bcf->core_paragraph, nullopt}, request_type}; + return ExportPlanAction{spec, AnyParagraph{nullopt, std::move(*bcf), nullopt}, request_type}; auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); if (auto scf = maybe_scf.get()) -- cgit v1.2.3 From 30d2cb9debccf0bcaa1d61cedefae400fdf07951 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 23 Aug 2017 15:58:05 -0700 Subject: [vcpkg] Install should not list already installed packages as "to be built" --- toolsrc/src/commands_install.cpp | 53 +++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 14 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 43d41bdf8..bd14bf7e3 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -347,6 +347,7 @@ namespace vcpkg::Commands::Install std::vector rebuilt_plans; std::vector only_install_plans; std::vector new_plans; + std::vector already_installed_plans; const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { if (auto iplan = package.install_plan.get()) @@ -369,10 +370,16 @@ namespace vcpkg::Commands::Install } else { - if (install_action->plan_type == InstallPlanType::INSTALL) - only_install_plans.emplace_back(install_action); - else - new_plans.emplace_back(install_action); + switch (install_action->plan_type) + { + case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break; + case InstallPlanType::ALREADY_INSTALLED: + if (install_action->request_type == RequestType::USER_REQUESTED) + already_installed_plans.emplace_back(install_action); + break; + case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break; + default: Checks::unreachable(VCPKG_LINE_INFO); + } } } else if (auto remove_action = action.remove_plan.get()) @@ -385,23 +392,41 @@ namespace vcpkg::Commands::Install std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name); std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name); - const std::string rebuilt_string = Strings::join("\n", rebuilt_plans, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); - if (rebuilt_plans.size() > 0) System::println("The following packages will be rebuilt:\n%s", rebuilt_string); + if (already_installed_plans.size() > 0) + { + const std::string already_string = + Strings::join("\n", already_installed_plans, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname()); + }); + System::println("The following packages are already installed:\n%s", already_string); + } + + if (rebuilt_plans.size() > 0) + { + const std::string rebuilt_string = Strings::join("\n", rebuilt_plans, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname()); + }); + System::println("The following packages will be rebuilt:\n%s", rebuilt_string); + } - const std::string new_string = Strings::join("\n", new_plans, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); if (new_plans.size() > 0) + { + const std::string new_string = Strings::join("\n", new_plans, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname()); + }); System::println("The following packages will be built and installed:\n%s", new_string); + } - const std::string only_install_string = Strings::join("\n", only_install_plans, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); if (only_install_plans.size() > 0) + { + const std::string only_install_string = + Strings::join("\n", only_install_plans, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname()); + }); System::println("The following packages will be directly installed:\n%s", only_install_string); + } if (has_non_user_requested_packages) System::println("Additional packages (*) will be installed to complete this operation."); -- cgit v1.2.3 From 3c34cca36adfce1d3388b30e643294be58b3ec8f Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 23 Aug 2017 16:16:31 -0700 Subject: [vcpkg] Fix typo --- toolsrc/src/commands_remove.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index e480f02dd..db5357514 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -151,7 +151,7 @@ namespace vcpkg::Commands::Remove if (specs.empty()) { - System::println(System::Color::success, "There are no oudated packages."); + System::println(System::Color::success, "There are no outdated packages."); Checks::exit_success(VCPKG_LINE_INFO); } } -- cgit v1.2.3 From bed70f54bc2dd7181a54bbbb94d2fe3a1a0b35cc Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 23 Aug 2017 22:46:28 -0700 Subject: [vcpkg] Add stringify for BuildResult::FILE_CONFLICTS --- toolsrc/src/vcpkg_Build.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index 124efb7f2..ca89ccf37 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -240,6 +240,7 @@ namespace vcpkg::Build static const std::string NULLVALUE_STRING = Enums::nullvalue_to_string("vcpkg::Commands::Build::BuildResult"); static const std::string SUCCEEDED_STRING = "SUCCEEDED"; static const std::string BUILD_FAILED_STRING = "BUILD_FAILED"; + static const std::string FILE_CONFLICTS_STRING = "FILE_CONFLICTS"; static const std::string POST_BUILD_CHECKS_FAILED_STRING = "POST_BUILD_CHECKS_FAILED"; static const std::string CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING = "CASCADED_DUE_TO_MISSING_DEPENDENCIES"; @@ -250,6 +251,7 @@ namespace vcpkg::Build case BuildResult::BUILD_FAILED: return BUILD_FAILED_STRING; case BuildResult::POST_BUILD_CHECKS_FAILED: return POST_BUILD_CHECKS_FAILED_STRING; case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: return CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING; + case BuildResult::FILE_CONFLICTS: return FILE_CONFLICTS_STRING; default: Checks::unreachable(VCPKG_LINE_INFO); } } -- cgit v1.2.3 From 7dd082cad7b1b8323fb5409399614e8e0f4cddf2 Mon Sep 17 00:00:00 2001 From: Mikhail Paulyshka Date: Thu, 24 Aug 2017 13:26:42 +0300 Subject: [vcpkg] testing for architectures supported by toolset --- toolsrc/src/VcpkgPaths.cpp | 44 +++++++++++++++++++++++++++++++++++++++--- toolsrc/src/vcpkg_Build.cpp | 46 ++++++++++++++++++++------------------------ toolsrc/src/vcpkg_System.cpp | 14 ++++++++++++++ 3 files changed, 76 insertions(+), 28 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 4be636650..642ca6a9c 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -279,6 +279,8 @@ namespace vcpkg static std::vector find_toolset_instances(const VcpkgPaths& paths) { + using CPU = System::CPUArchitecture; + const auto& fs = paths.get_filesystem(); const std::vector vs2017_installation_instances = get_VS2017_installation_instances(paths); @@ -298,9 +300,27 @@ namespace vcpkg { const fs::path vs2015_dumpbin_exe = *v / "VC" / "bin" / "dumpbin.exe"; paths_examined.push_back(vs2015_dumpbin_exe); + + const fs::path vs2015_bin_dir = vs2015_vcvarsall_bat.parent_path() / "bin"; + std::vector supported_archictectures; + if(fs.exists(vs2015_bin_dir / "vcvars32.bat")) + supported_archictectures.push_back({L"x86", CPU::X86, CPU::X86}); + if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat")) + supported_archictectures.push_back({L"x64", CPU::X64, CPU::X64}); + if (fs.exists(vs2015_bin_dir / "arm\\vcvarsarm.bat")) + supported_archictectures.push_back({L"arm", CPU::ARM, CPU::ARM}); + if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) + supported_archictectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) + supported_archictectures.push_back({L"x86_arm" , CPU::X86, CPU::ARM}); + if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) + supported_archictectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) + supported_archictectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + if (fs.exists(vs2015_dumpbin_exe)) { - found_toolsets.push_back({vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140"}); + found_toolsets.push_back({vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140", supported_archictectures }); } } } @@ -312,10 +332,28 @@ namespace vcpkg const fs::path vc_dir = instance / "VC"; // Skip any instances that do not have vcvarsall. - const fs::path vcvarsall_bat = vc_dir / "Auxiliary" / "Build" / "vcvarsall.bat"; + const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build"; + const fs::path vcvarsall_bat = vcvarsall_dir / "vcvarsall.bat"; paths_examined.push_back(vcvarsall_bat); if (!fs.exists(vcvarsall_bat)) continue; + //Get all supported architecturs + std::vector supported_architectures; + if (fs.exists(vcvarsall_dir / "vcvars32.bat")) + supported_architectures.push_back({L"x86", CPU::X86,CPU::X86 }); + if (fs.exists(vcvarsall_dir / "vcvars64.bat")) + supported_architectures.push_back({L"amd64", CPU::X64,CPU::X64 }); + if (fs.exists(vcvarsall_dir / "vcvarsarm.bat")) + supported_architectures.push_back({L"arm", CPU::ARM,CPU::ARM }); + if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) + supported_architectures.push_back({L"x86_amd64",CPU::X86,CPU::X64 }); + if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) + supported_architectures.push_back({L"x86_arm", CPU::X86,CPU::ARM }); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) + supported_architectures.push_back({L"amd64_x86", CPU::X64,CPU::X86 }); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) + supported_architectures.push_back({L"amd64_arm", CPU::X64,CPU::ARM }); + // Locate the "best" MSVC toolchain version const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; std::vector msvc_subdirectories = fs.get_files_non_recursive(msvc_path); @@ -332,7 +370,7 @@ namespace vcpkg paths_examined.push_back(dumpbin_path); if (fs.exists(dumpbin_path)) { - vs2017_toolset = Toolset{dumpbin_path, vcvarsall_bat, L"v141"}; + vs2017_toolset = Toolset{dumpbin_path, vcvarsall_bat, L"v141", supported_architectures}; break; } } diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index ca89ccf37..2c9a147a4 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -36,39 +36,35 @@ namespace vcpkg::Build Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported vcvarsall target %s", cmake_system_name); } - CWStringView to_vcvarsall_toolchain(const std::string& target_architecture) + CWStringView to_vcvarsall_toolchain(const std::string& target_architecture, const Toolset& toolset) { using CPU = System::CPUArchitecture; - struct ArchOption - { - CWStringView name; - CPU host_arch; - CPU target_arch; - }; - - static constexpr ArchOption X86 = {L"x86", CPU::X86, CPU::X86}; - static constexpr ArchOption X86_X64 = {L"x86_x64", CPU::X86, CPU::X64}; - static constexpr ArchOption X86_ARM = {L"x86_arm", CPU::X86, CPU::ARM}; - static constexpr ArchOption X86_ARM64 = {L"x86_arm64", CPU::X86, CPU::ARM64}; - - static constexpr ArchOption X64 = {L"amd64", CPU::X64, CPU::X64}; - static constexpr ArchOption X64_X86 = {L"amd64_x86", CPU::X64, CPU::X86}; - static constexpr ArchOption X64_ARM = {L"amd64_arm", CPU::X64, CPU::ARM}; - static constexpr ArchOption X64_ARM64 = {L"amd64_arm64", CPU::X64, CPU::ARM64}; - - static constexpr std::array VALUES = { + static constexpr ToolsetArchOption X86 = {L"x86", CPU::X86, CPU::X86}; + static constexpr ToolsetArchOption X86_X64 = {L"x86_x64", CPU::X86, CPU::X64}; + static constexpr ToolsetArchOption X86_ARM = {L"x86_arm", CPU::X86, CPU::ARM}; + static constexpr ToolsetArchOption X86_ARM64 = {L"x86_arm64", CPU::X86, CPU::ARM64}; + + static constexpr ToolsetArchOption X64 = {L"amd64", CPU::X64, CPU::X64}; + static constexpr ToolsetArchOption X64_X86 = {L"amd64_x86", CPU::X64, CPU::X86}; + static constexpr ToolsetArchOption X64_ARM = {L"amd64_arm", CPU::X64, CPU::ARM}; + static constexpr ToolsetArchOption X64_ARM64 = {L"amd64_arm64", CPU::X64, CPU::ARM64}; + + static constexpr std::array VALUES = { X86, X86_X64, X86_ARM, X86_ARM64, X64, X64_X86, X64_ARM, X64_ARM64}; auto target_arch = System::to_cpu_architecture(target_architecture); - auto host_arch = System::get_host_processor(); + auto host_architectures = System::get_supported_host_architectures(); for (auto&& value : VALUES) { - if (target_arch == value.target_arch && host_arch == value.host_arch) - { - return value.name; - } + if (target_arch != value.target_arch || + std::find(host_architectures.begin(), host_architectures.end(), value.host_arch) == host_architectures.end() || + std::find(toolset.supported_architectures.begin(), toolset.supported_architectures.end(), value) == toolset.supported_architectures.end() + ) + continue; + + return value.name; } Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported toolchain combination %s", target_architecture); @@ -82,7 +78,7 @@ namespace vcpkg::Build tonull = L""; } - auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture); + auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset); auto target = to_vcvarsall_target(pre_build_info.cmake_system_name); return Strings::wformat(LR"("%s" %s %s %s 2>&1)", toolset.vcvarsall.native(), arch, target, tonull); diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 883fe6612..3288ec7a2 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -42,6 +42,20 @@ namespace vcpkg::System return to_cpu_architecture(Strings::to_utf8(procarch)).value_or_exit(VCPKG_LINE_INFO); } + std::vector get_supported_host_architectures() + { + std::vector supported_architectures; + supported_architectures.push_back(get_host_processor()); + + //AMD64 machines support to run x86 applications + if(supported_architectures.back()==CPUArchitecture::X64) + { + supported_architectures.push_back(CPUArchitecture::X86); + } + + return supported_architectures; + } + int cmd_execute_clean(const CWStringView cmd_line) { static const std::wstring system_root = get_environment_variable(L"SystemRoot").value_or_exit(VCPKG_LINE_INFO); -- cgit v1.2.3 From 52d606e6ac6650271fc2fd02718eb107dd33e797 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 24 Aug 2017 12:06:28 -0700 Subject: Use CreateProcess instead of _wspawnlpe --- toolsrc/src/vcpkg_System.cpp | 50 +++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 12 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 883fe6612..2ad120e4c 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -96,8 +96,7 @@ namespace vcpkg::System // Flush stdout before launching external process fflush(nullptr); - std::vector env_cstr; - env_cstr.reserve(env_wstrings.size() + 2); + std::wstring env_cstr; for (auto&& env_wstring : env_wstrings) { @@ -105,20 +104,47 @@ namespace vcpkg::System auto v = value.get(); if (!v || v->empty()) continue; - env_wstring.push_back(L'='); - env_wstring.append(*v); - env_cstr.push_back(env_wstring.c_str()); + env_cstr.append(env_wstring); + env_cstr.push_back(L'='); + env_cstr.append(*v); + env_cstr.push_back(L'\0'); } - env_cstr.push_back(new_PATH.c_str()); - env_cstr.push_back(nullptr); + env_cstr.append(new_PATH); + env_cstr.push_back(L'\0'); + + STARTUPINFOW startup_info; + memset(&startup_info, 0, sizeof(STARTUPINFOW)); + startup_info.cb = sizeof(STARTUPINFOW); + + PROCESS_INFORMATION process_info; + memset(&process_info, 0, sizeof(PROCESS_INFORMATION)); // Basically we are wrapping it in quotes - const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); - Debug::println("_wspawnlpe(cmd.exe /c %s)", Strings::to_utf8(actual_cmd_line)); - auto exit_code = - _wspawnlpe(_P_WAIT, L"cmd.exe", L"cmd.exe", L"/c", actual_cmd_line.c_str(), nullptr, env_cstr.data()); - Debug::println("_wspawnlpe() returned %d", exit_code); + std::wstring actual_cmd_line = Strings::wformat(LR"###(cmd.exe /c "%s")###", cmd_line); + Debug::println("CreateProcessW(%s)", Strings::to_utf8(actual_cmd_line)); + bool succeeded = TRUE == CreateProcessW(nullptr, + actual_cmd_line.data(), + nullptr, + nullptr, + FALSE, + BELOW_NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, + env_cstr.data(), + nullptr, + &startup_info, + &process_info); + + Checks::check_exit(VCPKG_LINE_INFO, succeeded, "Process creation failed with error code: %lu", GetLastError()); + + CloseHandle(process_info.hThread); + + DWORD result = WaitForSingleObject(process_info.hProcess, INFINITE); + Checks::check_exit(VCPKG_LINE_INFO, result != WAIT_FAILED, "WaitForSingleObject failed"); + + DWORD exit_code = 0; + GetExitCodeProcess(process_info.hProcess, &exit_code); + + Debug::println("CreateProcessW() returned %lu", exit_code); return static_cast(exit_code); } -- cgit v1.2.3 From ceb54bae8754f707bec17ac6ff3e35a32b0966e3 Mon Sep 17 00:00:00 2001 From: Mikhail Paulyshka Date: Fri, 25 Aug 2017 00:45:11 +0300 Subject: [vcpkg] prefer AMD64 host architecture --- toolsrc/src/vcpkg_Build.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index 2c9a147a4..b0053766e 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -51,7 +51,7 @@ namespace vcpkg::Build static constexpr ToolsetArchOption X64_ARM64 = {L"amd64_arm64", CPU::X64, CPU::ARM64}; static constexpr std::array VALUES = { - X86, X86_X64, X86_ARM, X86_ARM64, X64, X64_X86, X64_ARM, X64_ARM64}; + X64, X64_X86, X64_ARM, X64_ARM64, X86, X86_X64, X86_ARM, X86_ARM64}; auto target_arch = System::to_cpu_architecture(target_architecture); auto host_architectures = System::get_supported_host_architectures(); -- cgit v1.2.3 From e237682cad4eaa582a10b5ad03a59ca6449e0795 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 23 Aug 2017 16:17:53 -0700 Subject: Introduce GlobalState struct --- toolsrc/src/Paragraphs.cpp | 3 ++- toolsrc/src/SourceParagraph.cpp | 1 - toolsrc/src/VcpkgCmdArguments.cpp | 3 ++- toolsrc/src/commands_search.cpp | 3 ++- toolsrc/src/vcpkg.cpp | 14 +++++++------- toolsrc/src/vcpkg_Build.cpp | 7 ++++--- toolsrc/src/vcpkg_GlobalState.cpp | 10 ++++++++++ toolsrc/src/vcpkg_System.cpp | 9 +++++---- toolsrc/src/vcpkglib.cpp | 2 -- 9 files changed, 32 insertions(+), 20 deletions(-) create mode 100644 toolsrc/src/vcpkg_GlobalState.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index 3a30f66a3..a7dee4fd3 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -3,6 +3,7 @@ #include "ParagraphParseResult.h" #include "Paragraphs.h" #include "vcpkg_Files.h" +#include "vcpkg_GlobalState.h" #include "vcpkg_Util.h" using namespace vcpkg::Parse; @@ -210,7 +211,7 @@ namespace vcpkg::Paragraphs if (auto vector_pghs = pghs.get()) { auto csf = SourceControlFile::parse_control_file(std::move(*vector_pghs)); - if (!g_feature_packages) + if (!GlobalState::feature_packages) { if (auto ptr = csf.get()) { diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 54f34cbd3..c69770ae1 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -13,7 +13,6 @@ namespace vcpkg { using namespace vcpkg::Parse; - bool g_feature_packages = false; namespace Fields { static const std::string BUILD_DEPENDS = "Build-Depends"; diff --git a/toolsrc/src/VcpkgCmdArguments.cpp b/toolsrc/src/VcpkgCmdArguments.cpp index ebf4c5fc5..a72e5226f 100644 --- a/toolsrc/src/VcpkgCmdArguments.cpp +++ b/toolsrc/src/VcpkgCmdArguments.cpp @@ -3,6 +3,7 @@ #include "VcpkgCmdArguments.h" #include "metrics.h" #include "vcpkg_Commands.h" +#include "vcpkg_GlobalState.h" #include "vcpkg_System.h" namespace vcpkg @@ -119,7 +120,7 @@ namespace vcpkg } if (arg == "--featurepackages") { - g_feature_packages = true; + GlobalState::feature_packages = true; continue; } diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index b1bd7ea6f..529d52a8b 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -3,6 +3,7 @@ #include "Paragraphs.h" #include "SourceParagraph.h" #include "vcpkg_Commands.h" +#include "vcpkg_GlobalState.h" #include "vcpkg_System.h" #include "vcpkglib.h" @@ -90,7 +91,7 @@ namespace vcpkg::Commands::Search if (!sources_and_errors.errors.empty()) { - if (vcpkg::g_debugging) + if (GlobalState::debugging) { print_error_message(sources_and_errors.errors); } diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 738b7b284..3ccb33aad 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -6,6 +6,7 @@ #include "vcpkg_Chrono.h" #include "vcpkg_Commands.h" #include "vcpkg_Files.h" +#include "vcpkg_GlobalState.h" #include "vcpkg_Input.h" #include "vcpkg_Strings.h" #include "vcpkg_System.h" @@ -184,17 +185,16 @@ static std::string trim_path_from_command_line(const std::string& full_command_l return std::string(it, full_command_line.cend()); } -static ElapsedTime g_timer; - int wmain(const int argc, const wchar_t* const* const argv) { if (argc == 0) std::abort(); - g_timer = ElapsedTime::create_started(); + GlobalState::timer = ElapsedTime::create_started(); + atexit([]() { - auto elapsed_us = g_timer.microseconds(); + auto elapsed_us = GlobalState::timer.microseconds(); Metrics::track_metric("elapsed_us", elapsed_us); - g_debugging = false; + GlobalState::debugging = false; Metrics::flush(); }); @@ -209,9 +209,9 @@ int wmain(const int argc, const wchar_t* const* const argv) if (auto p = args.printmetrics.get()) Metrics::set_print_metrics(*p); if (auto p = args.sendmetrics.get()) Metrics::set_send_metrics(*p); - if (auto p = args.debug.get()) g_debugging = *p; + if (auto p = args.debug.get()) GlobalState::debugging = *p; - if (g_debugging) + if (GlobalState::debugging) { inner(args); Checks::exit_fail(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index ca89ccf37..d4632afaa 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -8,6 +8,7 @@ #include "vcpkg_Chrono.h" #include "vcpkg_Commands.h" #include "vcpkg_Enums.h" +#include "vcpkg_GlobalState.h" #include "vcpkg_System.h" #include "vcpkg_optional.h" #include "vcpkglib.h" @@ -77,7 +78,7 @@ namespace vcpkg::Build std::wstring make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset) { const wchar_t* tonull = L" >nul"; - if (g_debugging) + if (GlobalState::debugging) { tonull = L""; } @@ -155,7 +156,7 @@ namespace vcpkg::Build const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); std::string features; - if (g_feature_packages) + if (GlobalState::feature_packages) { if (config.feature_list) { @@ -212,7 +213,7 @@ namespace vcpkg::Build { return {BuildResult::POST_BUILD_CHECKS_FAILED, {}}; } - if (g_feature_packages) + if (GlobalState::feature_packages) { if (config.feature_list) { diff --git a/toolsrc/src/vcpkg_GlobalState.cpp b/toolsrc/src/vcpkg_GlobalState.cpp new file mode 100644 index 000000000..cae2b2f8e --- /dev/null +++ b/toolsrc/src/vcpkg_GlobalState.cpp @@ -0,0 +1,10 @@ +#include "pch.h" + +#include "vcpkg_GlobalState.h" + +namespace vcpkg +{ + ElapsedTime GlobalState::timer; + bool GlobalState::debugging = false; + bool GlobalState::feature_packages = false; +} diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 2ad120e4c..2d6246d19 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "vcpkg_Checks.h" +#include "vcpkg_GlobalState.h" #include "vcpkg_System.h" #include "vcpkglib.h" @@ -94,7 +95,7 @@ namespace vcpkg::System }; // Flush stdout before launching external process - fflush(nullptr); + fflush(nullptr); std::wstring env_cstr; @@ -151,7 +152,7 @@ namespace vcpkg::System int cmd_execute(const CWStringView cmd_line) { // Flush stdout before launching external process - fflush(nullptr); + fflush(nullptr); // Basically we are wrapping it in quotes const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); @@ -302,7 +303,7 @@ namespace vcpkg::Debug { void println(const CStringView message) { - if (g_debugging) + if (GlobalState::debugging) { System::println("[DEBUG] %s", message); } @@ -310,7 +311,7 @@ namespace vcpkg::Debug void println(const System::Color c, const CStringView message) { - if (g_debugging) + if (GlobalState::debugging) { System::println(c, "[DEBUG] %s", message); } diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 6e90695de..b52f49d62 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -9,8 +9,6 @@ namespace vcpkg { - bool g_debugging = false; - static StatusParagraphs load_current_database(Files::Filesystem& fs, const fs::path& vcpkg_dir_status_file, const fs::path& vcpkg_dir_status_file_old) -- cgit v1.2.3 From 88d96a3699118cf21f6ec92284eb591db25d3a6a Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 23 Aug 2017 16:47:54 -0700 Subject: Run cleanup before exiting instead of calling atexit --- toolsrc/src/vcpkg.cpp | 7 +------ toolsrc/src/vcpkg_Checks.cpp | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 3ccb33aad..7294d8692 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -191,12 +191,7 @@ int wmain(const int argc, const wchar_t* const* const argv) GlobalState::timer = ElapsedTime::create_started(); - atexit([]() { - auto elapsed_us = GlobalState::timer.microseconds(); - Metrics::track_metric("elapsed_us", elapsed_us); - GlobalState::debugging = false; - Metrics::flush(); - }); + // Checks::register_console_ctrl_handler(); Metrics::track_property("version", Commands::Version::version()); diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp index 2674b889a..6ae595a54 100644 --- a/toolsrc/src/vcpkg_Checks.cpp +++ b/toolsrc/src/vcpkg_Checks.cpp @@ -1,11 +1,31 @@ #include "pch.h" +#include "metrics.h" #include "vcpkg_Checks.h" +#include "vcpkg_GlobalState.h" #include "vcpkg_System.h" #include "vcpkglib.h" namespace vcpkg::Checks { + [[noreturn]] static void cleanup_and_exit(const int exit_code) + { + auto elapsed_us = GlobalState::timer.microseconds(); + Metrics::track_metric("elapsed_us", elapsed_us); + GlobalState::debugging = false; + Metrics::flush(); + + ::exit(exit_code); + } + + static BOOL CtrlHandler(DWORD fdwCtrlType) + { + Metrics::track_metric("SignalCaptured", fdwCtrlType); + cleanup_and_exit(EXIT_FAILURE); + } + + void register_console_ctrl_handler() { SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); } + [[noreturn]] void unreachable(const LineInfo& line_info) { System::println(System::Color::error, "Error: Unreachable code was reached"); @@ -13,14 +33,14 @@ namespace vcpkg::Checks #ifndef NDEBUG std::abort(); #else - ::exit(EXIT_FAILURE); + cleanup_and_exit(EXIT_FAILURE); #endif } [[noreturn]] void exit_with_code(const LineInfo& line_info, const int exit_code) { Debug::println(System::Color::error, line_info.to_string()); - ::exit(exit_code); + cleanup_and_exit(exit_code); } [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView errorMessage) -- cgit v1.2.3 From 34bd87c9fcfb1ac9269c75db96852b64ed754d11 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 24 Aug 2017 16:32:06 -0700 Subject: Fix merge issues --- toolsrc/src/commands_install.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index bd14bf7e3..659418a38 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -6,6 +6,7 @@ #include "vcpkg_Commands.h" #include "vcpkg_Dependencies.h" #include "vcpkg_Files.h" +#include "vcpkg_GlobalState.h" #include "vcpkg_Input.h" #include "vcpkg_System.h" #include "vcpkg_Util.h" @@ -252,7 +253,8 @@ namespace vcpkg::Commands::Install { const InstallPlanType& plan_type = action.plan_type; const std::string display_name = action.spec.to_string(); - const std::string display_name_with_features = g_feature_packages ? action.displayname() : display_name; + const std::string display_name_with_features = + GlobalState::feature_packages ? action.displayname() : display_name; const bool is_user_requested = action.request_type == RequestType::USER_REQUESTED; const bool use_head_version = to_bool(build_package_options.use_head_version); @@ -275,7 +277,7 @@ namespace vcpkg::Commands::Install System::println("Building package %s... ", display_name_with_features); const auto result = [&]() -> Build::ExtendedBuildResult { - if (g_feature_packages) + if (GlobalState::feature_packages) { const Build::BuildPackageConfig build_config{ *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), @@ -459,7 +461,7 @@ namespace vcpkg::Commands::Install for (auto&& spec : specs) { Input::check_triplet(spec.package_spec.triplet(), paths); - if (!spec.features.empty() && !g_feature_packages) + if (!spec.features.empty() && !GlobalState::feature_packages) { Checks::exit_with_message( VCPKG_LINE_INFO, "Feature packages are experimentally available under the --featurepackages flag."); @@ -481,7 +483,7 @@ namespace vcpkg::Commands::Install std::vector action_plan; - if (g_feature_packages) + if (GlobalState::feature_packages) { std::unordered_map scf_map; auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); @@ -522,7 +524,7 @@ namespace vcpkg::Commands::Install } // execute the plan - if (g_feature_packages) + if (GlobalState::feature_packages) { for (const auto& action : action_plan) { -- cgit v1.2.3 From 98ee8a949ad4bfdfa9bf0411b552a23c923eaff7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 25 Aug 2017 16:03:57 -0700 Subject: [vcpkg] Trap Ctrl-C, enable thread safety for global data structures --- toolsrc/src/VcpkgCmdArguments.cpp | 8 ++++---- toolsrc/src/VcpkgPaths.cpp | 9 ++++++--- toolsrc/src/commands_install.cpp | 3 ++- toolsrc/src/metrics.cpp | 20 +++++++++++--------- toolsrc/src/vcpkg.cpp | 32 ++++++++++++++++++++------------ toolsrc/src/vcpkg_Build.cpp | 13 ++++++++----- toolsrc/src/vcpkg_Checks.cpp | 14 ++++++++++---- toolsrc/src/vcpkg_GlobalState.cpp | 6 +++--- toolsrc/src/vcpkg_Input.cpp | 2 +- toolsrc/src/vcpkg_metrics_uploader.cpp | 3 ++- toolsrc/src/vcpkglib.cpp | 2 +- 11 files changed, 68 insertions(+), 44 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgCmdArguments.cpp b/toolsrc/src/VcpkgCmdArguments.cpp index a72e5226f..cf6c7b562 100644 --- a/toolsrc/src/VcpkgCmdArguments.cpp +++ b/toolsrc/src/VcpkgCmdArguments.cpp @@ -16,7 +16,7 @@ namespace vcpkg if (arg_begin == arg_end) { System::println(System::Color::error, "Error: expected value after %s", option_name); - Metrics::track_property("error", "error option name"); + Metrics::g_metrics.lock()->track_property("error", "error option name"); Commands::Help::print_usage(); Checks::exit_fail(VCPKG_LINE_INFO); } @@ -24,7 +24,7 @@ namespace vcpkg if (option_field != nullptr) { System::println(System::Color::error, "Error: %s specified multiple times", option_name); - Metrics::track_property("error", "error option specified multiple times"); + Metrics::g_metrics.lock()->track_property("error", "error option specified multiple times"); Commands::Help::print_usage(); Checks::exit_fail(VCPKG_LINE_INFO); } @@ -37,7 +37,7 @@ namespace vcpkg if (option_field && option_field != new_setting) { System::println(System::Color::error, "Error: conflicting values specified for --%s", option_name); - Metrics::track_property("error", "error conflicting switches"); + Metrics::g_metrics.lock()->track_property("error", "error conflicting switches"); Commands::Help::print_usage(); Checks::exit_fail(VCPKG_LINE_INFO); } @@ -71,7 +71,7 @@ namespace vcpkg if (arg[0] == '-' && arg[1] != '-') { - Metrics::track_property("error", "error short options are not supported"); + Metrics::g_metrics.lock()->track_property("error", "error short options are not supported"); Checks::exit_with_message(VCPKG_LINE_INFO, "Error: short options are not supported: %s", arg); } diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 4be636650..1b76fdc24 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -87,8 +87,11 @@ namespace vcpkg "(No sufficient installed version was found)", Strings::to_utf8(tool_name), version_as_string); - Metrics::track_property("error", "powershell install failed"); - Metrics::track_property("installcmd", install_cmd); + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_property("error", "powershell install failed"); + locked_metrics->track_property("installcmd", install_cmd); + } Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); } @@ -186,7 +189,7 @@ namespace vcpkg if (paths.root.empty()) { - Metrics::track_property("error", "Invalid vcpkg root directory"); + Metrics::g_metrics.lock()->track_property("error", "Invalid vcpkg root directory"); Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid vcpkg root directory: %s", paths.root.string()); } diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 659418a38..a2e95eb48 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -514,7 +514,8 @@ namespace vcpkg::Commands::Install return "R$" + raction->spec.to_string(); Checks::unreachable(VCPKG_LINE_INFO); }); - Metrics::track_property("installplan", specs_string); + + Metrics::g_metrics.lock()->track_property("installplan", specs_string); print_plan(action_plan, is_recursive); diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp index 7992f3e51..6263c0fcb 100644 --- a/toolsrc/src/metrics.cpp +++ b/toolsrc/src/metrics.cpp @@ -8,6 +8,8 @@ namespace vcpkg::Metrics { + Util::LockGuarded g_metrics; + static std::string get_current_date_time() { struct tm newtime; @@ -223,25 +225,25 @@ namespace vcpkg::Metrics return hkcu_sqmclient.value_or(L"{}"); } - void set_user_information(const std::string& user_id, const std::string& first_use_time) + void Metrics::set_user_information(const std::string& user_id, const std::string& first_use_time) { g_metricmessage.user_id = user_id; g_metricmessage.user_timestamp = first_use_time; } - void init_user_information(std::string& user_id, std::string& first_use_time) + void Metrics::init_user_information(std::string& user_id, std::string& first_use_time) { user_id = generate_random_UUID(); first_use_time = get_current_date_time(); } - void set_send_metrics(bool should_send_metrics) { g_should_send_metrics = should_send_metrics; } + void Metrics::set_send_metrics(bool should_send_metrics) { g_should_send_metrics = should_send_metrics; } - void set_print_metrics(bool should_print_metrics) { g_should_print_metrics = should_print_metrics; } + void Metrics::set_print_metrics(bool should_print_metrics) { g_should_print_metrics = should_print_metrics; } - void track_metric(const std::string& name, double value) { g_metricmessage.TrackMetric(name, value); } + void Metrics::track_metric(const std::string& name, double value) { g_metricmessage.TrackMetric(name, value); } - void track_property(const std::string& name, const std::wstring& value) + void Metrics::track_property(const std::string& name, const std::wstring& value) { // Note: this is not valid UTF-16 -> UTF-8, it just yields a close enough approximation for our purposes. std::string converted_value; @@ -252,12 +254,12 @@ namespace vcpkg::Metrics g_metricmessage.TrackProperty(name, converted_value); } - void track_property(const std::string& name, const std::string& value) + void Metrics::track_property(const std::string& name, const std::string& value) { g_metricmessage.TrackProperty(name, value); } - void upload(const std::string& payload) + void Metrics::upload(const std::string& payload) { HINTERNET hSession = nullptr, hConnect = nullptr, hRequest = nullptr; BOOL bResults = FALSE; @@ -349,7 +351,7 @@ namespace vcpkg::Metrics return fs::path(buf, buf + bytes); } - void flush() + void Metrics::flush() { std::string payload = g_metricmessage.format_event_data_template(); if (g_should_print_metrics) std::cerr << payload << "\n"; diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 7294d8692..9da501ec0 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -27,7 +27,7 @@ void invalid_command(const std::string& cmd) static void inner(const VcpkgCmdArguments& args) { - Metrics::track_property("command", args.command); + Metrics::g_metrics.lock()->track_property("command", args.command); if (args.command.empty()) { Commands::Help::print_usage(); @@ -135,7 +135,7 @@ static void loadConfig() auto user_time = keys["User-Since"]; if (!user_id.empty() && !user_time.empty()) { - Metrics::set_user_information(user_id, user_time); + Metrics::g_metrics.lock()->set_user_information(user_id, user_time); return; } } @@ -146,8 +146,11 @@ static void loadConfig() // config file not found, could not be read, or invalid std::string user_id, user_time; - Metrics::init_user_information(user_id, user_time); - Metrics::set_user_information(user_id, user_time); + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->init_user_information(user_id, user_time); + locked_metrics->set_user_information(user_id, user_time); + } try { std::error_code ec; @@ -189,23 +192,28 @@ int wmain(const int argc, const wchar_t* const* const argv) { if (argc == 0) std::abort(); - GlobalState::timer = ElapsedTime::create_started(); + *GlobalState::timer.lock() = ElapsedTime::create_started(); // Checks::register_console_ctrl_handler(); - Metrics::track_property("version", Commands::Version::version()); - const std::string trimmed_command_line = trim_path_from_command_line(Strings::to_utf8(GetCommandLineW())); - Metrics::track_property("cmdline", trimmed_command_line); + + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_property("version", Commands::Version::version()); + locked_metrics->track_property("cmdline", trimmed_command_line); + } loadConfig(); - Metrics::track_property("sqmuser", Metrics::get_SQM_user()); + Metrics::g_metrics.lock()->track_property("sqmuser", Metrics::get_SQM_user()); const VcpkgCmdArguments args = VcpkgCmdArguments::create_from_command_line(argc, argv); - if (auto p = args.printmetrics.get()) Metrics::set_print_metrics(*p); - if (auto p = args.sendmetrics.get()) Metrics::set_send_metrics(*p); + if (auto p = args.printmetrics.get()) Metrics::g_metrics.lock()->set_print_metrics(*p); + if (auto p = args.sendmetrics.get()) Metrics::g_metrics.lock()->set_send_metrics(*p); if (auto p = args.debug.get()) GlobalState::debugging = *p; + vcpkg::Checks::register_console_ctrl_handler(); + if (GlobalState::debugging) { inner(args); @@ -226,7 +234,7 @@ int wmain(const int argc, const wchar_t* const* const argv) { exc_msg = "unknown error(...)"; } - Metrics::track_property("error", exc_msg); + Metrics::g_metrics.lock()->track_property("error", exc_msg); fflush(stdout); System::print("vcpkg.exe has crashed.\n" diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index d4632afaa..89f95ee9b 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -193,13 +193,16 @@ namespace vcpkg::Build int return_code = System::cmd_execute_clean(command); auto buildtimeus = timer.microseconds(); const auto spec_string = spec.to_string(); - Metrics::track_metric("buildtimeus-" + spec_string, buildtimeus); - if (return_code != 0) { - Metrics::track_property("error", "build failed"); - Metrics::track_property("build_error", spec_string); - return {BuildResult::BUILD_FAILED, {}}; + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_metric("buildtimeus-" + spec_string, buildtimeus); + if (return_code != 0) + { + locked_metrics->track_property("error", "build failed"); + locked_metrics->track_property("build_error", spec_string); + return {BuildResult::BUILD_FAILED, {}}; + } } auto build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp index 6ae595a54..d8d857daa 100644 --- a/toolsrc/src/vcpkg_Checks.cpp +++ b/toolsrc/src/vcpkg_Checks.cpp @@ -10,17 +10,23 @@ namespace vcpkg::Checks { [[noreturn]] static void cleanup_and_exit(const int exit_code) { - auto elapsed_us = GlobalState::timer.microseconds(); - Metrics::track_metric("elapsed_us", elapsed_us); + auto elapsed_us = GlobalState::timer.lock()->microseconds(); + + auto metrics = Metrics::g_metrics.lock(); + metrics->track_metric("elapsed_us", elapsed_us); GlobalState::debugging = false; - Metrics::flush(); + metrics->flush(); ::exit(exit_code); } static BOOL CtrlHandler(DWORD fdwCtrlType) { - Metrics::track_metric("SignalCaptured", fdwCtrlType); + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_property("CtrlHandler", std::to_string(fdwCtrlType)); + locked_metrics->track_property("error", "CtrlHandler was fired."); + } cleanup_and_exit(EXIT_FAILURE); } diff --git a/toolsrc/src/vcpkg_GlobalState.cpp b/toolsrc/src/vcpkg_GlobalState.cpp index cae2b2f8e..c194da466 100644 --- a/toolsrc/src/vcpkg_GlobalState.cpp +++ b/toolsrc/src/vcpkg_GlobalState.cpp @@ -4,7 +4,7 @@ namespace vcpkg { - ElapsedTime GlobalState::timer; - bool GlobalState::debugging = false; - bool GlobalState::feature_packages = false; + Util::LockGuarded GlobalState::timer; + std::atomic GlobalState::debugging = false; + std::atomic GlobalState::feature_packages = false; } diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp index f4e9a07c2..153e6a942 100644 --- a/toolsrc/src/vcpkg_Input.cpp +++ b/toolsrc/src/vcpkg_Input.cpp @@ -29,7 +29,7 @@ namespace vcpkg::Input if (!paths.is_valid_triplet(t)) { System::println(System::Color::error, "Error: invalid triplet: %s", t); - Metrics::track_property("error", "invalid triplet: " + t.to_string()); + Metrics::g_metrics.lock()->track_property("error", "invalid triplet: " + t.to_string()); Commands::Help::help_topic_valid_triplet(paths); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg_metrics_uploader.cpp b/toolsrc/src/vcpkg_metrics_uploader.cpp index 38bf7ff9c..c6670c625 100644 --- a/toolsrc/src/vcpkg_metrics_uploader.cpp +++ b/toolsrc/src/vcpkg_metrics_uploader.cpp @@ -11,5 +11,6 @@ int WINAPI WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ int) LPWSTR* szArgList = CommandLineToArgvW(GetCommandLineW(), &argCount); Checks::check_exit(VCPKG_LINE_INFO, argCount == 2, "Requires exactly one argument, the path to the payload file"); - Metrics::upload(Files::get_real_filesystem().read_contents(szArgList[1]).value_or_exit(VCPKG_LINE_INFO)); + auto v = Files::get_real_filesystem().read_contents(szArgList[1]).value_or_exit(VCPKG_LINE_INFO); + Metrics::g_metrics.lock()->upload(v); } diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index b52f49d62..96e9f05e1 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -117,7 +117,7 @@ namespace vcpkg if (!was_tracked) { was_tracked = true; - Metrics::track_property("listfile", "update to new format"); + Metrics::g_metrics.lock()->track_property("listfile", "update to new format"); } // The files are sorted such that directories are placed just before the files they contain -- cgit v1.2.3 From af017922974c4612517fe9c512df7cdd1ac79b43 Mon Sep 17 00:00:00 2001 From: Mikhail Paulyshka Date: Wed, 23 Aug 2017 00:48:39 +0300 Subject: [vcpkg] use UTF-8 for console input/output --- toolsrc/src/vcpkg.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 9da501ec0..fc9b1a016 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -18,6 +18,30 @@ using namespace vcpkg; +UINT console_cp_input; +UINT console_cp_output; + +void console_cp_set() +{ + console_cp_input = GetConsoleCP(); + console_cp_output = GetConsoleOutputCP(); + + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); +} + +void console_cp_reset() +{ + SetConsoleCP(console_cp_input); + SetConsoleOutputCP(console_cp_output); +} + +BOOL console_ctrl_handler(DWORD fdwCtrlType) +{ + console_cp_reset(); + return TRUE; +} + void invalid_command(const std::string& cmd) { System::println(System::Color::error, "invalid command: %s", cmd); @@ -192,6 +216,10 @@ int wmain(const int argc, const wchar_t* const* const argv) { if (argc == 0) std::abort(); + console_cp_set(); + SetConsoleCtrlHandler(PHANDLER_ROUTINE(console_ctrl_handler), TRUE); + atexit(console_cp_reset); + *GlobalState::timer.lock() = ElapsedTime::create_started(); // Checks::register_console_ctrl_handler(); -- cgit v1.2.3 From 67b9475ef29496508640f73410a10ecf737389eb Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 25 Aug 2017 16:55:14 -0700 Subject: [vcpkg] Set codepage to 65001, duplicate of #1682, fixes #1660 #1631 #1644 --- toolsrc/src/vcpkg.cpp | 36 ++++++------------------------------ toolsrc/src/vcpkg_Checks.cpp | 3 +++ toolsrc/src/vcpkg_GlobalState.cpp | 3 +++ 3 files changed, 12 insertions(+), 30 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index fc9b1a016..f37d079a6 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -18,30 +18,6 @@ using namespace vcpkg; -UINT console_cp_input; -UINT console_cp_output; - -void console_cp_set() -{ - console_cp_input = GetConsoleCP(); - console_cp_output = GetConsoleOutputCP(); - - SetConsoleCP(CP_UTF8); - SetConsoleOutputCP(CP_UTF8); -} - -void console_cp_reset() -{ - SetConsoleCP(console_cp_input); - SetConsoleOutputCP(console_cp_output); -} - -BOOL console_ctrl_handler(DWORD fdwCtrlType) -{ - console_cp_reset(); - return TRUE; -} - void invalid_command(const std::string& cmd) { System::println(System::Color::error, "invalid command: %s", cmd); @@ -216,13 +192,13 @@ int wmain(const int argc, const wchar_t* const* const argv) { if (argc == 0) std::abort(); - console_cp_set(); - SetConsoleCtrlHandler(PHANDLER_ROUTINE(console_ctrl_handler), TRUE); - atexit(console_cp_reset); + GlobalState::g_init_console_cp = GetConsoleCP(); + GlobalState::g_init_console_output_cp = GetConsoleOutputCP(); - *GlobalState::timer.lock() = ElapsedTime::create_started(); + SetConsoleCP(65001); + SetConsoleOutputCP(65001); - // Checks::register_console_ctrl_handler(); + *GlobalState::timer.lock() = ElapsedTime::create_started(); const std::string trimmed_command_line = trim_path_from_command_line(Strings::to_utf8(GetCommandLineW())); @@ -240,7 +216,7 @@ int wmain(const int argc, const wchar_t* const* const argv) if (auto p = args.sendmetrics.get()) Metrics::g_metrics.lock()->set_send_metrics(*p); if (auto p = args.debug.get()) GlobalState::debugging = *p; - vcpkg::Checks::register_console_ctrl_handler(); + Checks::register_console_ctrl_handler(); if (GlobalState::debugging) { diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp index d8d857daa..2ad2d06ab 100644 --- a/toolsrc/src/vcpkg_Checks.cpp +++ b/toolsrc/src/vcpkg_Checks.cpp @@ -17,6 +17,9 @@ namespace vcpkg::Checks GlobalState::debugging = false; metrics->flush(); + SetConsoleCP(GlobalState::g_init_console_cp); + SetConsoleOutputCP(GlobalState::g_init_console_output_cp); + ::exit(exit_code); } diff --git a/toolsrc/src/vcpkg_GlobalState.cpp b/toolsrc/src/vcpkg_GlobalState.cpp index c194da466..2221222c0 100644 --- a/toolsrc/src/vcpkg_GlobalState.cpp +++ b/toolsrc/src/vcpkg_GlobalState.cpp @@ -7,4 +7,7 @@ namespace vcpkg Util::LockGuarded GlobalState::timer; std::atomic GlobalState::debugging = false; std::atomic GlobalState::feature_packages = false; + + std::atomic GlobalState::g_init_console_cp = 0; + std::atomic GlobalState::g_init_console_output_cp = 0; } -- cgit v1.2.3 From 581aea74fb9737ee1efb0ae5d662ede8268b8e49 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 25 Aug 2017 23:34:44 -0700 Subject: [vcpkg] Use fgetws instead of fgets to accomodate non-ascii results --- toolsrc/src/vcpkg_System.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 2d6246d19..140f7d1b0 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -170,24 +170,24 @@ namespace vcpkg::System const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s 2>&1")###", cmd_line); Debug::println("_wpopen(%s)", Strings::to_utf8(actual_cmd_line)); - std::string output; - char buf[1024]; + std::wstring output; + wchar_t buf[1024]; auto pipe = _wpopen(actual_cmd_line.c_str(), L"r"); if (pipe == nullptr) { - return {1, output}; + return {1, Strings::to_utf8(output)}; } - while (fgets(buf, 1024, pipe)) + while (fgetws(buf, 1024, pipe)) { output.append(buf); } if (!feof(pipe)) { - return {1, output}; + return {1, Strings::to_utf8(output)}; } auto ec = _pclose(pipe); - Debug::println("_wpopen() returned %d", ec); - return {ec, output}; + Debug::println("_pclose() returned %d", ec); + return {ec, Strings::to_utf8(output)}; } std::wstring create_powershell_script_cmd(const fs::path& script_path, const CWStringView args) -- cgit v1.2.3 From 70949b0d814c469d76b8ddecc514ae0af6686347 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 26 Aug 2017 00:19:51 -0700 Subject: [vcpkg] Use vcvars argument strings from detected toolset. Avoid c-string pointer comparison. --- toolsrc/src/VcpkgPaths.cpp | 37 +++++++++++++++++-------------------- toolsrc/src/vcpkg_Build.cpp | 33 +++++++++------------------------ 2 files changed, 26 insertions(+), 44 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 642ca6a9c..7e3e5c736 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -302,25 +302,24 @@ namespace vcpkg paths_examined.push_back(vs2015_dumpbin_exe); const fs::path vs2015_bin_dir = vs2015_vcvarsall_bat.parent_path() / "bin"; - std::vector supported_archictectures; - if(fs.exists(vs2015_bin_dir / "vcvars32.bat")) - supported_archictectures.push_back({L"x86", CPU::X86, CPU::X86}); + std::vector supported_architectures; + if (fs.exists(vs2015_bin_dir / "vcvars32.bat")) + supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat")) - supported_archictectures.push_back({L"x64", CPU::X64, CPU::X64}); - if (fs.exists(vs2015_bin_dir / "arm\\vcvarsarm.bat")) - supported_archictectures.push_back({L"arm", CPU::ARM, CPU::ARM}); + supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) - supported_archictectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) - supported_archictectures.push_back({L"x86_arm" , CPU::X86, CPU::ARM}); + supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) - supported_archictectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) - supported_archictectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); if (fs.exists(vs2015_dumpbin_exe)) { - found_toolsets.push_back({vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140", supported_archictectures }); + found_toolsets.push_back( + {vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140", supported_architectures}); } } } @@ -337,22 +336,20 @@ namespace vcpkg paths_examined.push_back(vcvarsall_bat); if (!fs.exists(vcvarsall_bat)) continue; - //Get all supported architecturs + // Get all supported architectures std::vector supported_architectures; if (fs.exists(vcvarsall_dir / "vcvars32.bat")) - supported_architectures.push_back({L"x86", CPU::X86,CPU::X86 }); + supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); if (fs.exists(vcvarsall_dir / "vcvars64.bat")) - supported_architectures.push_back({L"amd64", CPU::X64,CPU::X64 }); - if (fs.exists(vcvarsall_dir / "vcvarsarm.bat")) - supported_architectures.push_back({L"arm", CPU::ARM,CPU::ARM }); + supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) - supported_architectures.push_back({L"x86_amd64",CPU::X86,CPU::X64 }); + supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) - supported_architectures.push_back({L"x86_arm", CPU::X86,CPU::ARM }); + supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) - supported_architectures.push_back({L"amd64_x86", CPU::X64,CPU::X86 }); + supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) - supported_architectures.push_back({L"amd64_arm", CPU::X64,CPU::ARM }); + supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); // Locate the "best" MSVC toolchain version const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index b0053766e..2b6950bc0 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -38,33 +38,18 @@ namespace vcpkg::Build CWStringView to_vcvarsall_toolchain(const std::string& target_architecture, const Toolset& toolset) { - using CPU = System::CPUArchitecture; - - static constexpr ToolsetArchOption X86 = {L"x86", CPU::X86, CPU::X86}; - static constexpr ToolsetArchOption X86_X64 = {L"x86_x64", CPU::X86, CPU::X64}; - static constexpr ToolsetArchOption X86_ARM = {L"x86_arm", CPU::X86, CPU::ARM}; - static constexpr ToolsetArchOption X86_ARM64 = {L"x86_arm64", CPU::X86, CPU::ARM64}; - - static constexpr ToolsetArchOption X64 = {L"amd64", CPU::X64, CPU::X64}; - static constexpr ToolsetArchOption X64_X86 = {L"amd64_x86", CPU::X64, CPU::X86}; - static constexpr ToolsetArchOption X64_ARM = {L"amd64_arm", CPU::X64, CPU::ARM}; - static constexpr ToolsetArchOption X64_ARM64 = {L"amd64_arm64", CPU::X64, CPU::ARM64}; - - static constexpr std::array VALUES = { - X64, X64_X86, X64_ARM, X64_ARM64, X86, X86_X64, X86_ARM, X86_ARM64}; - - auto target_arch = System::to_cpu_architecture(target_architecture); + auto maybe_target_arch = System::to_cpu_architecture(target_architecture); + Checks::check_exit( + VCPKG_LINE_INFO, maybe_target_arch.has_value(), "Invalid architecture string: %s", target_architecture); + auto target_arch = maybe_target_arch.value_or_exit(VCPKG_LINE_INFO); auto host_architectures = System::get_supported_host_architectures(); - for (auto&& value : VALUES) + for (auto&& host : host_architectures) { - if (target_arch != value.target_arch || - std::find(host_architectures.begin(), host_architectures.end(), value.host_arch) == host_architectures.end() || - std::find(toolset.supported_architectures.begin(), toolset.supported_architectures.end(), value) == toolset.supported_architectures.end() - ) - continue; - - return value.name; + auto it = Util::find_if(toolset.supported_architectures, [&](const ToolsetArchOption& opt) { + return host == opt.host_arch && target_arch == opt.target_arch; + }); + if (it != toolset.supported_architectures.end()) return it->name; } Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported toolchain combination %s", target_architecture); -- cgit v1.2.3 From 330b29732c8b178639f78c6fad10b9ec84f7669b Mon Sep 17 00:00:00 2001 From: atkawa7 Date: Sat, 26 Aug 2017 12:17:39 -0700 Subject: [vcpkg] free memory CommandLineToArgvW --- toolsrc/src/vcpkg_metrics_uploader.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_metrics_uploader.cpp b/toolsrc/src/vcpkg_metrics_uploader.cpp index c6670c625..cef4f4756 100644 --- a/toolsrc/src/vcpkg_metrics_uploader.cpp +++ b/toolsrc/src/vcpkg_metrics_uploader.cpp @@ -13,4 +13,6 @@ int WINAPI WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ int) Checks::check_exit(VCPKG_LINE_INFO, argCount == 2, "Requires exactly one argument, the path to the payload file"); auto v = Files::get_real_filesystem().read_contents(szArgList[1]).value_or_exit(VCPKG_LINE_INFO); Metrics::g_metrics.lock()->upload(v); + LocalFree(szArgList); + return 0; } -- cgit v1.2.3 From da299cb49cccd6cbcdcd18d66108311628337846 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 16:59:59 -0700 Subject: Add missing const keywords --- toolsrc/src/commands_export.cpp | 18 ++++++++---------- toolsrc/src/vcpkg.cpp | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index cbcb219b6..dbfb09aab 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -67,7 +67,7 @@ namespace vcpkg::Commands::Export for (const ExportPlanType plan_type : order) { - auto it = group_by_plan_type.find(plan_type); + const auto it = group_by_plan_type.find(plan_type); if (it == group_by_plan_type.cend()) { continue; @@ -205,11 +205,9 @@ namespace vcpkg::Commands::Export static Optional maybe_lookup(std::unordered_map const& m, std::string const& key) { - auto it = m.find(key); - if (it != m.end()) - return it->second; - else - return nullopt; + const auto it = m.find(key); + if (it != m.end()) return it->second; + return nullopt; } void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) @@ -266,7 +264,7 @@ namespace vcpkg::Commands::Export VCPKG_LINE_INFO, !maybe_nuget_version || nuget, "--nuget-version is only valid with --nuget"); // create the plan - StatusParagraphs status_db = database_load_check(paths); + const StatusParagraphs status_db = database_load_check(paths); std::vector export_plan = Dependencies::create_export_plan(paths, specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty"); @@ -285,7 +283,7 @@ namespace vcpkg::Commands::Export "Additional packages (*) need to be exported to complete this operation."); } - auto it = group_by_plan_type.find(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT); + const auto it = group_by_plan_type.find(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT); if (it != group_by_plan_type.cend() && !it->second.empty()) { System::println(System::Color::error, "There are packages that have not been built."); @@ -295,7 +293,7 @@ namespace vcpkg::Commands::Export Util::erase_remove_if( unbuilt, [](const ExportPlanAction* a) { return a->request_type != RequestType::USER_REQUESTED; }); - auto s = Strings::join(" ", unbuilt, [](const ExportPlanAction* a) { return a->spec.to_string(); }); + const auto s = Strings::join(" ", unbuilt, [](const ExportPlanAction* a) { return a->spec.to_string(); }); System::println("To build them, run:\n" " vcpkg install %s", s); @@ -360,7 +358,7 @@ namespace vcpkg::Commands::Export Checks::check_exit(VCPKG_LINE_INFO, !ec); } - auto print_next_step_info = [](const fs::path& prefix) { + const auto print_next_step_info = [](const fs::path& prefix) { const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; const CMakeVariable cmake_variable = CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index f37d079a6..781f03585 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -34,7 +34,7 @@ static void inner(const VcpkgCmdArguments& args) Checks::exit_fail(VCPKG_LINE_INFO); } - if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_c())) + if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_c())) { return command_function(args); } @@ -47,7 +47,7 @@ static void inner(const VcpkgCmdArguments& args) else { const Optional vcpkg_root_dir_env = System::get_environment_variable(L"VCPKG_ROOT"); - if (auto v = vcpkg_root_dir_env.get()) + if (const auto v = vcpkg_root_dir_env.get()) { vcpkg_root_dir = fs::stdfs::absolute(*v); } @@ -67,10 +67,10 @@ static void inner(const VcpkgCmdArguments& args) vcpkg_root_dir.string(), expected_paths.error().message()); const VcpkgPaths paths = expected_paths.value_or_exit(VCPKG_LINE_INFO); - int exit_code = _wchdir(paths.root.c_str()); + const int exit_code = _wchdir(paths.root.c_str()); Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed"); - if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_b())) + if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_b())) { return command_function(args, paths); } @@ -84,7 +84,7 @@ static void inner(const VcpkgCmdArguments& args) { const Optional vcpkg_default_triplet_env = System::get_environment_variable(L"VCPKG_DEFAULT_TRIPLET"); - if (auto v = vcpkg_default_triplet_env.get()) + if (const auto v = vcpkg_default_triplet_env.get()) { default_triplet = Triplet::from_canonical_name(Strings::to_utf8(*v)); } @@ -96,7 +96,7 @@ static void inner(const VcpkgCmdArguments& args) Input::check_triplet(default_triplet, paths); - if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_a())) + if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_a())) { return command_function(args, paths, default_triplet); } @@ -118,7 +118,7 @@ static void loadConfig() try { auto maybe_pghs = Paragraphs::get_paragraphs(Files::get_real_filesystem(), localappdata / "vcpkg" / "config"); - if (auto p_pghs = maybe_pghs.get()) + if (const auto p_pghs = maybe_pghs.get()) { const auto& pghs = *p_pghs; @@ -212,9 +212,9 @@ int wmain(const int argc, const wchar_t* const* const argv) const VcpkgCmdArguments args = VcpkgCmdArguments::create_from_command_line(argc, argv); - if (auto p = args.printmetrics.get()) Metrics::g_metrics.lock()->set_print_metrics(*p); - if (auto p = args.sendmetrics.get()) Metrics::g_metrics.lock()->set_send_metrics(*p); - if (auto p = args.debug.get()) GlobalState::debugging = *p; + if (const auto p = args.printmetrics.get()) Metrics::g_metrics.lock()->set_print_metrics(*p); + if (const auto p = args.sendmetrics.get()) Metrics::g_metrics.lock()->set_send_metrics(*p); + if (const auto p = args.debug.get()) GlobalState::debugging = *p; Checks::register_console_ctrl_handler(); -- cgit v1.2.3 From 75cc10b0f3351241588d307c625138aa358499fe Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 17:10:50 -0700 Subject: Add missing const --- toolsrc/src/BinaryParagraph.cpp | 2 +- toolsrc/src/coff_file_reader.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index 9abd388b9..97923c3c4 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -56,7 +56,7 @@ namespace vcpkg this->default_features = parse_comma_list(parser.optional_field(Fields::DEFAULTFEATURES)); } - if (auto err = parser.error_info(this->spec.to_string())) + if (const auto err = parser.error_info(this->spec.to_string())) { System::println( System::Color::error, "Error: while parsing the Binary Paragraph for %s", this->spec.to_string()); diff --git a/toolsrc/src/coff_file_reader.cpp b/toolsrc/src/coff_file_reader.cpp index 6c38c452b..10c1437c6 100644 --- a/toolsrc/src/coff_file_reader.cpp +++ b/toolsrc/src/coff_file_reader.cpp @@ -24,7 +24,7 @@ namespace vcpkg::COFFFileReader template static T peek_value_from_stream(fstream& fs) { - fpos_t original_pos = fs.tellg().seekpos(); + const fpos_t original_pos = fs.tellg().seekpos(); T data; fs.read(reinterpret_cast(&data), sizeof data); fs.seekg(original_pos); @@ -236,7 +236,7 @@ namespace vcpkg::COFFFileReader read_and_verify_PE_signature(fs); CoffFileHeader header = CoffFileHeader::read(fs); - MachineType machine = header.machine_type(); + const MachineType machine = header.machine_type(); return {machine}; } @@ -282,7 +282,7 @@ namespace vcpkg::COFFFileReader marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + second_linker_member_header.member_size()); marker.seek_to_marker(fs); - bool hasLongnameMemberHeader = peek_value_from_stream(fs) == 0x2F2F; + const bool hasLongnameMemberHeader = peek_value_from_stream(fs) == 0x2F2F; if (hasLongnameMemberHeader) { const ArchiveMemberHeader longnames_member_header = ArchiveMemberHeader::read(fs); -- cgit v1.2.3 From 269c6b4d55192492d8ad254723b5883f13794314 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 17:12:42 -0700 Subject: Use const. Take str by reference --- toolsrc/src/commands_build.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index 4da9cede2..71cd1b845 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -29,8 +29,8 @@ namespace vcpkg::Commands::BuildCommand const PackageSpec& spec = full_spec.package_spec; if (options.find(OPTION_CHECKS_ONLY) != options.end()) { - auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet()); - auto build_info = Build::read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); + const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet()); + const auto build_info = Build::read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); Checks::check_exit(VCPKG_LINE_INFO, error_count == 0); Checks::exit_success(VCPKG_LINE_INFO); @@ -45,7 +45,7 @@ namespace vcpkg::Commands::BuildCommand Checks::exit_fail(VCPKG_LINE_INFO); } - for (std::string str : full_spec.features) + for (const std::string& str : full_spec.features) { System::println("%s \n", str); } @@ -56,8 +56,8 @@ namespace vcpkg::Commands::BuildCommand scf->core_paragraph->name, spec.name()); - StatusParagraphs status_db = database_load_check(paths); - Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; + const StatusParagraphs status_db = database_load_check(paths); + const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; const Build::BuildPackageConfig build_config{ *scf->core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options}; @@ -92,7 +92,7 @@ namespace vcpkg::Commands::BuildCommand static const std::string example = Commands::Help::create_example_string("build zlib:x64-windows"); args.check_exact_arg_count( 1, example); // Build only takes a single package and all dependencies must already be installed - std::string command_argument = args.command_arguments.at(0); + const std::string command_argument = args.command_arguments.at(0); const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, example); Input::check_triplet(spec.package_spec.triplet(), paths); const std::unordered_set options = -- cgit v1.2.3 From 4a43e3e7f954cb79a71ab05dde6b5345d011db83 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 17:16:38 -0700 Subject: Use const --- toolsrc/src/commands_cache.cpp | 2 +- toolsrc/src/commands_depends.cpp | 2 +- toolsrc/src/commands_edit.cpp | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_cache.cpp b/toolsrc/src/commands_cache.cpp index 75de78461..fa0c62ee4 100644 --- a/toolsrc/src/commands_cache.cpp +++ b/toolsrc/src/commands_cache.cpp @@ -15,7 +15,7 @@ namespace vcpkg::Commands::Cache { const Expected> pghs = Paragraphs::get_single_paragraph(paths.get_filesystem(), path / "CONTROL"); - if (auto p = pghs.get()) + if (const auto p = pghs.get()) { const BinaryParagraph binary_paragraph = BinaryParagraph(*p); output.push_back(binary_paragraph); diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index 49e1c6c01..ffad91226 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -46,7 +46,7 @@ namespace vcpkg::Commands::DependInfo for (auto&& source_control_file : source_control_files) { const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; - auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name(); }); + const auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name(); }); System::println("%s: %s", source_paragraph.name, s); } diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index 72005a461..c0fe27fde 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -27,7 +27,7 @@ namespace vcpkg::Commands::Edit if (env_EDITOR.empty()) { const Optional env_EDITOR_optional = System::get_environment_variable(L"EDITOR"); - if (auto e = env_EDITOR_optional.get()) + if (const auto e = env_EDITOR_optional.get()) { env_EDITOR = *e; } @@ -63,7 +63,7 @@ namespace vcpkg::Commands::Edit { const Optional code_installpath = System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation"); - if (auto c = code_installpath.get()) + if (const auto c = code_installpath.get()) { auto p = fs::path(*c) / "Code.exe"; if (fs.exists(p)) @@ -91,11 +91,12 @@ namespace vcpkg::Commands::Edit { const auto buildtrees_current_dir = paths.buildtrees / port_name; - std::wstring cmdLine = Strings::wformat(LR"("%s" "%s" -n)", env_EDITOR, buildtrees_current_dir.native()); + const std::wstring cmdLine = + Strings::wformat(LR"("%s" "%s" -n)", env_EDITOR, buildtrees_current_dir.native()); Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmdLine)); } - std::wstring cmdLine = Strings::wformat( + const std::wstring cmdLine = Strings::wformat( LR"("%s" "%s" "%s" -n)", env_EDITOR, portpath.native(), (portpath / "portfile.cmake").native()); Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmdLine)); } -- cgit v1.2.3 From 0404a51e4a13f37a280241812ccddd745a4ca129 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 17:20:29 -0700 Subject: [edit] Fix variable names to be consistence with vcpkg's convention --- toolsrc/src/commands_edit.cpp | 54 +++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index c0fe27fde..e72931e63 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -12,8 +12,8 @@ namespace vcpkg::Commands::Edit auto& fs = paths.get_filesystem(); - static const std::string example = Commands::Help::create_example_string("edit zlib"); - args.check_exact_arg_count(1, example); + static const std::string EXAMPLE = Commands::Help::create_example_string("edit zlib"); + args.check_exact_arg_count(1, EXAMPLE); const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_BUILDTREES}); const std::string port_name = args.command_arguments.at(0); @@ -22,44 +22,44 @@ namespace vcpkg::Commands::Edit Checks::check_exit(VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name); // Find the user's selected editor - std::wstring env_EDITOR; + std::wstring env_editor; - if (env_EDITOR.empty()) + if (env_editor.empty()) { - const Optional env_EDITOR_optional = System::get_environment_variable(L"EDITOR"); - if (const auto e = env_EDITOR_optional.get()) + const Optional env_editor_optional = System::get_environment_variable(L"EDITOR"); + if (const auto e = env_editor_optional.get()) { - env_EDITOR = *e; + env_editor = *e; } } - if (env_EDITOR.empty()) + if (env_editor.empty()) { - const fs::path CODE_EXE_PATH = System::get_ProgramFiles_platform_bitness() / "Microsoft VS Code/Code.exe"; - if (fs.exists(CODE_EXE_PATH)) + const fs::path code_exe_path = System::get_ProgramFiles_platform_bitness() / "Microsoft VS Code/Code.exe"; + if (fs.exists(code_exe_path)) { - env_EDITOR = CODE_EXE_PATH; + env_editor = code_exe_path; } } - if (env_EDITOR.empty()) + if (env_editor.empty()) { - const fs::path CODE_EXE_PATH = System::get_ProgramFiles_32_bit() / "Microsoft VS Code/Code.exe"; - if (fs.exists(CODE_EXE_PATH)) + const fs::path code_exe_path = System::get_ProgramFiles_32_bit() / "Microsoft VS Code/Code.exe"; + if (fs.exists(code_exe_path)) { - env_EDITOR = CODE_EXE_PATH; + env_editor = code_exe_path; } } - if (env_EDITOR.empty()) + if (env_editor.empty()) { - static const std::array regkeys = { + static const std::array REGKEYS = { LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", }; - for (auto&& keypath : regkeys) + for (auto&& keypath : REGKEYS) { const Optional code_installpath = System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation"); @@ -68,20 +68,20 @@ namespace vcpkg::Commands::Edit auto p = fs::path(*c) / "Code.exe"; if (fs.exists(p)) { - env_EDITOR = p.native(); + env_editor = p.native(); break; } auto p_insiders = fs::path(*c) / "Code - Insiders.exe"; if (fs.exists(p_insiders)) { - env_EDITOR = p_insiders.native(); + env_editor = p_insiders.native(); break; } } } } - if (env_EDITOR.empty()) + if (env_editor.empty()) { Checks::exit_with_message( VCPKG_LINE_INFO, "Visual Studio Code was not found and the environment variable EDITOR is not set"); @@ -91,13 +91,13 @@ namespace vcpkg::Commands::Edit { const auto buildtrees_current_dir = paths.buildtrees / port_name; - const std::wstring cmdLine = - Strings::wformat(LR"("%s" "%s" -n)", env_EDITOR, buildtrees_current_dir.native()); - Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmdLine)); + const std::wstring cmd_line = + Strings::wformat(LR"("%s" "%s" -n)", env_editor, buildtrees_current_dir.native()); + Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); } - const std::wstring cmdLine = Strings::wformat( - LR"("%s" "%s" "%s" -n)", env_EDITOR, portpath.native(), (portpath / "portfile.cmake").native()); - Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmdLine)); + const std::wstring cmd_line = Strings::wformat( + LR"("%s" "%s" "%s" -n)", env_editor, portpath.native(), (portpath / "portfile.cmake").native()); + Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); } } -- cgit v1.2.3 From 98074f5a21717a851323019b75d9c0fdb599eaae Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 17:21:34 -0700 Subject: [commands_env.cpp] Use const. Naming scheme --- toolsrc/src/commands_env.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_env.cpp b/toolsrc/src/commands_env.cpp index dd7172b89..073c501f5 100644 --- a/toolsrc/src/commands_env.cpp +++ b/toolsrc/src/commands_env.cpp @@ -8,12 +8,13 @@ namespace vcpkg::Commands::Env { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string example = Commands::Help::create_example_string(R"(env --Triplet x64-windows)"); - args.check_exact_arg_count(0, example); + static const std::string EXAMPLE = Commands::Help::create_example_string(R"(env --Triplet x64-windows)"); + args.check_exact_arg_count(0, EXAMPLE); args.check_and_get_optional_command_arguments({}); - auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); - System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, paths.get_toolset(pre_build_info.platform_toolset)) + L" && cmd"); + const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); + System::cmd_execute_clean( + Build::make_build_env_cmd(pre_build_info, paths.get_toolset(pre_build_info.platform_toolset)) + L" && cmd"); Checks::exit_success(VCPKG_LINE_INFO); } -- cgit v1.2.3 From 4d952a5e1d286e281a837f332fbac9e43866d933 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 17:22:40 -0700 Subject: [commands_hash.cpp] Use const. Naming scheme. --- toolsrc/src/commands_hash.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_hash.cpp b/toolsrc/src/commands_hash.cpp index 0da2b031f..b3211b9f8 100644 --- a/toolsrc/src/commands_hash.cpp +++ b/toolsrc/src/commands_hash.cpp @@ -6,22 +6,22 @@ namespace vcpkg::Commands::Hash { - static void do_file_hash(fs::path const& path, std::wstring const& hashType) + static void do_file_hash(fs::path const& path, std::wstring const& hash_type) { - auto cmd_line = Strings::wformat(LR"(CertUtil.exe -hashfile "%s" %s)", path.c_str(), hashType); - auto ec_data = System::cmd_execute_and_capture_output(cmd_line); + const auto cmd_line = Strings::wformat(LR"(CertUtil.exe -hashfile "%s" %s)", path.c_str(), hash_type); + const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); Checks::check_exit( VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::to_utf8(cmd_line)); std::string const& output = ec_data.output; - auto start = output.find_first_of("\r\n"); + const auto start = output.find_first_of("\r\n"); Checks::check_exit(VCPKG_LINE_INFO, start != std::string::npos, "Unexpected output format from command: %s", Strings::to_utf8(cmd_line)); - auto end = output.find_first_of("\r\n", start + 1); + const auto end = output.find_first_of("\r\n", start + 1); Checks::check_exit(VCPKG_LINE_INFO, end != std::string::npos, "Unexpected output format from command: %s", @@ -34,11 +34,11 @@ namespace vcpkg::Commands::Hash void perform_and_exit(const VcpkgCmdArguments& args) { - static const std::string example = + static const std::string EXAMPLE = Strings::format("The argument should be a file path\n%s", Commands::Help::create_example_string("hash boost_1_62_0.tar.bz2")); - args.check_min_arg_count(1, example); - args.check_max_arg_count(2, example); + args.check_min_arg_count(1, EXAMPLE); + args.check_max_arg_count(2, EXAMPLE); args.check_and_get_optional_command_arguments({}); if (args.command_arguments.size() == 1) -- cgit v1.2.3 From 5b42ec9b5d7277d9a4452c4c3a109770d9437205 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 28 Aug 2017 17:26:01 -0700 Subject: [vcpkg] Hack to fix codepage problems -- root cause unknown --- toolsrc/src/VcpkgPaths.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 1b76fdc24..4bceff784 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -264,7 +264,14 @@ namespace vcpkg const std::wstring cmd = System::create_powershell_script_cmd(script); System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect VS 2017 instances"); - return Strings::split(ec_data.output, "\n"); + return Util::fmap(Strings::split(ec_data.output, "\n"), [](const std::string& line) { + auto colon_pos = line.find(':'); + if (colon_pos != std::string::npos && colon_pos > 0) + { + return line.substr(colon_pos - 1); + } + return line; + }); } static Optional get_VS2015_installation_instance() -- cgit v1.2.3 From f3156ae3e4b62159c178f12cdba58e6a661832d0 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 18:01:24 -0700 Subject: [vcpkg_Build.cpp] USe const. Misc fixes --- toolsrc/src/vcpkg_Build.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index 0ae63d4e3..bec9c9ef7 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -64,8 +64,8 @@ namespace vcpkg::Build tonull = L""; } - auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset); - auto target = to_vcvarsall_target(pre_build_info.cmake_system_name); + const auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset); + const auto target = to_vcvarsall_target(pre_build_info.cmake_system_name); return Strings::wformat(LR"("%s" %s %s %s 2>&1)", toolset.vcvarsall.native(), arch, target, tonull); } @@ -85,7 +85,7 @@ namespace vcpkg::Build BinaryControlFile& bcf) { BinaryParagraph bpgh(source_paragraph, triplet); - if (auto p_ver = build_info.version.get()) + if (const auto p_ver = build_info.version.get()) { bpgh.version = *p_ver; } @@ -132,7 +132,7 @@ namespace vcpkg::Build const fs::path& git_exe_path = paths.get_git_exe(); const fs::path ports_cmake_script_path = paths.ports_cmake; - auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); + const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); @@ -171,8 +171,8 @@ namespace vcpkg::Build const ElapsedTime timer = ElapsedTime::create_started(); - int return_code = System::cmd_execute_clean(command); - auto buildtimeus = timer.microseconds(); + const int return_code = System::cmd_execute_clean(command); + const auto buildtimeus = timer.microseconds(); const auto spec_string = spec.to_string(); { @@ -186,7 +186,7 @@ namespace vcpkg::Build } } - auto build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); + const BuildInfo build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); BinaryControlFile bcf; @@ -269,7 +269,7 @@ namespace vcpkg::Build parser.required_field(BuildInfoRequiredField::CRT_LINKAGE, crt_linkage_as_string); auto crtlinkage = to_linkage_type(crt_linkage_as_string); - if (auto p = crtlinkage.get()) + if (const auto p = crtlinkage.get()) build_info.crt_linkage = *p; else Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid crt linkage type: [%s]", crt_linkage_as_string); @@ -279,7 +279,7 @@ namespace vcpkg::Build std::string library_linkage_as_string; parser.required_field(BuildInfoRequiredField::LIBRARY_LINKAGE, library_linkage_as_string); auto liblinkage = to_linkage_type(library_linkage_as_string); - if (auto p = liblinkage.get()) + if (const auto p = liblinkage.get()) build_info.library_linkage = *p; else Checks::exit_with_message( @@ -292,9 +292,8 @@ namespace vcpkg::Build for (auto policy : g_all_policies) { const auto setting = parser.optional_field(to_string(policy)); - if (setting.empty()) - continue; - else if (setting == "enabled") + if (setting.empty()) continue; + if (setting == "enabled") policies.emplace(policy, true); else if (setting == "disabled") policies.emplace(policy, false); @@ -303,7 +302,7 @@ namespace vcpkg::Build VCPKG_LINE_INFO, "Unknown setting for policy '%s': %s", to_string(policy), setting); } - if (auto err = parser.error_info("PostBuildInformation")) + if (const auto err = parser.error_info("PostBuildInformation")) { print_error_message(err); Checks::exit_fail(VCPKG_LINE_INFO); @@ -337,14 +336,14 @@ namespace vcpkg::Build }); const std::wstring command = Strings::wformat(LR"(%s)", cmd_launch_cmake); - auto ec_data = System::cmd_execute_and_capture_output(command); + const auto ec_data = System::cmd_execute_and_capture_output(command); Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0); const std::vector lines = Strings::split(ec_data.output, "\n"); PreBuildInfo pre_build_info; - auto e = lines.cend(); + const auto e = lines.cend(); auto cur = std::find(lines.cbegin(), e, FLAG_GUID); if (cur != e) ++cur; -- cgit v1.2.3 From 63a9572ecfeccc143de6bc10a23c453823996dff Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 18:03:01 -0700 Subject: [vcpkg_Dependencies.cpp] Order of initialization --- toolsrc/src/vcpkg_Dependencies.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 4525fa02a..279f5f870 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -166,7 +166,7 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const AnyParagraph& any_paragraph, const RequestType& request_type) - : spec(spec), request_type(request_type), plan_type(InstallPlanType::UNKNOWN), any_paragraph(any_paragraph) + : spec(spec), any_paragraph(any_paragraph), plan_type(InstallPlanType::UNKNOWN), request_type(request_type) { if (auto p = any_paragraph.status_paragraph.get()) { -- cgit v1.2.3 From 174c264b449dc77ab71ae07aa78673239ebd0c48 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 18:03:43 -0700 Subject: [vcpkg_Dependencies.cpp] Remove redundant else --- toolsrc/src/vcpkg_Dependencies.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 279f5f870..2c619c3ac 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -193,17 +193,15 @@ namespace vcpkg::Dependencies { return this->spec.to_string(); } - else - { - std::string features; - for (auto&& feature : this->feature_list) - { - features += feature + ","; - } - features.pop_back(); - return this->spec.name() + "[" + features + "]:" + this->spec.triplet().to_string(); + std::string features; + for (auto&& feature : this->feature_list) + { + features += feature + ","; } + features.pop_back(); + + return this->spec.name() + "[" + features + "]:" + this->spec.triplet().to_string(); } bool InstallPlanAction::compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right) -- cgit v1.2.3 From c2571cf8bca08bc6d1de7e23025a0dfdb1db4bb9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 18:37:36 -0700 Subject: Use Strings::join() and Strings::format() --- toolsrc/src/vcpkg_Dependencies.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 2c619c3ac..57f475df5 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -7,6 +7,7 @@ #include "vcpkg_Dependencies.h" #include "vcpkg_Files.h" #include "vcpkg_Graphs.h" +#include "vcpkg_Strings.h" #include "vcpkg_Util.h" #include "vcpkglib.h" @@ -194,14 +195,8 @@ namespace vcpkg::Dependencies return this->spec.to_string(); } - std::string features; - for (auto&& feature : this->feature_list) - { - features += feature + ","; - } - features.pop_back(); - - return this->spec.name() + "[" + features + "]:" + this->spec.triplet().to_string(); + const std::string features = Strings::join(",", this->feature_list); + return Strings::format("%s[%s]:%s", this->spec.name(), features, this->spec.triplet()); } bool InstallPlanAction::compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right) -- cgit v1.2.3 From b1cebc0740765b90af905d6f1c90ea9830506e1b Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 18:39:10 -0700 Subject: Make member functions const --- toolsrc/src/vcpkg_Dependencies.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 57f475df5..4d0c3c928 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -37,7 +37,7 @@ namespace vcpkg::Dependencies { Cluster* ptr; - Cluster* operator->() { return ptr; } + Cluster* operator->() const { return ptr; } }; bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } @@ -87,7 +87,7 @@ namespace vcpkg::Dependencies } private: - void cluster_from_scf(const SourceControlFile& scf, Cluster& out_cluster) + void cluster_from_scf(const SourceControlFile& scf, Cluster& out_cluster) const { FeatureNodeEdges core_dependencies; core_dependencies.build_edges = -- cgit v1.2.3 From 7d46adb47ca332a072ffb382e4a533aa68a17062 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 18:46:28 -0700 Subject: Use Strings::EMPTY --- toolsrc/src/BinaryParagraph.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index 97923c3c4..783fa6ace 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -80,10 +80,10 @@ namespace vcpkg BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, const Triplet& triplet) { this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); - this->version = ""; + this->version = Strings::EMPTY; this->feature = fpgh.name; this->description = fpgh.description; - this->maintainer = ""; + this->maintainer = Strings::EMPTY; this->depends = filter_dependencies(fpgh.depends, triplet); } -- cgit v1.2.3 From f3d803addfb3d84d828786d2e6b0b8a34f2fc494 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 18:54:48 -0700 Subject: Introduce Strings::is_empty() --- toolsrc/src/vcpkg_Strings.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 0c1c1f9f9..b5ea338de 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -71,6 +71,9 @@ namespace vcpkg::Strings::details namespace vcpkg::Strings { + bool is_empty(const CStringView s) { return s == EMPTY; } + bool is_empty(const CWStringView s) { return s == WEMPTY; } + std::wstring to_utf16(const CStringView s) { std::wstring_convert, wchar_t> conversion; -- cgit v1.2.3 From 4a6b43c15a2b6c121686355f37443da6e2d05c9b Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 18:55:27 -0700 Subject: Improve BinaryParagraph::displayname() --- toolsrc/src/BinaryParagraph.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index 783fa6ace..1ab1aa63e 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -89,14 +89,8 @@ namespace vcpkg std::string BinaryParagraph::displayname() const { - if (this->feature == "") - { - return this->spec.name() + "[core]:" + this->spec.triplet().to_string(); - } - else - { - return this->spec.name() + "[" + this->feature + "]:" + this->spec.triplet().to_string(); - } + const auto f = Strings::is_empty(this->feature) ? "core" : this->feature; + return Strings::format("%s[%s]:%s", this->spec.name(), f, this->spec.triplet()); } std::string BinaryParagraph::dir() const { return this->spec.dir(); } -- cgit v1.2.3 From d02d44b0f12ae0603c5578bdcc4c0a51a3e309c7 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 18:58:59 -0700 Subject: Use Strings::EMPTY instead of "" --- toolsrc/src/commands_build.cpp | 4 ++-- toolsrc/src/commands_install.cpp | 2 +- toolsrc/src/commands_version.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index 71cd1b845..421568ce5 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -68,12 +68,12 @@ namespace vcpkg::Commands::BuildCommand System::println(System::Color::error, "The build command requires all dependencies to be already installed."); System::println("The following dependencies are missing:"); - System::println(""); + System::println(Strings::EMPTY); for (const auto& p : result.unmet_dependencies) { System::println(" %s", p); } - System::println(""); + System::println(Strings::EMPTY); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index a2e95eb48..1c474f7b0 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -199,7 +199,7 @@ namespace vcpkg::Commands::Install bcf.core_paragraph.spec); System::print("\n "); System::println(Strings::join("\n ", intersection)); - System::println(""); + System::println(Strings::EMPTY); return InstallResult::FILE_CONFLICTS; } diff --git a/toolsrc/src/commands_version.cpp b/toolsrc/src/commands_version.cpp index cd21f2561..af81cd26e 100644 --- a/toolsrc/src/commands_version.cpp +++ b/toolsrc/src/commands_version.cpp @@ -20,7 +20,7 @@ namespace vcpkg::Commands::Version #ifndef NDEBUG + std::string("-debug") #endif - + std::string(Metrics::get_compiled_metrics_enabled() ? "" : "-external"); + + std::string(Metrics::get_compiled_metrics_enabled() ? Strings::EMPTY : "-external"); return s_version; } -- cgit v1.2.3 From 992f192c5e937f22877117e64ff7a38a6447c4bc Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 19:29:12 -0700 Subject: Add System::println() with no args --- toolsrc/src/vcpkg_System.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 481f2431e..c48f719e1 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -48,8 +48,8 @@ namespace vcpkg::System std::vector supported_architectures; supported_architectures.push_back(get_host_processor()); - //AMD64 machines support to run x86 applications - if(supported_architectures.back()==CPUArchitecture::X64) + // AMD64 machines support to run x86 applications + if (supported_architectures.back() == CPUArchitecture::X64) { supported_architectures.push_back(CPUArchitecture::X86); } @@ -211,6 +211,8 @@ namespace vcpkg::System LR"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.native(), args); } + void println() { println(Strings::EMPTY); } + void print(const CStringView message) { fputs(message, stdout); } void println(const CStringView message) -- cgit v1.2.3 From 6684240090512f745bf7530b2fb4bcd31c3fb02e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 19:29:55 -0700 Subject: Use Strings::EMPTY --- toolsrc/src/PackageSpec.cpp | 4 ++-- toolsrc/src/commands_remove.cpp | 2 +- toolsrc/src/metrics.cpp | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index a43bc5ff5..890de8899 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -38,7 +38,7 @@ namespace vcpkg for (auto&& feature : spec->features) f_specs.push_back(FeatureSpec{pspec, feature}); - if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, ""}); + if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, Strings::EMPTY}); } else { @@ -56,7 +56,7 @@ namespace vcpkg std::vector ret; for (auto&& spec : specs) { - ret.emplace_back(spec.package_spec, ""); + ret.emplace_back(spec.package_spec, Strings::EMPTY); for (auto&& feature : spec.features) ret.emplace_back(spec.package_spec, feature); } diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index db5357514..cca541c85 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -18,7 +18,7 @@ namespace vcpkg::Commands::Remove { auto& fs = paths.get_filesystem(); auto spghs = status_db->find_all(spec.name(), spec.triplet()); - auto core_pkg = **status_db->find(spec.name(), spec.triplet(), ""); + auto core_pkg = **status_db->find(spec.name(), spec.triplet(), Strings::EMPTY); for (auto&& spgh : spghs) { diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp index 6263c0fcb..8a7d02a30 100644 --- a/toolsrc/src/metrics.cpp +++ b/toolsrc/src/metrics.cpp @@ -25,7 +25,7 @@ namespace vcpkg::Metrics errno_t err = gmtime_s(&newtime, &now); if (err) { - return ""; + return Strings::EMPTY; } strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S", &newtime); @@ -125,16 +125,16 @@ namespace vcpkg::Metrics path += L"\\kernel32.dll"; auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr); - if (versz == 0) return ""; + if (versz == 0) return Strings::EMPTY; std::vector verbuf; verbuf.resize(versz); - if (!GetFileVersionInfoW(path.c_str(), 0, static_cast(verbuf.size()), &verbuf[0])) return ""; + if (!GetFileVersionInfoW(path.c_str(), 0, static_cast(verbuf.size()), &verbuf[0])) return Strings::EMPTY; void* rootblock; UINT rootblocksize; - if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return ""; + if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return Strings::EMPTY; auto rootblock_ffi = static_cast(rootblock); @@ -377,7 +377,7 @@ namespace vcpkg::Metrics path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; if (fs.exists(path)) return path; - return L""; + return Strings::WEMPTY; }(); std::error_code ec; -- cgit v1.2.3 From 03c4c7f8c49d103f57fe12899526b27fc8ccc452 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 19:32:07 -0700 Subject: Use System::println() with no args --- toolsrc/src/PostBuildLint.cpp | 16 ++++++++-------- toolsrc/src/commands_build.cpp | 4 ++-- toolsrc/src/commands_install.cpp | 2 +- toolsrc/src/vcpkg_Files.cpp | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index a5d923ad2..473c81cfa 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -10,9 +10,9 @@ #include "vcpkg_System.h" #include "vcpkg_Util.h" -using vcpkg::Build::PreBuildInfo; using vcpkg::Build::BuildInfo; using vcpkg::Build::BuildPolicy; +using vcpkg::Build::PreBuildInfo; namespace vcpkg::PostBuildLint { @@ -369,12 +369,12 @@ namespace vcpkg::PostBuildLint std::vector binaries_with_invalid_architecture) { System::println(System::Color::warning, "The following files were built for an incorrect architecture:"); - System::println(""); + System::println(); for (const FileAndArch& b : binaries_with_invalid_architecture) { System::println(" %s", b.file.generic_string()); System::println("Expected %s, but was: %s", expected_architecture, b.actual_arch); - System::println(""); + System::println(); } } @@ -487,7 +487,7 @@ namespace vcpkg::PostBuildLint System::println(System::Color::warning, "Release binaries were not found"); } - System::println(""); + System::println(); return LintStatus::ERROR_DETECTED; } @@ -621,12 +621,12 @@ namespace vcpkg::PostBuildLint System::println(System::Color::warning, "Expected %s crt linkage, but the following libs had invalid crt linkage:", expected_build_type.to_string()); - System::println(""); + System::println(); for (const BuildType_and_file btf : libs_with_invalid_crt) { System::println(" %s: %s", btf.file.generic_string(), btf.build_type.to_string()); } - System::println(""); + System::println(); System::println(System::Color::warning, "To inspect the lib files, use:\n dumpbin.exe /directives mylibfile.lib"); @@ -675,12 +675,12 @@ namespace vcpkg::PostBuildLint if (!dlls_with_outdated_crt.empty()) { System::println(System::Color::warning, "Detected outdated dynamic CRT in the following files:"); - System::println(""); + System::println(); for (const OutdatedDynamicCrt_and_file btf : dlls_with_outdated_crt) { System::println(" %s: %s", btf.file.generic_string(), btf.outdated_crt.name); } - System::println(""); + System::println(); System::println(System::Color::warning, "To inspect the dll files, use:\n dumpbin.exe /dependents mydllfile.dll"); diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index 421568ce5..26a783a4b 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -68,12 +68,12 @@ namespace vcpkg::Commands::BuildCommand System::println(System::Color::error, "The build command requires all dependencies to be already installed."); System::println("The following dependencies are missing:"); - System::println(Strings::EMPTY); + System::println(); for (const auto& p : result.unmet_dependencies) { System::println(" %s", p); } - System::println(Strings::EMPTY); + System::println(); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 1c474f7b0..8b1eec5eb 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -199,7 +199,7 @@ namespace vcpkg::Commands::Install bcf.core_paragraph.spec); System::print("\n "); System::println(Strings::join("\n ", intersection)); - System::println(Strings::EMPTY); + System::println(); return InstallResult::FILE_CONFLICTS; } diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp index 29da7e684..24edb779f 100644 --- a/toolsrc/src/vcpkg_Files.cpp +++ b/toolsrc/src/vcpkg_Files.cpp @@ -186,11 +186,11 @@ namespace vcpkg::Files void print_paths(const std::vector& paths) { - System::println(""); + System::println(); for (const fs::path& p : paths) { System::println(" %s", p.generic_string()); } - System::println(""); + System::println(); } } -- cgit v1.2.3 From 28e581599e263e3f0b021ad5b6914d80fa9640f8 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 28 Aug 2017 19:39:33 -0700 Subject: Use Strings::EMPTY --- toolsrc/src/SourceParagraph.cpp | 4 ++-- toolsrc/src/VcpkgCmdArguments.cpp | 6 +++--- toolsrc/src/VcpkgPaths.cpp | 2 +- toolsrc/src/vcpkg_Build.cpp | 8 ++++---- toolsrc/src/vcpkg_Checks.cpp | 2 +- toolsrc/src/vcpkg_Parse.cpp | 2 +- toolsrc/src/vcpkg_Strings.cpp | 2 +- toolsrc/src/vcpkglib.cpp | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index c69770ae1..50d6ecf07 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -187,7 +187,7 @@ namespace vcpkg { return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency { auto pos = depend_string.find(' '); - if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, ""); + if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, Strings::EMPTY); // expect of the form "\w+ \[\w+\]" Dependency dep; @@ -195,7 +195,7 @@ namespace vcpkg if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')') { // Error, but for now just slurp the entire string. - return Dependency::parse_dependency(depend_string, ""); + return Dependency::parse_dependency(depend_string, Strings::EMPTY); } dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3); return dep; diff --git a/toolsrc/src/VcpkgCmdArguments.cpp b/toolsrc/src/VcpkgCmdArguments.cpp index cf6c7b562..e7a9b8057 100644 --- a/toolsrc/src/VcpkgCmdArguments.cpp +++ b/toolsrc/src/VcpkgCmdArguments.cpp @@ -222,17 +222,17 @@ namespace vcpkg void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count) const { - return check_max_arg_count(expected_arg_count, ""); + return check_max_arg_count(expected_arg_count, Strings::EMPTY); } void VcpkgCmdArguments::check_min_arg_count(const size_t expected_arg_count) const { - return check_min_arg_count(expected_arg_count, ""); + return check_min_arg_count(expected_arg_count, Strings::EMPTY); } void VcpkgCmdArguments::check_exact_arg_count(const size_t expected_arg_count) const { - return check_exact_arg_count(expected_arg_count, ""); + return check_exact_arg_count(expected_arg_count, Strings::EMPTY); } void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count, const std::string& example_text) const diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 17a11b1a9..94fbf9a93 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -133,7 +133,7 @@ namespace vcpkg fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { static constexpr std::array expected_version = {4, 1, 0}; - static const std::wstring version_check_arguments = L""; + static const std::wstring version_check_arguments = Strings::WEMPTY; const fs::path downloaded_copy = downloads_folder / "nuget-4.1.0" / "nuget.exe"; const std::vector from_path = find_from_PATH(L"nuget"); diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index bec9c9ef7..a2fa99ac8 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -30,8 +30,8 @@ namespace vcpkg::Build CWStringView to_vcvarsall_target(const std::string& cmake_system_name) { - if (cmake_system_name == "") return L""; - if (cmake_system_name == "Windows") return L""; + if (cmake_system_name == Strings::EMPTY) return Strings::WEMPTY; + if (cmake_system_name == "Windows") return Strings::WEMPTY; if (cmake_system_name == "WindowsStore") return L"store"; Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported vcvarsall target %s", cmake_system_name); @@ -61,7 +61,7 @@ namespace vcpkg::Build const wchar_t* tonull = L" >nul"; if (GlobalState::debugging) { - tonull = L""; + tonull = Strings::WEMPTY; } const auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset); @@ -359,7 +359,7 @@ namespace vcpkg::Build const bool variable_with_no_value = s.size() == 1; const std::string variable_name = s.at(0); - const std::string variable_value = variable_with_no_value ? "" : s.at(1); + const std::string variable_value = variable_with_no_value ? Strings::EMPTY : s.at(1); if (variable_name == "VCPKG_TARGET_ARCHITECTURE") { diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp index 2ad2d06ab..b6a88a011 100644 --- a/toolsrc/src/vcpkg_Checks.cpp +++ b/toolsrc/src/vcpkg_Checks.cpp @@ -62,7 +62,7 @@ namespace vcpkg::Checks { if (!expression) { - exit_with_message(line_info, ""); + exit_with_message(line_info, Strings::EMPTY); } } diff --git a/toolsrc/src/vcpkg_Parse.cpp b/toolsrc/src/vcpkg_Parse.cpp index 118cde900..b54f7360b 100644 --- a/toolsrc/src/vcpkg_Parse.cpp +++ b/toolsrc/src/vcpkg_Parse.cpp @@ -30,7 +30,7 @@ namespace vcpkg::Parse } std::string ParagraphParser::optional_field(const std::string& fieldname) { - return remove_field(&fields, fieldname).value_or(""); + return remove_field(&fields, fieldname).value_or(Strings::EMPTY); } std::unique_ptr ParagraphParser::error_info(const std::string& name) const { diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index b5ea338de..d08898bce 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -133,7 +133,7 @@ namespace vcpkg::Strings trim(&s); } - Util::erase_remove_if(*strings, [](const std::string& s) { return s == ""; }); + Util::erase_remove_if(*strings, [](const std::string& s) { return Strings::is_empty(s); }); } std::vector split(const std::string& s, const std::string& delimiter) diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 96e9f05e1..9f47c9d61 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -189,7 +189,7 @@ namespace vcpkg for (const std::unique_ptr& pgh : status_db) { - if (pgh->state != InstallState::INSTALLED || pgh->package.feature != "") + if (pgh->state != InstallState::INSTALLED || !Strings::is_empty(pgh->package.feature)) { continue; } -- cgit v1.2.3 From 5337adf1078f27c993f01662b7dadb8da2801356 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 29 Aug 2017 16:20:21 -0700 Subject: Remove Strings::is_empty(). Use std::string.empty() --- toolsrc/src/BinaryParagraph.cpp | 2 +- toolsrc/src/vcpkg_Dependencies.cpp | 6 +++--- toolsrc/src/vcpkg_Strings.cpp | 5 +---- toolsrc/src/vcpkglib.cpp | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index 1ab1aa63e..1504912ab 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -89,7 +89,7 @@ namespace vcpkg std::string BinaryParagraph::displayname() const { - const auto f = Strings::is_empty(this->feature) ? "core" : this->feature; + const auto f = this->feature.empty() ? "core" : this->feature; return Strings::format("%s[%s]:%s", this->spec.name(), f, this->spec.triplet()); } diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 4d0c3c928..1a0f0a6ed 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -443,7 +443,7 @@ namespace vcpkg::Dependencies MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { - if (feature == "") + if (feature.empty()) { // Indicates that core was not specified in the reference return mark_plus("core", cluster, graph, graph_plan); @@ -551,7 +551,7 @@ namespace vcpkg::Dependencies auto& status_paragraph_feature = status_paragraph->package.feature; // In this case, empty string indicates the "core" paragraph for a package. - if (status_paragraph_feature == "") + if (status_paragraph_feature.empty()) { cluster.original_features.insert("core"); } @@ -573,7 +573,7 @@ namespace vcpkg::Dependencies auto& dep_cluster = graph.get(dependency.spec()); auto depends_name = dependency.feature(); - if (depends_name == "") depends_name = "core"; + if (depends_name.empty()) depends_name = "core"; auto& target_node = dep_cluster.edges[depends_name]; target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index d08898bce..15851829d 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -71,9 +71,6 @@ namespace vcpkg::Strings::details namespace vcpkg::Strings { - bool is_empty(const CStringView s) { return s == EMPTY; } - bool is_empty(const CWStringView s) { return s == WEMPTY; } - std::wstring to_utf16(const CStringView s) { std::wstring_convert, wchar_t> conversion; @@ -133,7 +130,7 @@ namespace vcpkg::Strings trim(&s); } - Util::erase_remove_if(*strings, [](const std::string& s) { return Strings::is_empty(s); }); + Util::erase_remove_if(*strings, [](const std::string& s) { return s.empty(); }); } std::vector split(const std::string& s, const std::string& delimiter) diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 9f47c9d61..14d062468 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -189,7 +189,7 @@ namespace vcpkg for (const std::unique_ptr& pgh : status_db) { - if (pgh->state != InstallState::INSTALLED || !Strings::is_empty(pgh->package.feature)) + if (pgh->state != InstallState::INSTALLED || !pgh->package.feature.empty()) { continue; } -- cgit v1.2.3 From 526b1436a16b5c60760cbfc16a7f64e49cf13a01 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 29 Aug 2017 17:02:33 -0700 Subject: [vcpkg] Dependency instead of installcmd --- toolsrc/src/VcpkgPaths.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 94fbf9a93..1a8693efc 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -90,7 +90,7 @@ namespace vcpkg { auto locked_metrics = Metrics::g_metrics.lock(); locked_metrics->track_property("error", "powershell install failed"); - locked_metrics->track_property("installcmd", install_cmd); + locked_metrics->track_property("dependency", tool_name); } Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); } -- cgit v1.2.3 From 765068fa70259be5487db2ffc4ea3e6b6e4d73bd Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 29 Aug 2017 19:04:47 -0700 Subject: [vcpkg] Refactor workaround for issue #1712. This should be removed once the root cause is found. --- toolsrc/src/VcpkgPaths.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 1fe92014c..ef9209b78 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -10,6 +10,16 @@ namespace vcpkg { + static std::string WORKAROUND_ISSUE_1712(const std::string& line) + { + auto colon_pos = line.find(':'); + if (colon_pos != std::string::npos && colon_pos > 0) + { + return line.substr(colon_pos - 1); + } + return line; + } + static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd, const std::array& expected_version) { @@ -95,7 +105,7 @@ namespace vcpkg Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); } - const fs::path actual_downloaded_path = Strings::trimmed(rc.output); + const fs::path actual_downloaded_path = WORKAROUND_ISSUE_1712(Strings::trimmed(rc.output)); std::error_code ec; auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); Checks::check_exit(VCPKG_LINE_INFO, @@ -264,14 +274,7 @@ namespace vcpkg const std::wstring cmd = System::create_powershell_script_cmd(script); System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect VS 2017 instances"); - return Util::fmap(Strings::split(ec_data.output, "\n"), [](const std::string& line) { - auto colon_pos = line.find(':'); - if (colon_pos != std::string::npos && colon_pos > 0) - { - return line.substr(colon_pos - 1); - } - return line; - }); + return Util::fmap(Strings::split(ec_data.output, "\n"), WORKAROUND_ISSUE_1712); } static Optional get_VS2015_installation_instance() -- cgit v1.2.3 From 673bb9e19e37efc62181e6d5e195053f9ee48886 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 29 Aug 2017 18:57:38 -0700 Subject: Add missing const --- toolsrc/src/vcpkg_System.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index db4dfec9b..b769d6d57 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -19,7 +19,7 @@ namespace vcpkg::System fs::path get_exe_path_of_current_process() { wchar_t buf[_MAX_PATH]; - int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); + const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); if (bytes == 0) std::abort(); return fs::path(buf, buf + bytes); } @@ -37,9 +37,9 @@ namespace vcpkg::System CPUArchitecture get_host_processor() { auto w6432 = get_environment_variable(L"PROCESSOR_ARCHITEW6432"); - if (auto p = w6432.get()) return to_cpu_architecture(Strings::to_utf8(*p)).value_or_exit(VCPKG_LINE_INFO); + if (const auto p = w6432.get()) return to_cpu_architecture(Strings::to_utf8(*p)).value_or_exit(VCPKG_LINE_INFO); - auto procarch = get_environment_variable(L"PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO); + const auto procarch = get_environment_variable(L"PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO); return to_cpu_architecture(Strings::to_utf8(procarch)).value_or_exit(VCPKG_LINE_INFO); } @@ -59,10 +59,10 @@ namespace vcpkg::System int cmd_execute_clean(const CWStringView cmd_line) { - static const std::wstring system_root = get_environment_variable(L"SystemRoot").value_or_exit(VCPKG_LINE_INFO); - static const std::wstring system_32 = system_root + LR"(\system32)"; - static const std::wstring new_PATH = Strings::wformat( - LR"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", system_32, system_root, system_32, system_32); + static const std::wstring SYSTEM_ROOT = get_environment_variable(L"SystemRoot").value_or_exit(VCPKG_LINE_INFO); + static const std::wstring SYSTEM_32 = SYSTEM_ROOT + LR"(\system32)"; + static const std::wstring NEW_PATH = Strings::wformat( + LR"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32); std::vector env_wstrings = { L"ALLUSERSPROFILE", @@ -116,7 +116,7 @@ namespace vcpkg::System for (auto&& env_wstring : env_wstrings) { const Optional value = System::get_environment_variable(env_wstring); - auto v = value.get(); + const auto v = value.get(); if (!v || v->empty()) continue; env_cstr.append(env_wstring); @@ -125,7 +125,7 @@ namespace vcpkg::System env_cstr.push_back(L'\0'); } - env_cstr.append(new_PATH); + env_cstr.append(NEW_PATH); env_cstr.push_back(L'\0'); STARTUPINFOW startup_info; @@ -153,7 +153,7 @@ namespace vcpkg::System CloseHandle(process_info.hThread); - DWORD result = WaitForSingleObject(process_info.hProcess, INFINITE); + const DWORD result = WaitForSingleObject(process_info.hProcess, INFINITE); Checks::check_exit(VCPKG_LINE_INFO, result != WAIT_FAILED, "WaitForSingleObject failed"); DWORD exit_code = 0; @@ -171,7 +171,7 @@ namespace vcpkg::System // Basically we are wrapping it in quotes const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); Debug::println("_wsystem(%s)", Strings::to_utf8(actual_cmd_line)); - int exit_code = _wsystem(actual_cmd_line.c_str()); + const int exit_code = _wsystem(actual_cmd_line.c_str()); Debug::println("_wsystem() returned %d", exit_code); return exit_code; } @@ -186,7 +186,7 @@ namespace vcpkg::System Debug::println("_wpopen(%s)", Strings::to_utf8(actual_cmd_line)); std::wstring output; wchar_t buf[1024]; - auto pipe = _wpopen(actual_cmd_line.c_str(), L"r"); + const auto pipe = _wpopen(actual_cmd_line.c_str(), L"r"); if (pipe == nullptr) { return {1, Strings::to_utf8(output)}; @@ -199,7 +199,8 @@ namespace vcpkg::System { return {1, Strings::to_utf8(output)}; } - auto ec = _pclose(pipe); + + const auto ec = _pclose(pipe); Debug::println("_pclose() returned %d", ec); return {ec, Strings::to_utf8(output)}; } @@ -223,11 +224,11 @@ namespace vcpkg::System void print(const Color c, const CStringView message) { - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo{}; GetConsoleScreenBufferInfo(hConsole, &consoleScreenBufferInfo); - auto original_color = consoleScreenBufferInfo.wAttributes; + const auto original_color = consoleScreenBufferInfo.wAttributes; SetConsoleTextAttribute(hConsole, static_cast(c) | (original_color & 0xF0)); print(message); @@ -242,13 +243,13 @@ namespace vcpkg::System Optional get_environment_variable(const CWStringView varname) noexcept { - auto sz = GetEnvironmentVariableW(varname, nullptr, 0); + const auto sz = GetEnvironmentVariableW(varname, nullptr, 0); if (sz == 0) return nullopt; std::wstring ret(sz, L'\0'); Checks::check_exit(VCPKG_LINE_INFO, MAXDWORD >= ret.size()); - auto sz2 = GetEnvironmentVariableW(varname, ret.data(), static_cast(ret.size())); + const auto sz2 = GetEnvironmentVariableW(varname, ret.data(), static_cast(ret.size())); Checks::check_exit(VCPKG_LINE_INFO, sz2 + 1 == sz); ret.pop_back(); return ret; @@ -262,7 +263,7 @@ namespace vcpkg::System Optional get_registry_string(HKEY base, const CWStringView subKey, const CWStringView valuename) { HKEY k = nullptr; - LSTATUS ec = RegOpenKeyExW(base, subKey, NULL, KEY_READ, &k); + const LSTATUS ec = RegOpenKeyExW(base, subKey, NULL, KEY_READ, &k); if (ec != ERROR_SUCCESS) return nullopt; DWORD dwBufferSize = 0; -- cgit v1.2.3 From 130d9019dfddc491dafe762a0dde41f5d3ada87e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 29 Aug 2017 18:59:00 -0700 Subject: Naming convention fixes --- toolsrc/src/vcpkg_System.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index b769d6d57..f5106b25e 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -224,15 +224,15 @@ namespace vcpkg::System void print(const Color c, const CStringView message) { - const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + const HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo{}; - GetConsoleScreenBufferInfo(hConsole, &consoleScreenBufferInfo); - const auto original_color = consoleScreenBufferInfo.wAttributes; + CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info{}; + GetConsoleScreenBufferInfo(console_handle, &console_screen_buffer_info); + const auto original_color = console_screen_buffer_info.wAttributes; - SetConsoleTextAttribute(hConsole, static_cast(c) | (original_color & 0xF0)); + SetConsoleTextAttribute(console_handle, static_cast(c) | (original_color & 0xF0)); print(message); - SetConsoleTextAttribute(hConsole, original_color); + SetConsoleTextAttribute(console_handle, original_color); } void println(const Color c, const CStringView message) @@ -260,23 +260,23 @@ namespace vcpkg::System return hkey_type == REG_SZ || hkey_type == REG_MULTI_SZ || hkey_type == REG_EXPAND_SZ; } - Optional get_registry_string(HKEY base, const CWStringView subKey, const CWStringView valuename) + Optional get_registry_string(HKEY base, const CWStringView sub_key, const CWStringView valuename) { HKEY k = nullptr; - const LSTATUS ec = RegOpenKeyExW(base, subKey, NULL, KEY_READ, &k); + const LSTATUS ec = RegOpenKeyExW(base, sub_key, NULL, KEY_READ, &k); if (ec != ERROR_SUCCESS) return nullopt; - DWORD dwBufferSize = 0; - DWORD dwType = 0; - auto rc = RegQueryValueExW(k, valuename, nullptr, &dwType, nullptr, &dwBufferSize); - if (rc != ERROR_SUCCESS || !is_string_keytype(dwType) || dwBufferSize == 0 || - dwBufferSize % sizeof(wchar_t) != 0) + DWORD dw_buffer_size = 0; + DWORD dw_type = 0; + auto rc = RegQueryValueExW(k, valuename, nullptr, &dw_type, nullptr, &dw_buffer_size); + if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size == 0 || + dw_buffer_size % sizeof(wchar_t) != 0) return nullopt; std::wstring ret; - ret.resize(dwBufferSize / sizeof(wchar_t)); + ret.resize(dw_buffer_size / sizeof(wchar_t)); - rc = RegQueryValueExW(k, valuename, nullptr, &dwType, reinterpret_cast(ret.data()), &dwBufferSize); - if (rc != ERROR_SUCCESS || !is_string_keytype(dwType) || dwBufferSize != sizeof(wchar_t) * ret.size()) + rc = RegQueryValueExW(k, valuename, nullptr, &dw_type, reinterpret_cast(ret.data()), &dw_buffer_size); + if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size != sizeof(wchar_t) * ret.size()) return nullopt; ret.pop_back(); // remove extra trailing null byte -- cgit v1.2.3 From 3063bf5be34f9a285e1a84fb9c70195933122d72 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 29 Aug 2017 19:02:22 -0700 Subject: Add missing const --- toolsrc/src/vcpkglib.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 14d062468..5cdafdbc8 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -39,7 +39,7 @@ namespace vcpkg { auto& fs = paths.get_filesystem(); - auto updates_dir = paths.vcpkg_dir_updates; + const auto updates_dir = paths.vcpkg_dir_updates; std::error_code ec; fs.create_directory(paths.installed, ec); @@ -90,9 +90,9 @@ namespace vcpkg static int update_id = 0; auto& fs = paths.get_filesystem(); - auto my_update_id = update_id++; - auto tmp_update_filename = paths.vcpkg_dir_updates / "incomplete"; - auto update_filename = paths.vcpkg_dir_updates / std::to_string(my_update_id); + const auto my_update_id = update_id++; + const auto tmp_update_filename = paths.vcpkg_dir_updates / "incomplete"; + const auto update_filename = paths.vcpkg_dir_updates / std::to_string(my_update_id); fs.write_contents(tmp_update_filename, Strings::serialize(p)); fs.rename(tmp_update_filename, update_filename); @@ -233,7 +233,7 @@ namespace vcpkg const fs::path& cmake_script, const std::vector& pass_variables) { - std::wstring cmd_cmake_pass_variables = Strings::join(L" ", pass_variables, [](auto&& v) { return v.s; }); + const std::wstring cmd_cmake_pass_variables = Strings::join(L" ", pass_variables, [](auto&& v) { return v.s; }); return Strings::wformat( LR"("%s" %s -P "%s")", cmake_exe.native(), cmd_cmake_pass_variables, cmake_script.generic_wstring()); } -- cgit v1.2.3 From 6b1fc769a64eb18ec25e289347ce2043968f706f Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 29 Aug 2017 19:21:01 -0700 Subject: Add missing const --- toolsrc/src/VcpkgCmdArguments.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgCmdArguments.cpp b/toolsrc/src/VcpkgCmdArguments.cpp index e7a9b8057..cb261930e 100644 --- a/toolsrc/src/VcpkgCmdArguments.cpp +++ b/toolsrc/src/VcpkgCmdArguments.cpp @@ -124,7 +124,7 @@ namespace vcpkg continue; } - auto eq_pos = arg.find('='); + const auto eq_pos = arg.find('='); if (eq_pos != std::string::npos) { args.optional_command_arguments.emplace(arg.substr(0, eq_pos), arg.substr(eq_pos + 1)); @@ -158,7 +158,7 @@ namespace vcpkg auto options_copy = this->optional_command_arguments; for (const std::string& option : valid_switches) { - auto it = options_copy.find(option); + const auto it = options_copy.find(option); if (it != options_copy.end()) { if (it->second.has_value()) @@ -177,7 +177,7 @@ namespace vcpkg for (const std::string& option : valid_settings) { - auto it = options_copy.find(option); + const auto it = options_copy.find(option); if (it != options_copy.end()) { if (!it->second.has_value()) -- cgit v1.2.3 From 62cde6598ddbf30f6872895aaf9715fc87f7b7aa Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 30 Aug 2017 22:42:43 -0700 Subject: Move function to Files::find_from_PATH() --- toolsrc/src/VcpkgPaths.cpp | 20 ++++---------------- toolsrc/src/vcpkg_Files.cpp | 13 +++++++++++++ 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index ef9209b78..865f2ce44 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -13,7 +13,7 @@ namespace vcpkg static std::string WORKAROUND_ISSUE_1712(const std::string& line) { auto colon_pos = line.find(':'); - if (colon_pos != std::string::npos && colon_pos > 0) + if (colon_pos != std::string::npos && colon_pos > 1) { return line.substr(colon_pos - 1); } @@ -68,18 +68,6 @@ namespace vcpkg return nullopt; } - static std::vector find_from_PATH(const std::wstring& name) - { - const std::wstring cmd = Strings::wformat(L"where.exe %s", name); - auto out = System::cmd_execute_and_capture_output(cmd); - if (out.exit_code != 0) - { - return {}; - } - - return Util::fmap(Strings::split(out.output, "\n"), [](auto&& s) { return fs::path(s); }); - } - static fs::path fetch_dependency(const fs::path& scripts_folder, const std::wstring& tool_name, const fs::path& expected_downloaded_path, @@ -122,7 +110,7 @@ namespace vcpkg static const std::wstring version_check_arguments = L"--version"; const fs::path downloaded_copy = downloads_folder / "cmake-3.9.1-win32-x86" / "bin" / "cmake.exe"; - const std::vector from_path = find_from_PATH(L"cmake"); + const std::vector from_path = Files::find_from_PATH(L"cmake"); std::vector candidate_paths; candidate_paths.push_back(downloaded_copy); @@ -146,7 +134,7 @@ namespace vcpkg static const std::wstring version_check_arguments = Strings::WEMPTY; const fs::path downloaded_copy = downloads_folder / "nuget-4.1.0" / "nuget.exe"; - const std::vector from_path = find_from_PATH(L"nuget"); + const std::vector from_path = Files::find_from_PATH(L"nuget"); std::vector candidate_paths; candidate_paths.push_back(downloaded_copy); @@ -167,7 +155,7 @@ namespace vcpkg static const std::wstring version_check_arguments = L"--version"; const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.1-32-bit" / "cmd" / "git.exe"; - const std::vector from_path = find_from_PATH(L"git"); + const std::vector from_path = Files::find_from_PATH(L"git"); std::vector candidate_paths; candidate_paths.push_back(downloaded_copy); diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp index 24edb779f..ad1fcebc6 100644 --- a/toolsrc/src/vcpkg_Files.cpp +++ b/toolsrc/src/vcpkg_Files.cpp @@ -2,6 +2,7 @@ #include "vcpkg_Files.h" #include "vcpkg_System.h" +#include "vcpkg_Util.h" #include namespace vcpkg::Files @@ -193,4 +194,16 @@ namespace vcpkg::Files } System::println(); } + + std::vector find_from_PATH(const std::wstring& name) + { + const std::wstring cmd = Strings::wformat(L"where.exe %s", name); + auto out = System::cmd_execute_and_capture_output(cmd); + if (out.exit_code != 0) + { + return {}; + } + + return Util::fmap(Strings::split(out.output, "\n"), [](auto&& s) { return fs::path(s); }); + } } -- cgit v1.2.3 From aa1e928c79d78aad0086960bec971fcfec2d2133 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 30 Aug 2017 23:26:34 -0700 Subject: Improve `vcpkg edit` and feedback when no editor is found --- toolsrc/src/commands_edit.cpp | 101 +++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 61 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index e72931e63..f71d4d44c 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -6,6 +6,30 @@ namespace vcpkg::Commands::Edit { + static std::vector find_from_registry() + { + static const std::array REGKEYS = { + LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", + LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", + LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", + LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", + }; + + std::vector output; + for (auto&& keypath : REGKEYS) + { + const Optional code_installpath = + System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation"); + if (const auto c = code_installpath.get()) + { + const fs::path install_path = fs::path(*c); + output.push_back(install_path / "Code.exe"); + output.push_back(install_path / "Code - Insiders.exe"); + } + } + return output; + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { static const std::string OPTION_BUILDTREES = "--buildtrees"; @@ -21,72 +45,27 @@ namespace vcpkg::Commands::Edit const fs::path portpath = paths.ports / port_name; Checks::check_exit(VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name); - // Find the user's selected editor - std::wstring env_editor; + std::vector candidate_paths; + const std::vector from_path = Files::find_from_PATH(L"EDITOR"); + candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + candidate_paths.push_back(System::get_ProgramFiles_platform_bitness() / "Microsoft VS Code" / "Code.exe"); + candidate_paths.push_back(System::get_ProgramFiles_32_bit() / "Microsoft VS Code" / "Code.exe"); - if (env_editor.empty()) - { - const Optional env_editor_optional = System::get_environment_variable(L"EDITOR"); - if (const auto e = env_editor_optional.get()) - { - env_editor = *e; - } - } - - if (env_editor.empty()) - { - const fs::path code_exe_path = System::get_ProgramFiles_platform_bitness() / "Microsoft VS Code/Code.exe"; - if (fs.exists(code_exe_path)) - { - env_editor = code_exe_path; - } - } - - if (env_editor.empty()) - { - const fs::path code_exe_path = System::get_ProgramFiles_32_bit() / "Microsoft VS Code/Code.exe"; - if (fs.exists(code_exe_path)) - { - env_editor = code_exe_path; - } - } - - if (env_editor.empty()) - { - static const std::array REGKEYS = { - LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", - LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", - LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", - LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", - }; - for (auto&& keypath : REGKEYS) - { - const Optional code_installpath = - System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation"); - if (const auto c = code_installpath.get()) - { - auto p = fs::path(*c) / "Code.exe"; - if (fs.exists(p)) - { - env_editor = p.native(); - break; - } - auto p_insiders = fs::path(*c) / "Code - Insiders.exe"; - if (fs.exists(p_insiders)) - { - env_editor = p_insiders.native(); - break; - } - } - } - } + const std::vector from_registry = find_from_registry(); + candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend()); - if (env_editor.empty()) + auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { return fs.exists(p); }); + if (it == candidate_paths.cend()) { - Checks::exit_with_message( - VCPKG_LINE_INFO, "Visual Studio Code was not found and the environment variable EDITOR is not set"); + System::println(System::Color::error, + "Error: Visual Studio Code was not found and the environment variable EDITOR is not set."); + System::println("The following paths were examined:"); + Files::print_paths(candidate_paths); + System::println("You can also set the environmental variable EDITOR to your editor of choice."); + Checks::exit_fail(VCPKG_LINE_INFO); } + const fs::path env_editor = *it; if (options.find(OPTION_BUILDTREES) != options.cend()) { const auto buildtrees_current_dir = paths.buildtrees / port_name; -- cgit v1.2.3 From f76244f700f3ae0fe353c53c19d209589e8cdaf7 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 30 Aug 2017 23:32:41 -0700 Subject: Use ::TerminateProcess() instead of ::exit() --- toolsrc/src/vcpkg_Checks.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp index b6a88a011..3692a0e9a 100644 --- a/toolsrc/src/vcpkg_Checks.cpp +++ b/toolsrc/src/vcpkg_Checks.cpp @@ -20,7 +20,9 @@ namespace vcpkg::Checks SetConsoleCP(GlobalState::g_init_console_cp); SetConsoleOutputCP(GlobalState::g_init_console_output_cp); - ::exit(exit_code); + fflush(nullptr); + + ::TerminateProcess(::GetCurrentProcess(), exit_code); } static BOOL CtrlHandler(DWORD fdwCtrlType) -- cgit v1.2.3 From f1867a8e899748673b2696de4b837f3e9d94bd69 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:01:23 -0700 Subject: Naming scheme --- toolsrc/src/vcpkg_System.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index f5106b25e..5313d419e 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -283,36 +283,36 @@ namespace vcpkg::System return ret; } - static const fs::path& get_ProgramFiles() + static const fs::path& get_program_files() { - static const fs::path p = System::get_environment_variable(L"PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO); - return p; + static const fs::path PATH = System::get_environment_variable(L"PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO); + return PATH; } const fs::path& get_ProgramFiles_32_bit() { - static const fs::path p = []() -> fs::path { + static const fs::path PATH = []() -> fs::path { auto value = System::get_environment_variable(L"ProgramFiles(x86)"); if (auto v = value.get()) { return std::move(*v); } - return get_ProgramFiles(); + return get_program_files(); }(); - return p; + return PATH; } const fs::path& get_ProgramFiles_platform_bitness() { - static const fs::path p = []() -> fs::path { + static const fs::path PATH = []() -> fs::path { auto value = System::get_environment_variable(L"ProgramW6432"); if (auto v = value.get()) { return std::move(*v); } - return get_ProgramFiles(); + return get_program_files(); }(); - return p; + return PATH; } } -- cgit v1.2.3 From d86d9727f6802a5f642e550db13e97a9a2ea8a29 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:02:12 -0700 Subject: Function naming convention --- toolsrc/src/VcpkgPaths.cpp | 4 ++-- toolsrc/src/commands_edit.cpp | 2 +- toolsrc/src/commands_integrate.cpp | 6 +++--- toolsrc/src/vcpkg_System.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 865f2ce44..c08612df2 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -116,7 +116,7 @@ namespace vcpkg candidate_paths.push_back(downloaded_copy); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); candidate_paths.push_back(System::get_ProgramFiles_platform_bitness() / "CMake" / "bin" / "cmake.exe"); - candidate_paths.push_back(System::get_ProgramFiles_32_bit() / "CMake" / "bin"); + candidate_paths.push_back(System::get_program_files_32_bit() / "CMake" / "bin"); const Optional path = find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version); @@ -161,7 +161,7 @@ namespace vcpkg candidate_paths.push_back(downloaded_copy); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); candidate_paths.push_back(System::get_ProgramFiles_platform_bitness() / "git" / "cmd" / "git.exe"); - candidate_paths.push_back(System::get_ProgramFiles_32_bit() / "git" / "cmd" / "git.exe"); + candidate_paths.push_back(System::get_program_files_32_bit() / "git" / "cmd" / "git.exe"); const Optional path = find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version); diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index f71d4d44c..c9886d82e 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -49,7 +49,7 @@ namespace vcpkg::Commands::Edit const std::vector from_path = Files::find_from_PATH(L"EDITOR"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); candidate_paths.push_back(System::get_ProgramFiles_platform_bitness() / "Microsoft VS Code" / "Code.exe"); - candidate_paths.push_back(System::get_ProgramFiles_32_bit() / "Microsoft VS Code" / "Code.exe"); + candidate_paths.push_back(System::get_program_files_32_bit() / "Microsoft VS Code" / "Code.exe"); const std::vector from_registry = find_from_registry(); candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend()); diff --git a/toolsrc/src/commands_integrate.cpp b/toolsrc/src/commands_integrate.cpp index c5942f9fc..fce9e4121 100644 --- a/toolsrc/src/commands_integrate.cpp +++ b/toolsrc/src/commands_integrate.cpp @@ -9,10 +9,10 @@ namespace vcpkg::Commands::Integrate { static const std::array old_system_target_files = { - System::get_ProgramFiles_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", - System::get_ProgramFiles_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"}; + System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", + System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"}; static const fs::path system_wide_targets_file = - System::get_ProgramFiles_32_bit() / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; + System::get_program_files_32_bit() / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; static std::string create_appdata_targets_shortcut(const std::string& target_path) noexcept { diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 5313d419e..d9d10f37b 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -289,7 +289,7 @@ namespace vcpkg::System return PATH; } - const fs::path& get_ProgramFiles_32_bit() + const fs::path& get_program_files_32_bit() { static const fs::path PATH = []() -> fs::path { auto value = System::get_environment_variable(L"ProgramFiles(x86)"); -- cgit v1.2.3 From 72394491b20753c3ee3987c5f15aedfc0742a0d8 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:02:51 -0700 Subject: Naming convention --- toolsrc/src/VcpkgPaths.cpp | 4 ++-- toolsrc/src/commands_edit.cpp | 2 +- toolsrc/src/vcpkg_System.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index c08612df2..e2004c67b 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -115,7 +115,7 @@ namespace vcpkg std::vector candidate_paths; candidate_paths.push_back(downloaded_copy); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - candidate_paths.push_back(System::get_ProgramFiles_platform_bitness() / "CMake" / "bin" / "cmake.exe"); + candidate_paths.push_back(System::get_program_files_platform_bitness() / "CMake" / "bin" / "cmake.exe"); candidate_paths.push_back(System::get_program_files_32_bit() / "CMake" / "bin"); const Optional path = @@ -160,7 +160,7 @@ namespace vcpkg std::vector candidate_paths; candidate_paths.push_back(downloaded_copy); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - candidate_paths.push_back(System::get_ProgramFiles_platform_bitness() / "git" / "cmd" / "git.exe"); + candidate_paths.push_back(System::get_program_files_platform_bitness() / "git" / "cmd" / "git.exe"); candidate_paths.push_back(System::get_program_files_32_bit() / "git" / "cmd" / "git.exe"); const Optional path = diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index c9886d82e..dc28de737 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -48,7 +48,7 @@ namespace vcpkg::Commands::Edit std::vector candidate_paths; const std::vector from_path = Files::find_from_PATH(L"EDITOR"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - candidate_paths.push_back(System::get_ProgramFiles_platform_bitness() / "Microsoft VS Code" / "Code.exe"); + candidate_paths.push_back(System::get_program_files_platform_bitness() / "Microsoft VS Code" / "Code.exe"); candidate_paths.push_back(System::get_program_files_32_bit() / "Microsoft VS Code" / "Code.exe"); const std::vector from_registry = find_from_registry(); diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index d9d10f37b..beaa997b8 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -302,7 +302,7 @@ namespace vcpkg::System return PATH; } - const fs::path& get_ProgramFiles_platform_bitness() + const fs::path& get_program_files_platform_bitness() { static const fs::path PATH = []() -> fs::path { auto value = System::get_environment_variable(L"ProgramW6432"); -- cgit v1.2.3 From badecd4207902b5faebb07a2c2f807f345994040 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:03:54 -0700 Subject: CoffFileReader naming convention --- toolsrc/src/PostBuildLint.cpp | 4 ++-- toolsrc/src/coff_file_reader.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 473c81cfa..8c04b94a0 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -389,7 +389,7 @@ namespace vcpkg::PostBuildLint file.extension() == ".dll", "The file extension was not .dll: %s", file.generic_string()); - COFFFileReader::DllInfo info = COFFFileReader::read_dll(file); + CoffFileReader::DllInfo info = CoffFileReader::read_dll(file); const std::string actual_architecture = get_actual_architecture(info.machine_type); if (expected_architecture != actual_architecture) @@ -418,7 +418,7 @@ namespace vcpkg::PostBuildLint file.extension() == ".lib", "The file extension was not .lib: %s", file.generic_string()); - COFFFileReader::LibInfo info = COFFFileReader::read_lib(file); + CoffFileReader::LibInfo info = CoffFileReader::read_lib(file); // This is zero for folly's debug library // TODO: Why? diff --git a/toolsrc/src/coff_file_reader.cpp b/toolsrc/src/coff_file_reader.cpp index 10c1437c6..bb3a6cefd 100644 --- a/toolsrc/src/coff_file_reader.cpp +++ b/toolsrc/src/coff_file_reader.cpp @@ -5,7 +5,7 @@ using namespace std; -namespace vcpkg::COFFFileReader +namespace vcpkg::CoffFileReader { template static T reinterpret_bytes(const char* data) -- cgit v1.2.3 From 07c963f36930a34050c57119c227cd95ea6d60aa Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:04:39 -0700 Subject: Add missing const --- toolsrc/src/PostBuildLint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 8c04b94a0..a30648163 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -389,7 +389,7 @@ namespace vcpkg::PostBuildLint file.extension() == ".dll", "The file extension was not .dll: %s", file.generic_string()); - CoffFileReader::DllInfo info = CoffFileReader::read_dll(file); + const CoffFileReader::DllInfo info = CoffFileReader::read_dll(file); const std::string actual_architecture = get_actual_architecture(info.machine_type); if (expected_architecture != actual_architecture) -- cgit v1.2.3 From b72c904719953c3b372c392c3a925609f4861f10 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:05:13 -0700 Subject: Naming convention fixes --- toolsrc/src/PostBuildLint.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index a30648163..1fd48d3ec 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -40,7 +40,7 @@ namespace vcpkg::PostBuildLint const std::vector& get_outdated_dynamic_crts() { - static const std::vector v_no_msvcrt = { + static const std::vector V_NO_MSVCRT = { {"msvcp100.dll", R"(msvcp100\.dll)"}, {"msvcp100d.dll", R"(msvcp100d\.dll)"}, {"msvcp110.dll", R"(msvcp110\.dll)"}, @@ -59,7 +59,7 @@ namespace vcpkg::PostBuildLint {"msvcrt20.dll", R"(msvcrt20\.dll)"}, {"msvcrt40.dll", R"(msvcrt40\.dll)"}}; - return v_no_msvcrt; + return V_NO_MSVCRT; } static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs, @@ -580,7 +580,7 @@ namespace vcpkg::PostBuildLint return LintStatus::SUCCESS; } - struct BuildType_and_file + struct BuildTypeAndFile { fs::path file; BuildType build_type; @@ -594,7 +594,7 @@ namespace vcpkg::PostBuildLint bad_build_types.erase(std::remove(bad_build_types.begin(), bad_build_types.end(), expected_build_type), bad_build_types.end()); - std::vector libs_with_invalid_crt; + std::vector libs_with_invalid_crt; for (const fs::path& lib : libs) { @@ -622,7 +622,7 @@ namespace vcpkg::PostBuildLint "Expected %s crt linkage, but the following libs had invalid crt linkage:", expected_build_type.to_string()); System::println(); - for (const BuildType_and_file btf : libs_with_invalid_crt) + for (const BuildTypeAndFile btf : libs_with_invalid_crt) { System::println(" %s: %s", btf.file.generic_string(), btf.build_type.to_string()); } @@ -636,12 +636,12 @@ namespace vcpkg::PostBuildLint return LintStatus::SUCCESS; } - struct OutdatedDynamicCrt_and_file + struct OutdatedDynamicCrtAndFile { fs::path file; OutdatedDynamicCrt outdated_crt; - OutdatedDynamicCrt_and_file() = delete; + OutdatedDynamicCrtAndFile() = delete; }; static LintStatus check_outdated_crt_linkage_of_dlls(const std::vector& dlls, @@ -650,7 +650,7 @@ namespace vcpkg::PostBuildLint { if (build_info.policies.is_enabled(BuildPolicy::ALLOW_OBSOLETE_MSVCRT)) return LintStatus::SUCCESS; - std::vector dlls_with_outdated_crt; + std::vector dlls_with_outdated_crt; for (const fs::path& dll : dlls) { @@ -676,7 +676,7 @@ namespace vcpkg::PostBuildLint { System::println(System::Color::warning, "Detected outdated dynamic CRT in the following files:"); System::println(); - for (const OutdatedDynamicCrt_and_file btf : dlls_with_outdated_crt) + for (const OutdatedDynamicCrtAndFile btf : dlls_with_outdated_crt) { System::println(" %s: %s", btf.file.generic_string(), btf.outdated_crt.name); } -- cgit v1.2.3 From 81c9445376e677aa04d33b125917a61020cafda9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:05:58 -0700 Subject: example -> EXAMPLE --- toolsrc/src/commands_build.cpp | 8 ++++---- toolsrc/src/commands_build_external.cpp | 7 +++---- toolsrc/src/commands_cache.cpp | 4 ++-- toolsrc/src/commands_ci.cpp | 6 +++--- toolsrc/src/commands_create.cpp | 6 +++--- toolsrc/src/commands_depends.cpp | 4 ++-- toolsrc/src/commands_export.cpp | 8 ++++---- toolsrc/src/commands_import.cpp | 4 ++-- toolsrc/src/commands_install.cpp | 8 ++++---- toolsrc/src/commands_integrate.cpp | 4 ++-- toolsrc/src/commands_list.cpp | 4 ++-- toolsrc/src/commands_owns.cpp | 4 ++-- toolsrc/src/commands_portsdiff.cpp | 6 +++--- toolsrc/src/commands_remove.cpp | 10 +++++----- toolsrc/src/commands_search.cpp | 4 ++-- 15 files changed, 43 insertions(+), 44 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index 26a783a4b..a69958058 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -89,11 +89,11 @@ namespace vcpkg::Commands::BuildCommand void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string example = Commands::Help::create_example_string("build zlib:x64-windows"); - args.check_exact_arg_count( - 1, example); // Build only takes a single package and all dependencies must already be installed + static const std::string EXAMPLE = Commands::Help::create_example_string("build zlib:x64-windows"); + // Build only takes a single package and all dependencies must already be installed + args.check_exact_arg_count(1, EXAMPLE); const std::string command_argument = args.command_arguments.at(0); - const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, example); + const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, EXAMPLE); Input::check_triplet(spec.package_spec.triplet(), paths); const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}); diff --git a/toolsrc/src/commands_build_external.cpp b/toolsrc/src/commands_build_external.cpp index ff70e9cf2..7e85f2250 100644 --- a/toolsrc/src/commands_build_external.cpp +++ b/toolsrc/src/commands_build_external.cpp @@ -2,17 +2,16 @@ #include "vcpkg_Commands.h" #include "vcpkg_Input.h" -#include "vcpkg_System.h" namespace vcpkg::Commands::BuildExternal { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string example = + static const std::string EXAMPLE = Commands::Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)"); - args.check_exact_arg_count(2, example); + args.check_exact_arg_count(2, EXAMPLE); const FullPackageSpec spec = - Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, example); + Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, EXAMPLE); Input::check_triplet(spec.package_spec.triplet(), paths); const std::unordered_set options = args.check_and_get_optional_command_arguments({}); diff --git a/toolsrc/src/commands_cache.cpp b/toolsrc/src/commands_cache.cpp index fa0c62ee4..5b65b197f 100644 --- a/toolsrc/src/commands_cache.cpp +++ b/toolsrc/src/commands_cache.cpp @@ -27,10 +27,10 @@ namespace vcpkg::Commands::Cache void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Strings::format( + static const std::string EXAMPLE = Strings::format( "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s", Commands::Help::create_example_string("cache png")); - args.check_max_arg_count(1, example); + args.check_max_arg_count(1, EXAMPLE); args.check_and_get_optional_command_arguments({}); const std::vector binary_paragraphs = read_all_binary_paragraphs(paths); diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index f781adf69..ca5e8a9a9 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -13,9 +13,9 @@ namespace vcpkg::Commands::CI { + using Build::BuildResult; using Dependencies::InstallPlanAction; using Dependencies::InstallPlanType; - using Build::BuildResult; static std::vector load_all_package_specs(Files::Filesystem& fs, const fs::path& ports_directory, @@ -30,8 +30,8 @@ namespace vcpkg::Commands::CI void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string example = Commands::Help::create_example_string("ci x64-windows"); - args.check_max_arg_count(1, example); + static const std::string EXAMPLE = Commands::Help::create_example_string("ci x64-windows"); + args.check_max_arg_count(1, EXAMPLE); const Triplet triplet = args.command_arguments.size() == 1 ? Triplet::from_canonical_name(args.command_arguments.at(0)) : default_triplet; diff --git a/toolsrc/src/commands_create.cpp b/toolsrc/src/commands_create.cpp index 7f85b776a..99c1b7401 100644 --- a/toolsrc/src/commands_create.cpp +++ b/toolsrc/src/commands_create.cpp @@ -10,10 +10,10 @@ namespace vcpkg::Commands::Create { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Commands::Help::create_example_string( + static const std::string EXAMPLE = Commands::Help::create_example_string( R"###(create zlib2 http://zlib.net/zlib1211.zip "zlib1211-2.zip")###"); - args.check_max_arg_count(3, example); - args.check_min_arg_count(2, example); + args.check_max_arg_count(3, EXAMPLE); + args.check_min_arg_count(2, EXAMPLE); args.check_and_get_optional_command_arguments({}); const std::string port_name = args.command_arguments.at(0); const std::string url = args.command_arguments.at(1); diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index ffad91226..17cd9c881 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -10,8 +10,8 @@ namespace vcpkg::Commands::DependInfo { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Commands::Help::create_example_string(R"###(depend-info [pat])###"); - args.check_max_arg_count(1, example); + static const std::string EXAMPLE = Commands::Help::create_example_string(R"###(depend-info [pat])###"); + args.check_max_arg_count(1, EXAMPLE); args.check_and_get_optional_command_arguments({}); std::vector> source_control_files = diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index dbfb09aab..9e87d7b01 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -221,12 +221,12 @@ namespace vcpkg::Commands::Export static const std::string OPTION_NUGET_VERSION = "--nuget-version"; // input sanitization - static const std::string example = + static const std::string EXAMPLE = Commands::Help::create_example_string("export zlib zlib:x64-windows boost --nuget"); - args.check_min_arg_count(1, example); + args.check_min_arg_count(1, EXAMPLE); const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, example); + return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); }); for (auto&& spec : specs) Input::check_triplet(spec.triplet(), paths); @@ -252,7 +252,7 @@ namespace vcpkg::Commands::Export if (!raw && !nuget && !zip && !_7zip && !dryRun) { System::println(System::Color::error, "Must provide at least one export type: --raw --nuget --zip --7zip"); - System::print(example); + System::print(EXAMPLE); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp index 5db1885b2..007e8c204 100644 --- a/toolsrc/src/commands_import.cpp +++ b/toolsrc/src/commands_import.cpp @@ -93,9 +93,9 @@ namespace vcpkg::Commands::Import void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Commands::Help::create_example_string( + static const std::string EXAMPLE = Commands::Help::create_example_string( R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)"); - args.check_exact_arg_count(3, example); + args.check_exact_arg_count(3, EXAMPLE); args.check_and_get_optional_command_arguments({}); const fs::path control_file_path(args.command_arguments[0]); diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 8b1eec5eb..d7c14f39c 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -450,12 +450,12 @@ namespace vcpkg::Commands::Install static const std::string OPTION_RECURSE = "--recurse"; // input sanitization - static const std::string example = + static const std::string EXAMPLE = Commands::Help::create_example_string("install zlib zlib:x64-windows curl boost"); - args.check_min_arg_count(1, example); + args.check_min_arg_count(1, EXAMPLE); const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_full_package_spec(arg, default_triplet, example); + return Input::check_and_get_full_package_spec(arg, default_triplet, EXAMPLE); }); for (auto&& spec : specs) @@ -549,7 +549,7 @@ namespace vcpkg::Commands::Install { // User specified --purge and --no-purge System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); - System::print(example); + System::print(EXAMPLE); Checks::exit_fail(VCPKG_LINE_INFO); } const std::string display_name = remove_action->spec.to_string(); diff --git a/toolsrc/src/commands_integrate.cpp b/toolsrc/src/commands_integrate.cpp index fce9e4121..b0ce5edee 100644 --- a/toolsrc/src/commands_integrate.cpp +++ b/toolsrc/src/commands_integrate.cpp @@ -317,10 +317,10 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Strings::format("Commands:\n" + static const std::string EXAMPLE = Strings::format("Commands:\n" "%s", INTEGRATE_COMMAND_HELPSTRING); - args.check_exact_arg_count(1, example); + args.check_exact_arg_count(1, EXAMPLE); args.check_and_get_optional_command_arguments({}); if (args.command_arguments[0] == "install") diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp index 3cfa7e184..98e26f3d0 100644 --- a/toolsrc/src/commands_list.cpp +++ b/toolsrc/src/commands_list.cpp @@ -25,10 +25,10 @@ namespace vcpkg::Commands::List void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Strings::format( + static const std::string EXAMPLE = Strings::format( "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", Commands::Help::create_example_string("list png")); - args.check_max_arg_count(1, example); + args.check_max_arg_count(1, EXAMPLE); const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_FULLDESC}); diff --git a/toolsrc/src/commands_owns.cpp b/toolsrc/src/commands_owns.cpp index 757292e96..718a0277f 100644 --- a/toolsrc/src/commands_owns.cpp +++ b/toolsrc/src/commands_owns.cpp @@ -25,9 +25,9 @@ namespace vcpkg::Commands::Owns void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Strings::format("The argument should be a pattern to search for. %s", + static const std::string EXAMPLE = Strings::format("The argument should be a pattern to search for. %s", Commands::Help::create_example_string("owns zlib.dll")); - args.check_exact_arg_count(1, example); + args.check_exact_arg_count(1, EXAMPLE); args.check_and_get_optional_command_arguments({}); StatusParagraphs status_db = database_load_check(paths); diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp index 83d62896f..09299cb09 100644 --- a/toolsrc/src/commands_portsdiff.cpp +++ b/toolsrc/src/commands_portsdiff.cpp @@ -117,11 +117,11 @@ namespace vcpkg::Commands::PortsDiff void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = + static const std::string EXAMPLE = Strings::format("The argument should be a branch/tag/hash to checkout.\n%s", Commands::Help::create_example_string("portsdiff mybranchname")); - args.check_min_arg_count(1, example); - args.check_max_arg_count(2, example); + args.check_min_arg_count(1, EXAMPLE); + args.check_max_arg_count(2, EXAMPLE); args.check_and_get_optional_command_arguments({}); const fs::path& git_exe = paths.get_git_exe(); diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index cca541c85..2b5033166 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -136,7 +136,7 @@ namespace vcpkg::Commands::Remove static const std::string OPTION_RECURSE = "--recurse"; static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_OUTDATED = "--outdated"; - static const std::string example = + static const std::string EXAMPLE = Commands::Help::create_example_string("remove zlib zlib:x64-windows curl boost"); const std::unordered_set options = args.check_and_get_optional_command_arguments( {OPTION_PURGE, OPTION_NO_PURGE, OPTION_RECURSE, OPTION_DRY_RUN, OPTION_OUTDATED}); @@ -145,7 +145,7 @@ namespace vcpkg::Commands::Remove std::vector specs; if (options.find(OPTION_OUTDATED) != options.cend()) { - args.check_exact_arg_count(0, example); + args.check_exact_arg_count(0, EXAMPLE); specs = Util::fmap(Update::find_outdated_packages(paths, status_db), [](auto&& outdated) { return outdated.spec; }); @@ -157,9 +157,9 @@ namespace vcpkg::Commands::Remove } else { - args.check_min_arg_count(1, example); + args.check_min_arg_count(1, EXAMPLE); specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, example); + return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); }); for (auto&& spec : specs) @@ -171,7 +171,7 @@ namespace vcpkg::Commands::Remove { // User specified --purge and --no-purge System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); - System::print(example); + System::print(EXAMPLE); Checks::exit_fail(VCPKG_LINE_INFO); } const bool isRecursive = options.find(OPTION_RECURSE) != options.cend(); diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index 529d52a8b..1ccec9fbe 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -80,10 +80,10 @@ namespace vcpkg::Commands::Search void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Strings::format( + static const std::string EXAMPLE = Strings::format( "The argument should be a substring to search for, or no argument to display all libraries.\n%s", Commands::Help::create_example_string("search png")); - args.check_max_arg_count(1, example); + args.check_max_arg_count(1, EXAMPLE); const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC}); -- cgit v1.2.3 From ef33eb96cf1b27bee88aa84b6f2cb3a8c43bb952 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:13:12 -0700 Subject: [vcpkg contact] Naming convention fix --- toolsrc/src/commands_contact.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_contact.cpp b/toolsrc/src/commands_contact.cpp index 7f4161802..8374350ee 100644 --- a/toolsrc/src/commands_contact.cpp +++ b/toolsrc/src/commands_contact.cpp @@ -7,8 +7,8 @@ namespace vcpkg::Commands::Contact { const std::string& email() { - static const std::string s_email = R"(vcpkg@microsoft.com)"; - return s_email; + static const std::string S_EMAIL = R"(vcpkg@microsoft.com)"; + return S_EMAIL; } void perform_and_exit(const VcpkgCmdArguments& args) -- cgit v1.2.3 From 78cbe5d52fc7661e59126f322826e71e2c3e66cc Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:13:22 -0700 Subject: [vcpkg export] Naming convention fixes --- toolsrc/src/commands_export.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index 9e87d7b01..b416a6f3c 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -21,7 +21,7 @@ namespace vcpkg::Commands::Export const std::string& nuget_id, const std::string& nupkg_version) { - static constexpr auto content_template = R"( + static constexpr auto CONTENT_TEMPLATE = R"( @NUGET_ID@ @@ -40,7 +40,7 @@ namespace vcpkg::Commands::Export )"; - std::string nuspec_file_content = std::regex_replace(content_template, std::regex("@NUGET_ID@"), nuget_id); + std::string nuspec_file_content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id); nuspec_file_content = std::regex_replace(nuspec_file_content, std::regex("@VERSION@"), nupkg_version); nuspec_file_content = std::regex_replace(nuspec_file_content, std::regex("@RAW_EXPORTED_DIR@"), raw_exported_dir); @@ -62,10 +62,10 @@ namespace vcpkg::Commands::Export static void print_plan(const std::map>& group_by_plan_type) { - static constexpr std::array order = {ExportPlanType::ALREADY_BUILT, + static constexpr std::array ORDER = {ExportPlanType::ALREADY_BUILT, ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT}; - for (const ExportPlanType plan_type : order) + for (const ExportPlanType plan_type : ORDER) { const auto it = group_by_plan_type.find(plan_type); if (it == group_by_plan_type.cend()) @@ -151,7 +151,7 @@ namespace vcpkg::Commands::Export enum class BackingEnum { ZIP = 1, - _7ZIP, + SEVEN_ZIP, }; constexpr ArchiveFormat() = delete; @@ -174,7 +174,7 @@ namespace vcpkg::Commands::Export namespace ArchiveFormatC { constexpr const ArchiveFormat ZIP(ArchiveFormat::BackingEnum::ZIP, L"zip", L"zip"); - constexpr const ArchiveFormat _7ZIP(ArchiveFormat::BackingEnum::_7ZIP, L"7z", L"7zip"); + constexpr const ArchiveFormat SEVEN_ZIP(ArchiveFormat::BackingEnum::SEVEN_ZIP, L"7z", L"7zip"); } static fs::path do_archive_export(const VcpkgPaths& paths, @@ -216,7 +216,7 @@ namespace vcpkg::Commands::Export static const std::string OPTION_RAW = "--raw"; static const std::string OPTION_NUGET = "--nuget"; static const std::string OPTION_ZIP = "--zip"; - static const std::string OPTION_7ZIP = "--7zip"; + static const std::string OPTION_SEVEN_ZIP = "--7zip"; static const std::string OPTION_NUGET_ID = "--nuget-id"; static const std::string OPTION_NUGET_VERSION = "--nuget-version"; @@ -237,19 +237,19 @@ namespace vcpkg::Commands::Export OPTION_RAW, OPTION_NUGET, OPTION_ZIP, - OPTION_7ZIP, + OPTION_SEVEN_ZIP, }, { OPTION_NUGET_ID, OPTION_NUGET_VERSION, }); - const bool dryRun = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); + const bool dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); const bool raw = options.switches.find(OPTION_RAW) != options.switches.cend(); const bool nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); const bool zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); - const bool _7zip = options.switches.find(OPTION_7ZIP) != options.switches.cend(); + const bool seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend(); - if (!raw && !nuget && !zip && !_7zip && !dryRun) + if (!raw && !nuget && !zip && !seven_zip && !dry_run) { System::println(System::Color::error, "Must provide at least one export type: --raw --nuget --zip --7zip"); System::print(EXAMPLE); @@ -300,7 +300,7 @@ namespace vcpkg::Commands::Export Checks::exit_fail(VCPKG_LINE_INFO); } - if (dryRun) + if (dry_run) { Checks::exit_success(VCPKG_LINE_INFO); } @@ -407,11 +407,11 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console print_next_step_info("[...]"); } - if (_7zip) + if (seven_zip) { System::println("Creating 7zip archive... "); const fs::path output_path = - do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::_7ZIP); + do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::SEVEN_ZIP); System::println(System::Color::success, "Creating 7zip archive... done"); System::println(System::Color::success, "7zip archive exported at: %s", output_path.generic_string()); print_next_step_info("[...]"); -- cgit v1.2.3 From b17480b0b44ddab04b7036766b58c41faa59afa7 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:13:30 -0700 Subject: Remove unused #include --- toolsrc/src/commands_create.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_create.cpp b/toolsrc/src/commands_create.cpp index 99c1b7401..6898f7399 100644 --- a/toolsrc/src/commands_create.cpp +++ b/toolsrc/src/commands_create.cpp @@ -2,7 +2,6 @@ #include "vcpkg_Commands.h" #include "vcpkg_Files.h" -#include "vcpkg_Input.h" #include "vcpkg_System.h" #include "vcpkglib.h" -- cgit v1.2.3 From 170cfa3f39d969ed5ebab7693610ffff9a313530 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:20:52 -0700 Subject: Add missing const --- toolsrc/src/MachineType.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/MachineType.cpp b/toolsrc/src/MachineType.cpp index 2f44ce21a..af6378c88 100644 --- a/toolsrc/src/MachineType.cpp +++ b/toolsrc/src/MachineType.cpp @@ -7,7 +7,7 @@ namespace vcpkg { MachineType to_machine_type(const uint16_t value) { - MachineType t = static_cast(value); + const MachineType t = static_cast(value); switch (t) { case MachineType::UNKNOWN: -- cgit v1.2.3 From 03edddef2402d7a578c7714b6b28d3734e3d3940 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:22:02 -0700 Subject: [vcpkg list] Naming convention fix --- toolsrc/src/commands_list.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp index 98e26f3d0..640885860 100644 --- a/toolsrc/src/commands_list.cpp +++ b/toolsrc/src/commands_list.cpp @@ -8,9 +8,9 @@ namespace vcpkg::Commands::List { static const std::string OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually - static void do_print(const StatusParagraph& pgh, bool FullDesc) + static void do_print(const StatusParagraph& pgh, bool full_desc) { - if (FullDesc) + if (full_desc) { System::println("%-30s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description); } -- cgit v1.2.3 From 775dc8ce4017395406f9699676b1e8a117afcac5 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:22:56 -0700 Subject: [vcpkg integrate] Naming convention fixes --- toolsrc/src/commands_integrate.cpp | 56 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_integrate.cpp b/toolsrc/src/commands_integrate.cpp index b0ce5edee..abfb676da 100644 --- a/toolsrc/src/commands_integrate.cpp +++ b/toolsrc/src/commands_integrate.cpp @@ -8,10 +8,10 @@ namespace vcpkg::Commands::Integrate { - static const std::array old_system_target_files = { + static const std::array OLD_SYSTEM_TARGET_FILES = { System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"}; - static const fs::path system_wide_targets_file = + static const fs::path SYSTEM_WIDE_TARGETS_FILE = System::get_program_files_32_bit() / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; static std::string create_appdata_targets_shortcut(const std::string& target_path) noexcept @@ -82,7 +82,7 @@ namespace vcpkg::Commands::Integrate const std::string& nuget_id, const std::string& nupkg_version) { - static constexpr auto content_template = R"( + static constexpr auto CONTENT_TEMPLATE = R"( @NUGET_ID@ @@ -99,7 +99,7 @@ namespace vcpkg::Commands::Integrate )"; - std::string content = std::regex_replace(content_template, std::regex("@NUGET_ID@"), nuget_id); + std::string content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id); content = std::regex_replace(content, std::regex("@VCPKG_DIR@"), vcpkg_root_dir.string()); content = std::regex_replace(content, std::regex("@VERSION@"), nupkg_version); return content; @@ -113,36 +113,36 @@ namespace vcpkg::Commands::Integrate static ElevationPromptChoice elevated_cmd_execute(const std::string& param) { - SHELLEXECUTEINFO shExInfo = {0}; - shExInfo.cbSize = sizeof(shExInfo); - shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS; - shExInfo.hwnd = nullptr; - shExInfo.lpVerb = "runas"; - shExInfo.lpFile = "cmd"; // Application to start - - shExInfo.lpParameters = param.c_str(); // Additional parameters - shExInfo.lpDirectory = nullptr; - shExInfo.nShow = SW_HIDE; - shExInfo.hInstApp = nullptr; - - if (!ShellExecuteExA(&shExInfo)) + SHELLEXECUTEINFO sh_ex_info = {0}; + sh_ex_info.cbSize = sizeof(sh_ex_info); + sh_ex_info.fMask = SEE_MASK_NOCLOSEPROCESS; + sh_ex_info.hwnd = nullptr; + sh_ex_info.lpVerb = "runas"; + sh_ex_info.lpFile = "cmd"; // Application to start + + sh_ex_info.lpParameters = param.c_str(); // Additional parameters + sh_ex_info.lpDirectory = nullptr; + sh_ex_info.nShow = SW_HIDE; + sh_ex_info.hInstApp = nullptr; + + if (!ShellExecuteExA(&sh_ex_info)) { return ElevationPromptChoice::NO; } - if (shExInfo.hProcess == nullptr) + if (sh_ex_info.hProcess == nullptr) { return ElevationPromptChoice::NO; } - WaitForSingleObject(shExInfo.hProcess, INFINITE); - CloseHandle(shExInfo.hProcess); + WaitForSingleObject(sh_ex_info.hProcess, INFINITE); + CloseHandle(sh_ex_info.hProcess); return ElevationPromptChoice::YES; } static fs::path get_appdata_targets_path() { - static const fs::path local_app_data = + static const fs::path LOCAL_APP_DATA = fs::path(System::get_environment_variable(L"LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO)); - return local_app_data / "vcpkg" / "vcpkg.user.targets"; + return LOCAL_APP_DATA / "vcpkg" / "vcpkg.user.targets"; } static void integrate_install(const VcpkgPaths& paths) @@ -150,7 +150,7 @@ namespace vcpkg::Commands::Integrate auto& fs = paths.get_filesystem(); // TODO: This block of code should eventually be removed - for (auto&& old_system_wide_targets_file : old_system_target_files) + for (auto&& old_system_wide_targets_file : OLD_SYSTEM_TARGET_FILES) { if (fs.exists(old_system_wide_targets_file)) { @@ -174,7 +174,7 @@ namespace vcpkg::Commands::Integrate fs.create_directory(tmp_dir, ec); bool should_install_system = true; - const Expected system_wide_file_contents = fs.read_contents(system_wide_targets_file); + const Expected system_wide_file_contents = fs.read_contents(SYSTEM_WIDE_TARGETS_FILE); if (auto contents_data = system_wide_file_contents.get()) { std::regex re(R"###()###"); @@ -193,9 +193,9 @@ namespace vcpkg::Commands::Integrate fs.write_contents(sys_src_path, create_system_targets_shortcut()); const std::string param = Strings::format(R"(/c mkdir "%s" & copy "%s" "%s" /Y > nul)", - system_wide_targets_file.parent_path().string(), + SYSTEM_WIDE_TARGETS_FILE.parent_path().string(), sys_src_path.string(), - system_wide_targets_file.string()); + SYSTEM_WIDE_TARGETS_FILE.string()); ElevationPromptChoice user_choice = elevated_cmd_execute(param); switch (user_choice) { @@ -207,9 +207,9 @@ namespace vcpkg::Commands::Integrate } Checks::check_exit(VCPKG_LINE_INFO, - fs.exists(system_wide_targets_file), + fs.exists(SYSTEM_WIDE_TARGETS_FILE), "Error: failed to copy targets file to %s", - system_wide_targets_file.string()); + SYSTEM_WIDE_TARGETS_FILE.string()); } const fs::path appdata_src_path = tmp_dir / "vcpkg.user.targets"; -- cgit v1.2.3 From dff6b22b430d27fac6239076d7511aaa5df6c9ca Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:24:44 -0700 Subject: [vcpkg integrate] Change regex to static const, add missing consts --- toolsrc/src/commands_integrate.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_integrate.cpp b/toolsrc/src/commands_integrate.cpp index abfb676da..1bf26910c 100644 --- a/toolsrc/src/commands_integrate.cpp +++ b/toolsrc/src/commands_integrate.cpp @@ -156,7 +156,7 @@ namespace vcpkg::Commands::Integrate { const std::string param = Strings::format(R"(/c DEL "%s" /Q > nul)", old_system_wide_targets_file.string()); - ElevationPromptChoice user_choice = elevated_cmd_execute(param); + const ElevationPromptChoice user_choice = elevated_cmd_execute(param); switch (user_choice) { case ElevationPromptChoice::YES: break; @@ -175,14 +175,14 @@ namespace vcpkg::Commands::Integrate bool should_install_system = true; const Expected system_wide_file_contents = fs.read_contents(SYSTEM_WIDE_TARGETS_FILE); - if (auto contents_data = system_wide_file_contents.get()) + static const std::regex RE(R"###()###"); + if (const auto contents_data = system_wide_file_contents.get()) { - std::regex re(R"###()###"); std::match_results match; - auto found = std::regex_search(*contents_data, match, re); + const auto found = std::regex_search(*contents_data, match, RE); if (found) { - int ver = atoi(match[1].str().c_str()); + const int ver = atoi(match[1].str().c_str()); if (ver >= 1) should_install_system = false; } } @@ -196,7 +196,7 @@ namespace vcpkg::Commands::Integrate SYSTEM_WIDE_TARGETS_FILE.parent_path().string(), sys_src_path.string(), SYSTEM_WIDE_TARGETS_FILE.string()); - ElevationPromptChoice user_choice = elevated_cmd_execute(param); + const ElevationPromptChoice user_choice = elevated_cmd_execute(param); switch (user_choice) { case ElevationPromptChoice::YES: break; @@ -217,7 +217,7 @@ namespace vcpkg::Commands::Integrate create_appdata_targets_shortcut(paths.buildsystems_msbuild_targets.string())); auto appdata_dst_path = get_appdata_targets_path(); - auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec); + const auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec); if (!rc || ec) { @@ -245,7 +245,7 @@ namespace vcpkg::Commands::Integrate const fs::path path = get_appdata_targets_path(); std::error_code ec; - bool was_deleted = fs.remove(path, ec); + const bool was_deleted = fs.remove(path, ec); Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %d", ec.message()); -- cgit v1.2.3 From 61e5b6980b41bb73daaac3c3e1e15f4b04f960d9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:27:10 -0700 Subject: [vcpkg import] Add missing consts --- toolsrc/src/commands_import.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp index 007e8c204..412a03d7f 100644 --- a/toolsrc/src/commands_import.cpp +++ b/toolsrc/src/commands_import.cpp @@ -28,7 +28,7 @@ namespace vcpkg::Commands::Import for (auto&& file : files) { if (fs.is_directory(file)) continue; - auto ext = file.extension(); + const auto ext = file.extension(); if (ext == ".dll") binaries.dlls.push_back(std::move(file)); else if (ext == ".lib") @@ -46,7 +46,7 @@ namespace vcpkg::Commands::Import for (auto const& src_path : files) { - fs::path dest_path = destination_folder / src_path.filename(); + const fs::path dest_path = destination_folder / src_path.filename(); fs.copy(src_path, dest_path, fs::copy_options::overwrite_existing); } } @@ -59,10 +59,10 @@ namespace vcpkg::Commands::Import check_is_directory(VCPKG_LINE_INFO, fs, include_directory); check_is_directory(VCPKG_LINE_INFO, fs, project_directory); check_is_directory(VCPKG_LINE_INFO, fs, destination_path); - Binaries debug_binaries = find_binaries_in_dir(fs, project_directory / "Debug"); - Binaries release_binaries = find_binaries_in_dir(fs, project_directory / "Release"); + const Binaries debug_binaries = find_binaries_in_dir(fs, project_directory / "Debug"); + const Binaries release_binaries = find_binaries_in_dir(fs, project_directory / "Release"); - fs::path destination_include_directory = destination_path / "include"; + const fs::path destination_include_directory = destination_path / "include"; fs.copy(include_directory, destination_include_directory, fs::copy_options::recursive | fs::copy_options::overwrite_existing); @@ -82,12 +82,12 @@ namespace vcpkg::Commands::Import const BinaryParagraph& control_file_data) { auto& fs = paths.get_filesystem(); - fs::path library_destination_path = paths.package_dir(control_file_data.spec); + const fs::path library_destination_path = paths.package_dir(control_file_data.spec); std::error_code ec; fs.create_directory(library_destination_path, ec); place_library_files_in(paths.get_filesystem(), include_directory, project_directory, library_destination_path); - fs::path control_file_path = library_destination_path / "CONTROL"; + const fs::path control_file_path = library_destination_path / "CONTROL"; fs.write_contents(control_file_path, Strings::serialize(control_file_data)); } -- cgit v1.2.3 From f0d5d94348a95c502688816c3ab360cd087aca95 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 31 Aug 2017 18:33:52 -0700 Subject: [vcpkg portsdiff] Add missing const, remove unused #include --- toolsrc/src/commands_portsdiff.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp index 09299cb09..32bc3de3c 100644 --- a/toolsrc/src/commands_portsdiff.cpp +++ b/toolsrc/src/commands_portsdiff.cpp @@ -2,7 +2,6 @@ #include "Paragraphs.h" #include "SortedVector.h" -#include "SourceParagraph.h" #include "vcpkg_Commands.h" #include "vcpkg_Maps.h" #include "vcpkg_System.h" @@ -139,8 +138,8 @@ namespace vcpkg::Commands::PortsDiff read_ports_from_commit(paths, git_commit_id_for_previous_snapshot); // Already sorted, so set_difference can work on std::vector too - std::vector current_ports = Maps::extract_keys(current_names_and_versions); - std::vector previous_ports = Maps::extract_keys(previous_names_and_versions); + const std::vector current_ports = Maps::extract_keys(current_names_and_versions); + const std::vector previous_ports = Maps::extract_keys(previous_names_and_versions); const SetElementPresence setp = SetElementPresence::create(current_ports, previous_ports); -- cgit v1.2.3 From 97063965b06280025eb123347f0145d6d817a29f Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 16:26:52 -0700 Subject: Remove #1712 workaround. Clean Byte-Order-Mark if present --- toolsrc/src/VcpkgPaths.cpp | 14 ++------------ toolsrc/src/vcpkg_System.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index e2004c67b..64c4ae630 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -10,16 +10,6 @@ namespace vcpkg { - static std::string WORKAROUND_ISSUE_1712(const std::string& line) - { - auto colon_pos = line.find(':'); - if (colon_pos != std::string::npos && colon_pos > 1) - { - return line.substr(colon_pos - 1); - } - return line; - } - static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd, const std::array& expected_version) { @@ -93,7 +83,7 @@ namespace vcpkg Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); } - const fs::path actual_downloaded_path = WORKAROUND_ISSUE_1712(Strings::trimmed(rc.output)); + const fs::path actual_downloaded_path = Strings::trimmed(rc.output); std::error_code ec; auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); Checks::check_exit(VCPKG_LINE_INFO, @@ -262,7 +252,7 @@ namespace vcpkg const std::wstring cmd = System::create_powershell_script_cmd(script); System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect VS 2017 instances"); - return Util::fmap(Strings::split(ec_data.output, "\n"), WORKAROUND_ISSUE_1712); + return Strings::split(ec_data.output, "\n"); } static Optional get_VS2015_installation_instance() diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index beaa997b8..40e335117 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -176,6 +176,17 @@ namespace vcpkg::System return exit_code; } + // On Win7, output from powershell calls contain a byte order mark, so we strip it out if it is present + static void remove_byte_order_mark(std::wstring* s) + { + const wchar_t* a = s->c_str(); + // This is the UTF-8 byte-order mark + if (a[0] == 0xEF && a[1] == 0xBB && a[2] == 0xBF) + { + s->erase(0, 3); + } + } + ExitCodeAndOutput cmd_execute_and_capture_output(const CWStringView cmd_line) { // Flush stdout before launching external process @@ -202,6 +213,7 @@ namespace vcpkg::System const auto ec = _pclose(pipe); Debug::println("_pclose() returned %d", ec); + remove_byte_order_mark(&output); return {ec, Strings::to_utf8(output)}; } -- cgit v1.2.3 From 86dc3107ca03575519d020cdf3dcebbf45c5d462 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 16:55:26 -0700 Subject: [VcpkgPaths.cpp] Naming conventions and const fixes --- toolsrc/src/VcpkgPaths.cpp | 67 +++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 33 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 64c4ae630..50032b740 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -13,24 +13,24 @@ namespace vcpkg static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd, const std::array& expected_version) { - static const std::regex re(R"###((\d+)\.(\d+)\.(\d+))###"); + static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###"); - auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s)", version_cmd)); + const auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s)", version_cmd)); if (rc.exit_code != 0) { return false; } std::match_results match; - auto found = std::regex_search(rc.output, match, re); + const auto found = std::regex_search(rc.output, match, RE); if (!found) { return false; } - int d1 = atoi(match[1].str().c_str()); - int d2 = atoi(match[2].str().c_str()); - int d3 = atoi(match[3].str().c_str()); + const int d1 = atoi(match[1].str().c_str()); + const int d2 = atoi(match[2].str().c_str()); + const int d3 = atoi(match[3].str().c_str()); if (d1 > expected_version[0] || (d1 == expected_version[0] && d2 > expected_version[1]) || (d1 == expected_version[0] && d2 == expected_version[1] && d3 >= expected_version[2])) { @@ -64,8 +64,9 @@ namespace vcpkg const std::array& version) { const fs::path script = scripts_folder / "fetchDependency.ps1"; - auto install_cmd = System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name)); - System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd); + const auto install_cmd = + System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name)); + const System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd); if (rc.exit_code) { const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); @@ -85,7 +86,7 @@ namespace vcpkg const fs::path actual_downloaded_path = Strings::trimmed(rc.output); std::error_code ec; - auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); + const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); Checks::check_exit(VCPKG_LINE_INFO, eq && !ec, "Expected dependency downloaded path to be %s, but was %s", @@ -96,8 +97,8 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array expected_version = {3, 9, 1}; - static const std::wstring version_check_arguments = L"--version"; + static constexpr std::array EXPECTED_VERSION = {3, 9, 1}; + static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; const fs::path downloaded_copy = downloads_folder / "cmake-3.9.1-win32-x86" / "bin" / "cmake.exe"; const std::vector from_path = Files::find_from_PATH(L"cmake"); @@ -109,19 +110,19 @@ namespace vcpkg candidate_paths.push_back(System::get_program_files_32_bit() / "CMake" / "bin"); const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version); - if (auto p = path.get()) + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) { return *p; } - return fetch_dependency(scripts_folder, L"cmake", downloaded_copy, expected_version); + return fetch_dependency(scripts_folder, L"cmake", downloaded_copy, EXPECTED_VERSION); } fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array expected_version = {4, 1, 0}; - static const std::wstring version_check_arguments = Strings::WEMPTY; + static constexpr std::array EXPECTED_VERSION = {4, 1, 0}; + static const std::wstring VERSION_CHECK_ARGUMENTS = Strings::WEMPTY; const fs::path downloaded_copy = downloads_folder / "nuget-4.1.0" / "nuget.exe"; const std::vector from_path = Files::find_from_PATH(L"nuget"); @@ -130,19 +131,19 @@ namespace vcpkg candidate_paths.push_back(downloaded_copy); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - auto path = find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version); - if (auto p = path.get()) + auto path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) { return *p; } - return fetch_dependency(scripts_folder, L"nuget", downloaded_copy, expected_version); + return fetch_dependency(scripts_folder, L"nuget", downloaded_copy, EXPECTED_VERSION); } fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array expected_version = {2, 14, 1}; - static const std::wstring version_check_arguments = L"--version"; + static constexpr std::array EXPECTED_VERSION = {2, 14, 1}; + static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.1-32-bit" / "cmd" / "git.exe"; const std::vector from_path = Files::find_from_PATH(L"git"); @@ -154,13 +155,13 @@ namespace vcpkg candidate_paths.push_back(System::get_program_files_32_bit() / "git" / "cmd" / "git.exe"); const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version); - if (auto p = path.get()) + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) { return *p; } - return fetch_dependency(scripts_folder, L"git", downloaded_copy, expected_version); + return fetch_dependency(scripts_folder, L"git", downloaded_copy, EXPECTED_VERSION); } Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir) @@ -221,7 +222,7 @@ namespace vcpkg { for (auto&& path : get_filesystem().get_files_non_recursive(this->triplets)) { - std::string triplet_file_name = path.stem().generic_u8string(); + const std::string triplet_file_name = path.stem().generic_u8string(); if (t.canonical_name() == triplet_file_name) // TODO: fuzzy compare { // t.value = triplet_file_name; // NOTE: uncomment when implementing fuzzy compare @@ -246,19 +247,19 @@ namespace vcpkg return this->nuget_exe.get_lazy([this]() { return get_nuget_path(this->downloads, this->scripts); }); } - static std::vector get_VS2017_installation_instances(const VcpkgPaths& paths) + static std::vector get_vs2017_installation_instances(const VcpkgPaths& paths) { const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; const std::wstring cmd = System::create_powershell_script_cmd(script); - System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); + const System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect VS 2017 instances"); return Strings::split(ec_data.output, "\n"); } - static Optional get_VS2015_installation_instance() + static Optional get_vs2015_installation_instance() { const Optional vs2015_cmntools_optional = System::get_environment_variable(L"VS140COMNTOOLS"); - if (auto v = vs2015_cmntools_optional.get()) + if (const auto v = vs2015_cmntools_optional.get()) { const fs::path vs2015_cmntools = fs::path(*v).parent_path(); // The call to parent_path() is needed because // the env variable has a trailing backslash @@ -274,15 +275,15 @@ namespace vcpkg const auto& fs = paths.get_filesystem(); - const std::vector vs2017_installation_instances = get_VS2017_installation_instances(paths); + const std::vector vs2017_installation_instances = get_vs2017_installation_instances(paths); // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. std::vector paths_examined; std::vector found_toolsets; // VS2015 - const Optional vs_2015_installation_instance = get_VS2015_installation_instance(); - if (auto v = vs_2015_installation_instance.get()) + const Optional vs_2015_installation_instance = get_vs2015_installation_instance(); + if (const auto v = vs_2015_installation_instance.get()) { const fs::path vs2015_vcvarsall_bat = *v / "VC" / "vcvarsall.bat"; @@ -362,7 +363,7 @@ namespace vcpkg break; } } - if (auto value = vs2017_toolset.get()) + if (const auto value = vs2017_toolset.get()) { found_toolsets.push_back(*value); break; -- cgit v1.2.3 From 797c94caecc3df34e82a9d0a1d774551cdc8ff66 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 16:56:53 -0700 Subject: Remove uneeded else branch. Fix variable hiding --- toolsrc/src/VcpkgPaths.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 50032b740..7d574006e 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -393,15 +393,12 @@ namespace vcpkg { return vs_toolsets.back(); } - else - { - const auto toolset = Util::find_if(vs_toolsets, [&](const Toolset& toolset) { - return toolset_version == Strings::to_utf8(toolset.version); - }); - Checks::check_exit( - VCPKG_LINE_INFO, toolset != vs_toolsets.end(), "Could not find toolset '%s'", toolset_version); - return *toolset; - } + + const auto toolset = Util::find_if( + vs_toolsets, [&](const Toolset& t) { return toolset_version == Strings::to_utf8(t.version); }); + Checks::check_exit( + VCPKG_LINE_INFO, toolset != vs_toolsets.end(), "Could not find toolset '%s'", toolset_version); + return *toolset; } Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); } -- cgit v1.2.3 From 95eadb8ddd7dfb7f0899055a98fa91485ed74dc8 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 16:58:51 -0700 Subject: [VcpkgPaths.cpp] Don't modify and ref on the fly --- toolsrc/src/VcpkgPaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 7d574006e..906a5e67f 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -318,9 +318,9 @@ namespace vcpkg // VS2017 Optional vs2017_toolset; - for (const fs::path& instance : vs2017_installation_instances) + for (const std::string& instance : vs2017_installation_instances) { - const fs::path vc_dir = instance / "VC"; + const fs::path vc_dir = fs::path{instance} / "VC"; // Skip any instances that do not have vcvarsall. const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build"; -- cgit v1.2.3 From c15c80e802f432f1b8d3775c7abff5e91531b641 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 17:01:02 -0700 Subject: [vcpkg_Parse] Add missing const --- toolsrc/src/vcpkg_Parse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Parse.cpp b/toolsrc/src/vcpkg_Parse.cpp index b54f7360b..e671a1a05 100644 --- a/toolsrc/src/vcpkg_Parse.cpp +++ b/toolsrc/src/vcpkg_Parse.cpp @@ -23,12 +23,12 @@ namespace vcpkg::Parse void ParagraphParser::required_field(const std::string& fieldname, std::string& out) { auto maybe_field = remove_field(&fields, fieldname); - if (auto field = maybe_field.get()) + if (const auto field = maybe_field.get()) out = std::move(*field); else missing_fields.push_back(fieldname); } - std::string ParagraphParser::optional_field(const std::string& fieldname) + std::string ParagraphParser::optional_field(const std::string& fieldname) const { return remove_field(&fields, fieldname).value_or(Strings::EMPTY); } -- cgit v1.2.3 From 3a43e190209719ea2789f1e50dc5a6a2a3e5d4b9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 17:02:12 -0700 Subject: [vcpkg_Input] Add missing const --- toolsrc/src/vcpkg_Input.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp index 153e6a942..f1cac9632 100644 --- a/toolsrc/src/vcpkg_Input.cpp +++ b/toolsrc/src/vcpkg_Input.cpp @@ -13,7 +13,7 @@ namespace vcpkg::Input { const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet); - if (auto spec = expected_spec.get()) + if (const auto spec = expected_spec.get()) { return PackageSpec{spec->package_spec}; } @@ -41,7 +41,7 @@ namespace vcpkg::Input { const std::string as_lowercase = Strings::ascii_to_lowercase(full_package_spec_as_string); auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet); - if (auto spec = expected_spec.get()) + if (const auto spec = expected_spec.get()) { return *spec; } -- cgit v1.2.3 From 9e7275c5dfeb9400492ceb8bed6635208a3d3cda Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 17:03:23 -0700 Subject: [vcpkg_Chrono] Add missing consts --- toolsrc/src/vcpkg_Chrono.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Chrono.cpp b/toolsrc/src/vcpkg_Chrono.cpp index d70f4a054..d96f30987 100644 --- a/toolsrc/src/vcpkg_Chrono.cpp +++ b/toolsrc/src/vcpkg_Chrono.cpp @@ -7,43 +7,43 @@ namespace vcpkg { static std::string format_time_userfriendly(const std::chrono::nanoseconds& nanos) { + using std::chrono::duration_cast; using std::chrono::hours; - using std::chrono::minutes; - using std::chrono::seconds; - using std::chrono::milliseconds; using std::chrono::microseconds; + using std::chrono::milliseconds; + using std::chrono::minutes; using std::chrono::nanoseconds; - using std::chrono::duration_cast; + using std::chrono::seconds; const double nanos_as_double = static_cast(nanos.count()); if (duration_cast(nanos) > hours()) { - auto t = nanos_as_double / duration_cast(hours(1)).count(); + const auto t = nanos_as_double / duration_cast(hours(1)).count(); return Strings::format("%.4g h", t); } if (duration_cast(nanos) > minutes()) { - auto t = nanos_as_double / duration_cast(minutes(1)).count(); + const auto t = nanos_as_double / duration_cast(minutes(1)).count(); return Strings::format("%.4g min", t); } if (duration_cast(nanos) > seconds()) { - auto t = nanos_as_double / duration_cast(seconds(1)).count(); + const auto t = nanos_as_double / duration_cast(seconds(1)).count(); return Strings::format("%.4g s", t); } if (duration_cast(nanos) > milliseconds()) { - auto t = nanos_as_double / duration_cast(milliseconds(1)).count(); + const auto t = nanos_as_double / duration_cast(milliseconds(1)).count(); return Strings::format("%.4g ms", t); } if (duration_cast(nanos) > microseconds()) { - auto t = nanos_as_double / duration_cast(microseconds(1)).count(); + const auto t = nanos_as_double / duration_cast(microseconds(1)).count(); return Strings::format("%.4g us", t); } -- cgit v1.2.3 From 2d758beea9d8068f189f79d79b4087e40d42154b Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 17:05:22 -0700 Subject: [vcpkg_Checks] Naming convention fixes --- toolsrc/src/vcpkg_Checks.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp index 3692a0e9a..e7c9046a4 100644 --- a/toolsrc/src/vcpkg_Checks.cpp +++ b/toolsrc/src/vcpkg_Checks.cpp @@ -10,7 +10,7 @@ namespace vcpkg::Checks { [[noreturn]] static void cleanup_and_exit(const int exit_code) { - auto elapsed_us = GlobalState::timer.lock()->microseconds(); + const auto elapsed_us = GlobalState::timer.lock()->microseconds(); auto metrics = Metrics::g_metrics.lock(); metrics->track_metric("elapsed_us", elapsed_us); @@ -25,17 +25,20 @@ namespace vcpkg::Checks ::TerminateProcess(::GetCurrentProcess(), exit_code); } - static BOOL CtrlHandler(DWORD fdwCtrlType) + static BOOL ctrl_handler(DWORD fdw_ctrl_type) { { auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_property("CtrlHandler", std::to_string(fdwCtrlType)); + locked_metrics->track_property("CtrlHandler", std::to_string(fdw_ctrl_type)); locked_metrics->track_property("error", "CtrlHandler was fired."); } cleanup_and_exit(EXIT_FAILURE); } - void register_console_ctrl_handler() { SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); } + void register_console_ctrl_handler() + { + SetConsoleCtrlHandler(reinterpret_cast(ctrl_handler), TRUE); + } [[noreturn]] void unreachable(const LineInfo& line_info) { @@ -54,9 +57,9 @@ namespace vcpkg::Checks cleanup_and_exit(exit_code); } - [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView errorMessage) + [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView error_message) { - System::println(System::Color::error, errorMessage); + System::println(System::Color::error, error_message); exit_fail(line_info); } @@ -68,11 +71,11 @@ namespace vcpkg::Checks } } - void check_exit(const LineInfo& line_info, bool expression, const CStringView errorMessage) + void check_exit(const LineInfo& line_info, bool expression, const CStringView error_message) { if (!expression) { - exit_with_message(line_info, errorMessage); + exit_with_message(line_info, error_message); } } } -- cgit v1.2.3 From 66eeab0015866417f4386a3822127ce7d40c49f9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 17:08:21 -0700 Subject: [Triplet] Naming convention and missing const --- toolsrc/src/triplet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/triplet.cpp b/toolsrc/src/triplet.cpp index 451deb040..3b56da02a 100644 --- a/toolsrc/src/triplet.cpp +++ b/toolsrc/src/triplet.cpp @@ -15,7 +15,7 @@ namespace vcpkg bool operator==(const TripletInstance& o) const { return o.value == value; } }; - const TripletInstance Triplet::default_instance({}); + const TripletInstance Triplet::DEFAULT_INSTANCE({}); } template<> @@ -41,10 +41,10 @@ namespace vcpkg Triplet Triplet::from_canonical_name(const std::string& triplet_as_string) { std::string s(Strings::ascii_to_lowercase(triplet_as_string)); - auto it = std::find(s.cbegin(), s.cend(), '-'); + const auto it = std::find(s.cbegin(), s.cend(), '-'); Checks::check_exit(VCPKG_LINE_INFO, it != s.cend(), "Invalid triplet: %s", triplet_as_string); - auto p = g_triplet_instances.emplace(std::move(s)); + const auto p = g_triplet_instances.emplace(std::move(s)); return &*p.first; } -- cgit v1.2.3 From b76ac1da157c9c86cb451c871ea5ae0ddf74dbb9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 17:12:58 -0700 Subject: Add missing consts --- toolsrc/src/SourceParagraph.cpp | 6 +++--- toolsrc/src/StatusParagraphs.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 50d6ecf07..64b7bbad1 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -137,7 +137,7 @@ namespace vcpkg auto control_file = std::make_unique(); auto maybe_source = parse_source_paragraph(std::move(control_paragraphs.front())); - if (auto source = maybe_source.get()) + if (const auto source = maybe_source.get()) control_file->core_paragraph = std::move(*source); else return std::move(maybe_source).error(); @@ -147,7 +147,7 @@ namespace vcpkg for (auto&& feature_pgh : control_paragraphs) { auto maybe_feature = parse_feature_paragraph(std::move(feature_pgh)); - if (auto feature = maybe_feature.get()) + if (const auto feature = maybe_feature.get()) control_file->feature_paragraphs.emplace_back(std::move(*feature)); else return std::move(maybe_feature).error(); @@ -263,7 +263,7 @@ namespace vcpkg bool Supports::is_supported(Architecture arch, Platform plat, Linkage crt, ToolsetVersion tools) { - auto is_in_or_empty = [](auto v, auto&& c) -> bool { return c.empty() || c.end() != Util::find(c, v); }; + const auto is_in_or_empty = [](auto v, auto&& c) -> bool { return c.empty() || c.end() != Util::find(c, v); }; if (!is_in_or_empty(arch, architectures)) return false; if (!is_in_or_empty(plat, platforms)) return false; if (!is_in_or_empty(crt, crt_linkages)) return false; diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp index 02ee61f75..aaba95eb9 100644 --- a/toolsrc/src/StatusParagraphs.cpp +++ b/toolsrc/src/StatusParagraphs.cpp @@ -67,7 +67,7 @@ namespace vcpkg { Checks::check_exit(VCPKG_LINE_INFO, pgh != nullptr, "Inserted null paragraph"); const PackageSpec& spec = pgh->package.spec; - auto ptr = find(spec.name(), spec.triplet(), pgh->package.feature); + const auto ptr = find(spec.name(), spec.triplet(), pgh->package.feature); if (ptr == end()) { paragraphs.push_back(std::move(pgh)); -- cgit v1.2.3 From e25a125d8540f13410008dff7281b5d679ac9fcb Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 17:13:45 -0700 Subject: Don't return by const copy --- toolsrc/src/SourceParagraph.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 64b7bbad1..d8fa37914 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -220,11 +220,7 @@ namespace vcpkg return FeatureSpec::from_strings_and_triplet(filter_dependencies(deps, t), t); } - const std::string to_string(const Dependency& dep) - { - std::string name = dep.name(); - return name; - } + std::string to_string(const Dependency& dep) { return dep.name(); } ExpectedT> Supports::parse(const std::vector& strs) { -- cgit v1.2.3 From db06c7fa69da2f8b84431b8b79b0ef64e0bf00bf Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 17:14:50 -0700 Subject: Add missing consts --- toolsrc/src/StatusParagraph.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/StatusParagraph.cpp b/toolsrc/src/StatusParagraph.cpp index 5b5c3978f..f8ae293c2 100644 --- a/toolsrc/src/StatusParagraph.cpp +++ b/toolsrc/src/StatusParagraph.cpp @@ -33,8 +33,8 @@ namespace vcpkg this->package = BinaryParagraph(std::move(fields)); auto b = status_field.begin(); - auto mark = b; - auto e = status_field.end(); + const auto mark = b; + const auto e = status_field.end(); // Todo: improve error handling while (b != e && *b != ' ') -- cgit v1.2.3 From 35a9d223bc14fb4b35d6ad876d208897c8ce590a Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Sep 2017 17:22:55 -0700 Subject: Use Strings::join() and Strings::format() --- toolsrc/src/SourceParagraph.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index d8fa37914..171689ce7 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -170,17 +170,10 @@ namespace vcpkg std::string Dependency::name() const { - std::string str = this->depend.name; - if (this->depend.features.empty()) return str; + if (this->depend.features.empty()) return this->depend.name; - str += "["; - for (auto&& s : this->depend.features) - { - str += s + ","; - } - str.pop_back(); - str += "]"; - return str; + const std::string features = Strings::join(",", this->depend.features); + return Strings::format("%s[%s]", this->depend.name, features); } std::vector vcpkg::expand_qualified_dependencies(const std::vector& depends) -- cgit v1.2.3 From c167c70c272a417779e601fffcbdb72278da1848 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sat, 2 Sep 2017 16:48:29 +0200 Subject: - Added support for VS2013 build chain tools. --- toolsrc/src/PostBuildLint.cpp | 8 +++---- toolsrc/src/VcpkgPaths.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 1fd48d3ec..33dc446cf 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -45,8 +45,8 @@ namespace vcpkg::PostBuildLint {"msvcp100d.dll", R"(msvcp100d\.dll)"}, {"msvcp110.dll", R"(msvcp110\.dll)"}, {"msvcp110_win.dll", R"(msvcp110_win\.dll)"}, - {"msvcp120.dll", R"(msvcp120\.dll)"}, - {"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"}, + //{"msvcp120.dll", R"(msvcp120\.dll)"}, + //{"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"}, {"msvcp60.dll", R"(msvcp60\.dll)"}, {"msvcp60.dll", R"(msvcp60\.dll)"}, @@ -54,8 +54,8 @@ namespace vcpkg::PostBuildLint {"msvcr100d.dll", R"(msvcr100d\.dll)"}, {"msvcr100_clr0400.dll", R"(msvcr100_clr0400\.dll)"}, {"msvcr110.dll", R"(msvcr110\.dll)"}, - {"msvcr120.dll", R"(msvcr120\.dll)"}, - {"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"}, + //{"msvcr120.dll", R"(msvcr120\.dll)"}, + //{"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"}, {"msvcrt20.dll", R"(msvcrt20\.dll)"}, {"msvcrt40.dll", R"(msvcrt40\.dll)"}}; diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 906a5e67f..71a35d24c 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -268,6 +268,19 @@ namespace vcpkg return nullopt; } + + static Optional get_vs2013_installation_instance() + { + const Optional vs2013_cmntools_optional = System::get_environment_variable(L"VS120COMNTOOLS"); + if (const auto v = vs2013_cmntools_optional.get()) + { + const fs::path vs2013_cmntools = fs::path(*v).parent_path(); // The call to parent_path() is needed because + // the env variable has a trailing backslash + return vs2013_cmntools.parent_path().parent_path(); + } + + return nullopt; + } static std::vector find_toolset_instances(const VcpkgPaths& paths) { @@ -275,12 +288,46 @@ namespace vcpkg const auto& fs = paths.get_filesystem(); - const std::vector vs2017_installation_instances = get_vs2017_installation_instances(paths); // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. std::vector paths_examined; std::vector found_toolsets; + // VS2013 + const Optional vs_2013_installation_instance = get_vs2013_installation_instance(); + if (const auto v = vs_2013_installation_instance.get()) + { + const fs::path vs2013_vcvarsall_bat = *v / "VC" / "vcvarsall.bat"; + + paths_examined.push_back(vs2013_vcvarsall_bat); + if (fs.exists(vs2013_vcvarsall_bat)) + { + const fs::path vs2013_dumpbin_exe = *v / "VC" / "bin" / "dumpbin.exe"; + paths_examined.push_back(vs2013_dumpbin_exe); + + const fs::path vs2013_bin_dir = vs2013_vcvarsall_bat.parent_path() / "bin"; + std::vector supported_architectures; + if (fs.exists(vs2013_bin_dir / "vcvars32.bat")) + supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); + if (fs.exists(3 / "amd64\\vcvars64.bat")) + supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); + if (fs.exists(vs2013_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) + supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + if (fs.exists(vs2013_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) + supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); + if (fs.exists(vs2013_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) + supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + if (fs.exists(vs2013_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) + supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + + if (fs.exists(vs2013_dumpbin_exe)) + { + found_toolsets.push_back( + {vs2013_dumpbin_exe, vs2013_vcvarsall_bat, L"v120", supported_architectures}); + } + } + } + // VS2015 const Optional vs_2015_installation_instance = get_vs2015_installation_instance(); if (const auto v = vs_2015_installation_instance.get()) @@ -318,6 +365,7 @@ namespace vcpkg // VS2017 Optional vs2017_toolset; + const std::vector vs2017_installation_instances = get_vs2017_installation_instances(paths); for (const std::string& instance : vs2017_installation_instances) { const fs::path vc_dir = fs::path{instance} / "VC"; -- cgit v1.2.3 From bafe4f2fe071503458b4f7c2bf1c645420dbc6ff Mon Sep 17 00:00:00 2001 From: atkawa7 Date: Wed, 6 Sep 2017 10:33:51 -0700 Subject: an empty delimiter causes the split function to fail --- toolsrc/src/vcpkg_Strings.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 15851829d..5ad951399 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -136,6 +136,11 @@ namespace vcpkg::Strings std::vector split(const std::string& s, const std::string& delimiter) { std::vector output; + + if(delimiter.empty()){ + output.push_back(s); + return output; + } size_t i = 0; for (size_t pos = s.find(delimiter); pos != std::string::npos; pos = s.find(delimiter, pos)) -- cgit v1.2.3 From d2de7d3e7d1a0bea3dba9a0a7f6cfff68ae513a0 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 7 Sep 2017 16:16:30 -0700 Subject: [vcpkg_Build.h] Naming scheme, unneeded #include, unneeded inline --- toolsrc/src/commands_ci.cpp | 2 +- toolsrc/src/vcpkg_Build.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index ca5e8a9a9..fda9f1716 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -77,7 +77,7 @@ namespace vcpkg::Commands::CI } std::map summary; - for (const BuildResult& v : Build::BuildResult_values) + for (const BuildResult& v : Build::BUILD_RESULT_VALUES) { summary[v] = 0; } diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index a2fa99ac8..d40140aca 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -289,7 +289,7 @@ namespace vcpkg::Build if (!version.empty()) build_info.version = std::move(version); std::map policies; - for (auto policy : g_all_policies) + for (auto policy : G_ALL_POLICIES) { const auto setting = parser.optional_field(to_string(policy)); if (setting.empty()) continue; -- cgit v1.2.3 From 43dde3f4892be55558b012b845d864e7be95c7b9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 13 Sep 2017 16:10:25 -0700 Subject: Refactor package removal code to eliminate its duplication --- toolsrc/src/commands_install.cpp | 73 ++++++++-------------------------------- toolsrc/src/commands_remove.cpp | 63 +++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 86 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index d7c14f39c..2473ad599 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -524,72 +524,27 @@ namespace vcpkg::Commands::Install Checks::exit_success(VCPKG_LINE_INFO); } - // execute the plan - if (GlobalState::feature_packages) - { - for (const auto& action : action_plan) - { - if (auto install_action = action.install_plan.get()) - { - const BuildResult result = - perform_install_plan_action(paths, *install_action, install_plan_options, status_db); - if (result != BuildResult::SUCCEEDED) - { - System::println(Build::create_user_troubleshooting_message(install_action->spec)); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - else if (auto remove_action = action.remove_plan.get()) - { - static const std::string OPTION_PURGE = "--purge"; - static const std::string OPTION_NO_PURGE = "--no-purge"; - - const bool alsoRemoveFolderFromPackages = options.find(OPTION_NO_PURGE) == options.end(); - if (options.find(OPTION_PURGE) != options.end() && !alsoRemoveFolderFromPackages) - { - // User specified --purge and --no-purge - System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); - System::print(EXAMPLE); - Checks::exit_fail(VCPKG_LINE_INFO); - } - const std::string display_name = remove_action->spec.to_string(); - switch (remove_action->plan_type) - { - case RemovePlanType::NOT_INSTALLED: - System::println(System::Color::success, "Package %s is not installed", display_name); - break; - case RemovePlanType::REMOVE: - System::println("Removing package %s... ", display_name); - Commands::Remove::remove_package(paths, remove_action->spec, &status_db); - System::println(System::Color::success, "Removing package %s... done", display_name); - break; - case RemovePlanType::UNKNOWN: - default: Checks::unreachable(VCPKG_LINE_INFO); - } - - if (alsoRemoveFolderFromPackages) - { - System::println("Purging package %s... ", display_name); - Files::Filesystem& fs = paths.get_filesystem(); - std::error_code ec; - fs.remove_all(paths.packages / remove_action->spec.dir(), ec); - System::println(System::Color::success, "Purging package %s... done", display_name); - } - } - } - } - else + for (const auto& action : action_plan) { - for (const auto& action : action_plan) + if (auto install_action = action.install_plan.get()) { - const auto& iaction = action.install_plan.value_or_exit(VCPKG_LINE_INFO); - const BuildResult result = perform_install_plan_action(paths, iaction, install_plan_options, status_db); + const BuildResult result = + perform_install_plan_action(paths, *install_action, install_plan_options, status_db); if (result != BuildResult::SUCCEEDED) { - System::println(Build::create_user_troubleshooting_message(iaction.spec)); + System::println(Build::create_user_troubleshooting_message(install_action->spec)); Checks::exit_fail(VCPKG_LINE_INFO); } } + else if (auto remove_action = action.remove_plan.get()) + { + Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages); + Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db); + } + else + { + Checks::unreachable(VCPKG_LINE_INFO); + } } Checks::exit_success(VCPKG_LINE_INFO); diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index 2b5033166..453e0ec96 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -129,6 +129,37 @@ namespace vcpkg::Commands::Remove } } + void perform_remove_plan_action(const VcpkgPaths& paths, + const RemovePlanAction& action, + const Purge purge, + StatusParagraphs& status_db) + { + const std::string display_name = action.spec.to_string(); + + switch (action.plan_type) + { + case RemovePlanType::NOT_INSTALLED: + System::println(System::Color::success, "Package %s is not installed", display_name); + break; + case RemovePlanType::REMOVE: + System::println("Removing package %s... ", display_name); + remove_package(paths, action.spec, &status_db); + System::println(System::Color::success, "Removing package %s... done", display_name); + break; + case RemovePlanType::UNKNOWN: + default: Checks::unreachable(VCPKG_LINE_INFO); + } + + if (purge == Purge::YES) + { + System::println("Purging package %s... ", display_name); + Files::Filesystem& fs = paths.get_filesystem(); + std::error_code ec; + fs.remove_all(paths.packages / action.spec.dir(), ec); + System::println(System::Color::success, "Purging package %s... done", display_name); + } + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { static const std::string OPTION_PURGE = "--purge"; @@ -166,14 +197,15 @@ namespace vcpkg::Commands::Remove Input::check_triplet(spec.triplet(), paths); } - const bool alsoRemoveFolderFromPackages = options.find(OPTION_NO_PURGE) == options.end(); - if (options.find(OPTION_PURGE) != options.end() && !alsoRemoveFolderFromPackages) + const bool no_purge_was_passed = options.find(OPTION_NO_PURGE) != options.end(); + const bool purge_was_passed = options.find(OPTION_PURGE) != options.end(); + if (purge_was_passed && no_purge_was_passed) { - // User specified --purge and --no-purge System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); System::print(EXAMPLE); Checks::exit_fail(VCPKG_LINE_INFO); } + const Purge purge = to_purge(purge_was_passed || !no_purge_was_passed); const bool isRecursive = options.find(OPTION_RECURSE) != options.cend(); const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend(); @@ -209,30 +241,7 @@ namespace vcpkg::Commands::Remove for (const RemovePlanAction& action : remove_plan) { - const std::string display_name = action.spec.to_string(); - - switch (action.plan_type) - { - case RemovePlanType::NOT_INSTALLED: - System::println(System::Color::success, "Package %s is not installed", display_name); - break; - case RemovePlanType::REMOVE: - System::println("Removing package %s... ", display_name); - remove_package(paths, action.spec, &status_db); - System::println(System::Color::success, "Removing package %s... done", display_name); - break; - case RemovePlanType::UNKNOWN: - default: Checks::unreachable(VCPKG_LINE_INFO); - } - - if (alsoRemoveFolderFromPackages) - { - System::println("Purging package %s... ", display_name); - Files::Filesystem& fs = paths.get_filesystem(); - std::error_code ec; - fs.remove_all(paths.packages / action.spec.dir(), ec); - System::println(System::Color::success, "Purging package %s... done", display_name); - } + perform_remove_plan_action(paths, action, purge, status_db); } Checks::exit_success(VCPKG_LINE_INFO); -- cgit v1.2.3 From 32a01e68516d51b998ec80878eb20c000f6c95ba Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 13 Sep 2017 16:12:08 -0700 Subject: [install] Naming scheme and const --- toolsrc/src/commands_install.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 2473ad599..2e169e8af 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -59,7 +59,7 @@ namespace vcpkg::Commands::Install auto files = fs.get_files_recursive(source_dir); for (auto&& file : files) { - auto status = fs.status(file, ec); + const auto status = fs.status(file, ec); if (ec) { System::println(System::Color::error, "failed: %s: %s", file.u8string(), ec.message()); @@ -309,7 +309,7 @@ namespace vcpkg::Commands::Install const BinaryControlFile bcf = Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); System::println("Installing package %s... ", display_name_with_features); - auto install_result = install_package(paths, bcf, &status_db); + const auto install_result = install_package(paths, bcf, &status_db); switch (install_result) { case InstallResult::SUCCESS: @@ -328,7 +328,7 @@ namespace vcpkg::Commands::Install System::Color::warning, "Package %s is already built -- not building from HEAD", display_name); } System::println("Installing package %s... ", display_name); - auto install_result = install_package( + const auto install_result = install_package( paths, action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO), &status_db); switch (install_result) { @@ -470,7 +470,7 @@ namespace vcpkg::Commands::Install const std::unordered_set options = args.check_and_get_optional_command_arguments( {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE}); - const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend(); + const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend(); const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend(); const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); @@ -519,14 +519,14 @@ namespace vcpkg::Commands::Install print_plan(action_plan, is_recursive); - if (dryRun) + if (dry_run) { Checks::exit_success(VCPKG_LINE_INFO); } for (const auto& action : action_plan) { - if (auto install_action = action.install_plan.get()) + if (const auto install_action = action.install_plan.get()) { const BuildResult result = perform_install_plan_action(paths, *install_action, install_plan_options, status_db); @@ -536,7 +536,7 @@ namespace vcpkg::Commands::Install Checks::exit_fail(VCPKG_LINE_INFO); } } - else if (auto remove_action = action.remove_plan.get()) + else if (const auto remove_action = action.remove_plan.get()) { Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages); Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db); -- cgit v1.2.3 From d521d366b278e9e963c18d34a7c5f41f42ea9ec7 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 13 Sep 2017 17:23:04 -0700 Subject: Rework vcpkg install (and vcpkg ci) - Refactor install-plan-execution code to reduce duplication - Add `vcpkg install --keep-going` option - Add elapsed time to each invidial package and total time - Add a counter to the install (e.g. Starting package 3/12: ) --- toolsrc/src/commands_ci.cpp | 52 +++-------------- toolsrc/src/commands_install.cpp | 112 +++++++++++++++++++++++++++++-------- toolsrc/src/vcpkg_Dependencies.cpp | 15 +++++ 3 files changed, 111 insertions(+), 68 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index fda9f1716..75ff65556 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -41,57 +41,19 @@ namespace vcpkg::Commands::CI StatusParagraphs status_db = database_load_check(paths); const auto& paths_port_file = Dependencies::PathsPortFile(paths); - const std::vector install_plan = + std::vector install_plan = Dependencies::create_install_plan(paths_port_file, specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); - std::vector results; - std::vector timing; - const ElapsedTime timer = ElapsedTime::create_started(); - size_t counter = 0; - const size_t package_count = install_plan.size(); const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; - for (const InstallPlanAction& action : install_plan) - { - const ElapsedTime build_timer = ElapsedTime::create_started(); - counter++; - const std::string display_name = action.spec.to_string(); - System::println("Starting package %d/%d: %s", counter, package_count, display_name); + const std::vector action_plan = + Util::fmap(install_plan, [](InstallPlanAction& install_action) { + return Dependencies::AnyAction(std::move(install_action)); + }); - timing.push_back("0"); - results.push_back(BuildResult::NULLVALUE); - - const BuildResult result = - Install::perform_install_plan_action(paths, action, install_plan_options, status_db); - timing.back() = build_timer.to_string(); - results.back() = result; - System::println("Elapsed time for package %s: %s", action.spec, build_timer.to_string()); - } - - System::println("Total time taken: %s", timer.to_string()); - - for (size_t i = 0; i < results.size(); i++) - { - System::println("%s: %s: %s", install_plan[i].spec, Build::to_string(results[i]), timing[i]); - } - - std::map summary; - for (const BuildResult& v : Build::BUILD_RESULT_VALUES) - { - summary[v] = 0; - } - - for (const BuildResult& r : results) - { - summary[r]++; - } - - System::println("\n\nSUMMARY"); - for (const std::pair& entry : summary) - { - System::println(" %s: %d", Build::to_string(entry.first), entry.second); - } + Install::perform_and_exit( + action_plan, install_plan_options, Install::KeepGoing::YES, Install::PrintSummary::YES, paths, status_db); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 2e169e8af..d4cb94775 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -442,12 +442,98 @@ namespace vcpkg::Commands::Install } } + void perform_and_exit(const std::vector& action_plan, + const Build::BuildPackageOptions& install_plan_options, + const KeepGoing keep_going, + const PrintSummary print_summary, + const VcpkgPaths& paths, + StatusParagraphs& status_db) + { + std::vector results; + std::vector timing; + const ElapsedTime timer = ElapsedTime::create_started(); + size_t counter = 0; + const size_t package_count = action_plan.size(); + + for (const auto& action : action_plan) + { + const ElapsedTime build_timer = ElapsedTime::create_started(); + counter++; + + if (counter > 2) + { + break; + } + + const std::string display_name = action.spec().to_string(); + System::println("Starting package %d/%d: %s", counter, package_count, display_name); + + timing.push_back("0"); + results.push_back(BuildResult::NULLVALUE); + + if (const auto install_action = action.install_plan.get()) + { + const BuildResult result = + perform_install_plan_action(paths, *install_action, install_plan_options, status_db); + if (result != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO) + { + System::println(Build::create_user_troubleshooting_message(install_action->spec)); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + results.back() = result; + } + else if (const auto remove_action = action.remove_plan.get()) + { + Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages); + Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db); + } + else + { + Checks::unreachable(VCPKG_LINE_INFO); + } + + timing.back() = build_timer.to_string(); + System::println("Elapsed time for package %s: %s", display_name, build_timer.to_string()); + } + + System::println("Total time taken: %s", timer.to_string()); + + if (print_summary == PrintSummary::YES) + { + for (size_t i = 0; i < results.size(); i++) + { + System::println("%s: %s: %s", action_plan[i].spec(), Build::to_string(results[i]), timing[i]); + } + + std::map summary; + for (const BuildResult& v : Build::BUILD_RESULT_VALUES) + { + summary[v] = 0; + } + + for (const BuildResult& r : results) + { + summary[r]++; + } + + System::println("\n\nSUMMARY"); + for (const std::pair& entry : summary) + { + System::println(" %s: %d", Build::to_string(entry.first), entry.second); + } + } + + Checks::exit_success(VCPKG_LINE_INFO); + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_USE_HEAD_VERSION = "--head"; static const std::string OPTION_NO_DOWNLOADS = "--no-downloads"; static const std::string OPTION_RECURSE = "--recurse"; + static const std::string OPTION_KEEP_GOING = "--keep-going"; // input sanitization static const std::string EXAMPLE = @@ -469,11 +555,12 @@ namespace vcpkg::Commands::Install } const std::unordered_set options = args.check_and_get_optional_command_arguments( - {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE}); + {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE, OPTION_KEEP_GOING}); const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend(); const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend(); const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); + const KeepGoing keep_going = to_keep_going(options.find(OPTION_KEEP_GOING) != options.cend()); // create the plan StatusParagraphs status_db = database_load_check(paths); @@ -524,28 +611,7 @@ namespace vcpkg::Commands::Install Checks::exit_success(VCPKG_LINE_INFO); } - for (const auto& action : action_plan) - { - if (const auto install_action = action.install_plan.get()) - { - const BuildResult result = - perform_install_plan_action(paths, *install_action, install_plan_options, status_db); - if (result != BuildResult::SUCCEEDED) - { - System::println(Build::create_user_troubleshooting_message(install_action->spec)); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - else if (const auto remove_action = action.remove_plan.get()) - { - Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages); - Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db); - } - else - { - Checks::unreachable(VCPKG_LINE_INFO); - } - } + perform_and_exit(action_plan, install_plan_options, keep_going, PrintSummary::NO, paths, status_db); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 1a0f0a6ed..8dd60a2eb 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -213,6 +213,21 @@ namespace vcpkg::Dependencies { } + const PackageSpec& AnyAction::spec() const + { + if (const auto p = install_plan.get()) + { + return p->spec; + } + + if (const auto p = remove_plan.get()) + { + return p->spec; + } + + Checks::exit_with_message(VCPKG_LINE_INFO, "Null action"); + } + bool ExportPlanAction::compare_by_name(const ExportPlanAction* left, const ExportPlanAction* right) { return left->spec.name() < right->spec.name(); -- cgit v1.2.3 From d080439ce408c4fd0312f0925f10543179e79b27 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 13 Sep 2017 21:46:48 -0700 Subject: [commands_remove.cpp] Naming scheme and missing const --- toolsrc/src/commands_remove.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index 453e0ec96..a9f1b2564 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -18,7 +18,7 @@ namespace vcpkg::Commands::Remove { auto& fs = paths.get_filesystem(); auto spghs = status_db->find_all(spec.name(), spec.triplet()); - auto core_pkg = **status_db->find(spec.name(), spec.triplet(), Strings::EMPTY); + const auto core_pkg = **status_db->find(spec.name(), spec.triplet(), Strings::EMPTY); for (auto&& spgh : spghs) { @@ -31,7 +31,7 @@ namespace vcpkg::Commands::Remove auto maybe_lines = fs.read_lines(paths.listfile_path(core_pkg.package)); - if (auto lines = maybe_lines.get()) + if (const auto lines = maybe_lines.get()) { std::vector dirs_touched; for (auto&& suffix : *lines) @@ -42,7 +42,7 @@ namespace vcpkg::Commands::Remove auto target = paths.installed / suffix; - auto status = fs.status(target, ec); + const auto status = fs.status(target, ec); if (ec) { System::println(System::Color::error, "failed: %s", ec.message()); @@ -72,7 +72,7 @@ namespace vcpkg::Commands::Remove } auto b = dirs_touched.rbegin(); - auto e = dirs_touched.rend(); + const auto e = dirs_touched.rend(); for (; b != e; ++b) { if (fs.is_empty(*b)) @@ -100,11 +100,11 @@ namespace vcpkg::Commands::Remove static void print_plan(const std::map>& group_by_plan_type) { - static constexpr std::array order = {RemovePlanType::NOT_INSTALLED, RemovePlanType::REMOVE}; + static constexpr std::array ORDER = {RemovePlanType::NOT_INSTALLED, RemovePlanType::REMOVE}; - for (const RemovePlanType plan_type : order) + for (const RemovePlanType plan_type : ORDER) { - auto it = group_by_plan_type.find(plan_type); + const auto it = group_by_plan_type.find(plan_type); if (it == group_by_plan_type.cend()) { continue; @@ -206,8 +206,8 @@ namespace vcpkg::Commands::Remove Checks::exit_fail(VCPKG_LINE_INFO); } const Purge purge = to_purge(purge_was_passed || !no_purge_was_passed); - const bool isRecursive = options.find(OPTION_RECURSE) != options.cend(); - const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend(); + const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); + const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend(); const std::vector remove_plan = Dependencies::create_remove_plan(specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !remove_plan.empty(), "Remove plan cannot be empty"); @@ -226,7 +226,7 @@ namespace vcpkg::Commands::Remove System::println(System::Color::warning, "Additional packages (*) need to be removed to complete this operation."); - if (!isRecursive) + if (!is_recursive) { System::println(System::Color::warning, "If you are sure you want to remove them, run the command with the --recurse option"); @@ -234,7 +234,7 @@ namespace vcpkg::Commands::Remove } } - if (dryRun) + if (dry_run) { Checks::exit_success(VCPKG_LINE_INFO); } -- cgit v1.2.3 From 2d1bee6bb5f776e6f7281d0245ef7f0030cb7412 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 13 Sep 2017 21:48:38 -0700 Subject: [vcpkg.cpp] Naming scheme --- toolsrc/src/vcpkg.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 781f03585..75b61f952 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -104,7 +104,7 @@ static void inner(const VcpkgCmdArguments& args) return invalid_command(args.command); } -static void loadConfig() +static void load_config() { fs::path localappdata; { @@ -207,7 +207,7 @@ int wmain(const int argc, const wchar_t* const* const argv) locked_metrics->track_property("version", Commands::Version::version()); locked_metrics->track_property("cmdline", trimmed_command_line); } - loadConfig(); + load_config(); Metrics::g_metrics.lock()->track_property("sqmuser", Metrics::get_SQM_user()); const VcpkgCmdArguments args = VcpkgCmdArguments::create_from_command_line(argc, argv); -- cgit v1.2.3 From c6af9797fd5a4df5f3b709784c95e9590beb2d32 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 13 Sep 2017 23:08:01 -0700 Subject: [metrics.cpp] Naming scheme and missing const --- toolsrc/src/metrics.cpp | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp index 8a7d02a30..3c352f1a6 100644 --- a/toolsrc/src/metrics.cpp +++ b/toolsrc/src/metrics.cpp @@ -20,9 +20,9 @@ namespace vcpkg::Metrics _ftime_s(&timebuffer); time_t now = timebuffer.time; - int milli = timebuffer.millitm; + const int milli = timebuffer.millitm; - errno_t err = gmtime_s(&newtime, &now); + const errno_t err = gmtime_s(&newtime, &now); if (err) { return Strings::EMPTY; @@ -34,7 +34,7 @@ namespace vcpkg::Metrics static std::string generate_random_UUID() { - int partSizes[] = {8, 4, 4, 4, 12}; + int part_sizes[] = {8, 4, 4, 4, 12}; char uuid[37]; memset(uuid, 0, sizeof(uuid)); int num; @@ -50,7 +50,7 @@ namespace vcpkg::Metrics // Generating UUID format version 4 // http://en.wikipedia.org/wiki/Universally_unique_identifier - for (int i = 0; i < partSizes[part]; i++, index++) + for (int i = 0; i < part_sizes[part]; i++, index++) { if (part == 2 && i == 0) { @@ -81,8 +81,8 @@ namespace vcpkg::Metrics static const std::string& get_session_id() { - static const std::string id = generate_random_UUID(); - return id; + static const std::string ID = generate_random_UUID(); + return ID; } static std::string to_json_string(const std::string& str) @@ -101,11 +101,11 @@ namespace vcpkg::Metrics else if (ch < 0x20 || ch >= 0x80) { // Note: this treats incoming Strings as Latin-1 - static constexpr const char hex[16] = { + static constexpr const char HEX[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; encoded.append("\\u00"); - encoded.push_back(hex[ch / 16]); - encoded.push_back(hex[ch % 16]); + encoded.push_back(HEX[ch / 16]); + encoded.push_back(HEX[ch % 16]); } else { @@ -120,7 +120,7 @@ namespace vcpkg::Metrics { std::wstring path; path.resize(MAX_PATH); - auto n = GetSystemDirectoryW(&path[0], static_cast(path.size())); + const auto n = GetSystemDirectoryW(&path[0], static_cast(path.size())); path.resize(n); path += L"\\kernel32.dll"; @@ -282,10 +282,11 @@ namespace vcpkg::Metrics { if (MAXDWORD <= payload.size()) abort(); std::wstring hdrs = L"Content-Type: application/json\r\n"; + std::string& p = const_cast(payload); bResults = WinHttpSendRequest(hRequest, hdrs.c_str(), static_cast(hdrs.size()), - (void*)&payload[0], + static_cast(&p[0]), static_cast(payload.size()), static_cast(payload.size()), 0); @@ -308,24 +309,24 @@ namespace vcpkg::Metrics WINHTTP_NO_HEADER_INDEX); } - std::vector responseBuffer; + std::vector response_buffer; if (bResults) { - DWORD availableData = 0, readData = 0, totalData = 0; - while ((bResults = WinHttpQueryDataAvailable(hRequest, &availableData)) == TRUE && availableData > 0) + DWORD available_data = 0, read_data = 0, total_data = 0; + while ((bResults = WinHttpQueryDataAvailable(hRequest, &available_data)) == TRUE && available_data > 0) { - responseBuffer.resize(responseBuffer.size() + availableData); + response_buffer.resize(response_buffer.size() + available_data); - bResults = WinHttpReadData(hRequest, &responseBuffer.data()[totalData], availableData, &readData); + bResults = WinHttpReadData(hRequest, &response_buffer.data()[total_data], available_data, &read_data); if (!bResults) { break; } - totalData += readData; + total_data += read_data; - responseBuffer.resize(totalData); + response_buffer.resize(total_data); } } @@ -388,8 +389,8 @@ namespace vcpkg::Metrics const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); fs.write_contents(vcpkg_metrics_txt_path, payload); - const std::wstring cmdLine = + const std::wstring cmd_line = Strings::wformat(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native()); - System::cmd_execute_clean(cmdLine); + System::cmd_execute_clean(cmd_line); } } -- cgit v1.2.3 From 263466642face5485d50bccb60b45e774fe31fd9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 13 Sep 2017 23:10:53 -0700 Subject: [metrics.cpp] More naming scheme and const fixes --- toolsrc/src/metrics.cpp | 95 ++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 48 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp index 3c352f1a6..8a0050bfc 100644 --- a/toolsrc/src/metrics.cpp +++ b/toolsrc/src/metrics.cpp @@ -124,7 +124,7 @@ namespace vcpkg::Metrics path.resize(n); path += L"\\kernel32.dll"; - auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr); + const auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr); if (versz == 0) return Strings::EMPTY; std::vector verbuf; @@ -152,7 +152,7 @@ namespace vcpkg::Metrics std::string properties; std::string measurements; - void TrackProperty(const std::string& name, const std::string& value) + void track_property(const std::string& name, const std::string& value) { if (properties.size() != 0) properties.push_back(','); properties.append(to_json_string(name)); @@ -160,7 +160,7 @@ namespace vcpkg::Metrics properties.append(to_json_string(value)); } - void TrackMetric(const std::string& name, double value) + void track_metric(const std::string& name, double value) { if (measurements.size() != 0) measurements.push_back(','); measurements.append(to_json_string(name)); @@ -241,7 +241,7 @@ namespace vcpkg::Metrics void Metrics::set_print_metrics(bool should_print_metrics) { g_should_print_metrics = should_print_metrics; } - void Metrics::track_metric(const std::string& name, double value) { g_metricmessage.TrackMetric(name, value); } + void Metrics::track_metric(const std::string& name, double value) { g_metricmessage.track_metric(name, value); } void Metrics::track_property(const std::string& name, const std::wstring& value) { @@ -251,75 +251,74 @@ namespace vcpkg::Metrics std::transform( value.begin(), value.end(), converted_value.begin(), [](wchar_t ch) { return static_cast(ch); }); - g_metricmessage.TrackProperty(name, converted_value); + g_metricmessage.track_property(name, converted_value); } void Metrics::track_property(const std::string& name, const std::string& value) { - g_metricmessage.TrackProperty(name, value); + g_metricmessage.track_property(name, value); } void Metrics::upload(const std::string& payload) { - HINTERNET hSession = nullptr, hConnect = nullptr, hRequest = nullptr; - BOOL bResults = FALSE; + HINTERNET connect = nullptr, request = nullptr; + BOOL results = FALSE; - hSession = WinHttpOpen( + const HINTERNET session = WinHttpOpen( L"vcpkg/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); - if (hSession) - hConnect = WinHttpConnect(hSession, L"dc.services.visualstudio.com", INTERNET_DEFAULT_HTTPS_PORT, 0); - - if (hConnect) - hRequest = WinHttpOpenRequest(hConnect, - L"POST", - L"/v2/track", - nullptr, - WINHTTP_NO_REFERER, - WINHTTP_DEFAULT_ACCEPT_TYPES, - WINHTTP_FLAG_SECURE); - - if (hRequest) + if (session) connect = WinHttpConnect(session, L"dc.services.visualstudio.com", INTERNET_DEFAULT_HTTPS_PORT, 0); + + if (connect) + request = WinHttpOpenRequest(connect, + L"POST", + L"/v2/track", + nullptr, + WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, + WINHTTP_FLAG_SECURE); + + if (request) { if (MAXDWORD <= payload.size()) abort(); std::wstring hdrs = L"Content-Type: application/json\r\n"; std::string& p = const_cast(payload); - bResults = WinHttpSendRequest(hRequest, - hdrs.c_str(), - static_cast(hdrs.size()), - static_cast(&p[0]), - static_cast(payload.size()), - static_cast(payload.size()), - 0); + results = WinHttpSendRequest(request, + hdrs.c_str(), + static_cast(hdrs.size()), + static_cast(&p[0]), + static_cast(payload.size()), + static_cast(payload.size()), + 0); } - if (bResults) + if (results) { - bResults = WinHttpReceiveResponse(hRequest, nullptr); + results = WinHttpReceiveResponse(request, nullptr); } DWORD http_code = 0, junk = sizeof(DWORD); - if (bResults) + if (results) { - bResults = WinHttpQueryHeaders(hRequest, - WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, - nullptr, - &http_code, - &junk, - WINHTTP_NO_HEADER_INDEX); + results = WinHttpQueryHeaders(request, + WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, + nullptr, + &http_code, + &junk, + WINHTTP_NO_HEADER_INDEX); } std::vector response_buffer; - if (bResults) + if (results) { DWORD available_data = 0, read_data = 0, total_data = 0; - while ((bResults = WinHttpQueryDataAvailable(hRequest, &available_data)) == TRUE && available_data > 0) + while ((results = WinHttpQueryDataAvailable(request, &available_data)) == TRUE && available_data > 0) { response_buffer.resize(response_buffer.size() + available_data); - bResults = WinHttpReadData(hRequest, &response_buffer.data()[total_data], available_data, &read_data); + results = WinHttpReadData(request, &response_buffer.data()[total_data], available_data, &read_data); - if (!bResults) + if (!results) { break; } @@ -330,7 +329,7 @@ namespace vcpkg::Metrics } } - if (!bResults) + if (!results) { #ifndef NDEBUG __debugbreak(); @@ -339,22 +338,22 @@ namespace vcpkg::Metrics #endif } - if (hRequest) WinHttpCloseHandle(hRequest); - if (hConnect) WinHttpCloseHandle(hConnect); - if (hSession) WinHttpCloseHandle(hSession); + if (request) WinHttpCloseHandle(request); + if (connect) WinHttpCloseHandle(connect); + if (session) WinHttpCloseHandle(session); } static fs::path get_bindir() { wchar_t buf[_MAX_PATH]; - int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); + const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); if (bytes == 0) std::abort(); return fs::path(buf, buf + bytes); } void Metrics::flush() { - std::string payload = g_metricmessage.format_event_data_template(); + const std::string payload = g_metricmessage.format_event_data_template(); if (g_should_print_metrics) std::cerr << payload << "\n"; if (!g_should_send_metrics) return; -- cgit v1.2.3 From 2d6029e41c68fd44b22f8cef1b13fbaa44c8fad9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 14 Sep 2017 04:04:15 -0700 Subject: Introduce Version::warn_if_vcpkg_version_mismatch() --- toolsrc/src/commands_update.cpp | 28 ++-------------------------- toolsrc/src/commands_version.cpp | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 28 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp index 35f24af12..42a8333bd 100644 --- a/toolsrc/src/commands_update.cpp +++ b/toolsrc/src/commands_update.cpp @@ -2,7 +2,6 @@ #include "Paragraphs.h" #include "vcpkg_Commands.h" -#include "vcpkg_Files.h" #include "vcpkg_System.h" #include "vcpkglib.h" @@ -22,7 +21,7 @@ namespace vcpkg::Commands::Update std::vector output; for (const StatusParagraph* pgh : installed_packages) { - auto it = src_names_to_versions.find(pgh->package.spec.name()); + const auto it = src_names_to_versions.find(pgh->package.spec.name()); if (it == src_names_to_versions.end()) { // Package was not installed from portfile @@ -69,30 +68,7 @@ namespace vcpkg::Commands::Update install_line); } - auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt"); - if (auto version_contents = version_file.get()) - { - int maj1, min1, rev1; - auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1); - - int maj2, min2, rev2; - auto num2 = sscanf_s(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2); - - if (num1 == 3 && num2 == 3) - { - if (maj1 != maj2 || min1 != min2 || rev1 != rev2) - { - System::println("Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use " - ".\\bootstrap-vcpkg.bat to update.", - maj2, - min2, - rev2, - maj1, - min1, - rev1); - } - } - } + Version::warn_if_vcpkg_version_mismatch(paths); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/commands_version.cpp b/toolsrc/src/commands_version.cpp index af81cd26e..fdbe7b66c 100644 --- a/toolsrc/src/commands_version.cpp +++ b/toolsrc/src/commands_version.cpp @@ -13,7 +13,7 @@ namespace vcpkg::Commands::Version { const std::string& version() { - static const std::string s_version = + static const std::string S_VERSION = #include "../VERSION.txt" +std::string(VCPKG_VERSION_AS_STRING) @@ -21,7 +21,35 @@ namespace vcpkg::Commands::Version + std::string("-debug") #endif + std::string(Metrics::get_compiled_metrics_enabled() ? Strings::EMPTY : "-external"); - return s_version; + return S_VERSION; + } + + void warn_if_vcpkg_version_mismatch(const VcpkgPaths& paths) + { + auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt"); + if (const auto version_contents = version_file.get()) + { + int maj1, min1, rev1; + const auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1); + + int maj2, min2, rev2; + const auto num2 = sscanf_s(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2); + + if (num1 == 3 && num2 == 3) + { + if (maj1 != maj2 || min1 != min2 || rev1 != rev2) + { + System::println("Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use " + ".\\bootstrap-vcpkg.bat to update.", + maj2, + min2, + rev2, + maj1, + min1, + rev1); + } + } + } } void perform_and_exit(const VcpkgCmdArguments& args) -- cgit v1.2.3 From d55036a7978d122292f3e33c84ae49269ba5498b Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 14 Sep 2017 04:12:13 -0700 Subject: Change message of version mismach to a warning --- toolsrc/src/commands_version.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_version.cpp b/toolsrc/src/commands_version.cpp index fdbe7b66c..5744ea9ef 100644 --- a/toolsrc/src/commands_version.cpp +++ b/toolsrc/src/commands_version.cpp @@ -39,7 +39,8 @@ namespace vcpkg::Commands::Version { if (maj1 != maj2 || min1 != min2 || rev1 != rev2) { - System::println("Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use " + System::println(System::Color::warning, + "Warning: Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use " ".\\bootstrap-vcpkg.bat to update.", maj2, min2, -- cgit v1.2.3 From be27ae05f081997556b3273ba23c6e574d469854 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 14 Sep 2017 04:13:03 -0700 Subject: Version check is now performed before running any command (except vcpkg version/hash/contact) --- toolsrc/src/commands_update.cpp | 2 -- toolsrc/src/vcpkg.cpp | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp index 42a8333bd..71ea4b063 100644 --- a/toolsrc/src/commands_update.cpp +++ b/toolsrc/src/commands_update.cpp @@ -68,8 +68,6 @@ namespace vcpkg::Commands::Update install_line); } - Version::warn_if_vcpkg_version_mismatch(paths); - Checks::exit_success(VCPKG_LINE_INFO); } } diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 75b61f952..f4300a73c 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -69,6 +69,7 @@ static void inner(const VcpkgCmdArguments& args) const VcpkgPaths paths = expected_paths.value_or_exit(VCPKG_LINE_INFO); const int exit_code = _wchdir(paths.root.c_str()); Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed"); + Commands::Version::warn_if_vcpkg_version_mismatch(paths); if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_b())) { -- cgit v1.2.3 From aa72ecc6a4ef205526c5e435a54e18ec042fe260 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 14 Sep 2017 08:14:41 -0700 Subject: [vcpkg] hotfix for ci/install merge Disables accidental testing statement that was left in during the commit. --- toolsrc/src/commands_install.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index d4cb94775..b530a394c 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -462,7 +462,7 @@ namespace vcpkg::Commands::Install if (counter > 2) { - break; + // break; } const std::string display_name = action.spec().to_string(); -- cgit v1.2.3 From 8339f29df5fb5657cdeeb2b8eaa4f48d7d08a0c2 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 14 Sep 2017 13:41:07 -0700 Subject: Remove stray debugging code --- toolsrc/src/commands_install.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index b530a394c..aca25996e 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -460,11 +460,6 @@ namespace vcpkg::Commands::Install const ElapsedTime build_timer = ElapsedTime::create_started(); counter++; - if (counter > 2) - { - // break; - } - const std::string display_name = action.spec().to_string(); System::println("Starting package %d/%d: %s", counter, package_count, display_name); -- cgit v1.2.3 From 6363910319a082512179269fb6329ecbc367b3bc Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 14 Sep 2017 15:45:32 -0700 Subject: `vcpkg edit`: Improve detection for VSCode - Insiders. Prefer it if available --- toolsrc/src/commands_edit.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index dc28de737..7f400f48b 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -8,11 +8,10 @@ namespace vcpkg::Commands::Edit { static std::vector find_from_registry() { - static const std::array REGKEYS = { + static const std::array REGKEYS = { LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", - LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", + LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1)", LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", - LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", }; std::vector output; @@ -23,8 +22,8 @@ namespace vcpkg::Commands::Edit if (const auto c = code_installpath.get()) { const fs::path install_path = fs::path(*c); - output.push_back(install_path / "Code.exe"); output.push_back(install_path / "Code - Insiders.exe"); + output.push_back(install_path / "Code.exe"); } } return output; @@ -34,6 +33,9 @@ namespace vcpkg::Commands::Edit { static const std::string OPTION_BUILDTREES = "--buildtrees"; + static const fs::path VS_CODE_INSIDERS = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe"; + static const fs::path VS_CODE = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe"; + auto& fs = paths.get_filesystem(); static const std::string EXAMPLE = Commands::Help::create_example_string("edit zlib"); @@ -48,8 +50,10 @@ namespace vcpkg::Commands::Edit std::vector candidate_paths; const std::vector from_path = Files::find_from_PATH(L"EDITOR"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - candidate_paths.push_back(System::get_program_files_platform_bitness() / "Microsoft VS Code" / "Code.exe"); - candidate_paths.push_back(System::get_program_files_32_bit() / "Microsoft VS Code" / "Code.exe"); + candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE_INSIDERS); + candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE_INSIDERS); + candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE); + candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE); const std::vector from_registry = find_from_registry(); candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend()); -- cgit v1.2.3 From b08f2a02e73721cc63acecccc2c25f2c0f488d45 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 19 Sep 2017 12:45:37 -0700 Subject: [vcpkg edit] Fix VSCode path --- toolsrc/src/commands_edit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index 7f400f48b..823c87534 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -34,7 +34,7 @@ namespace vcpkg::Commands::Edit static const std::string OPTION_BUILDTREES = "--buildtrees"; static const fs::path VS_CODE_INSIDERS = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe"; - static const fs::path VS_CODE = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe"; + static const fs::path VS_CODE = fs::path{"Microsoft VS Code"} / "Code.exe"; auto& fs = paths.get_filesystem(); -- cgit v1.2.3 From 39a96fc2f4a7d471ab3fa16c480fc0d9965605b1 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 15 Sep 2017 16:47:07 -0700 Subject: Bump required version of CMake to 3.9.2 --- toolsrc/src/VcpkgPaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 906a5e67f..29edbb260 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -97,10 +97,10 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array EXPECTED_VERSION = {3, 9, 1}; + static constexpr std::array EXPECTED_VERSION = {3, 9, 2}; static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; - const fs::path downloaded_copy = downloads_folder / "cmake-3.9.1-win32-x86" / "bin" / "cmake.exe"; + const fs::path downloaded_copy = downloads_folder / "cmake-3.9.2-win32-x86" / "bin" / "cmake.exe"; const std::vector from_path = Files::find_from_PATH(L"cmake"); std::vector candidate_paths; -- cgit v1.2.3 From 548b7f69197fad294f44b6e3ae5f587116220fae Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 22 Sep 2017 14:20:27 -0700 Subject: Bump required version of CMake to 3.9.3 3.9.3 contains this interesting change: FindBoost: Add support for Boost 1.65.0 and 1.65.1 to CMake 3.9 --- toolsrc/src/VcpkgPaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 29edbb260..02e238b3f 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -97,10 +97,10 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array EXPECTED_VERSION = {3, 9, 2}; + static constexpr std::array EXPECTED_VERSION = {3, 9, 3}; static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; - const fs::path downloaded_copy = downloads_folder / "cmake-3.9.2-win32-x86" / "bin" / "cmake.exe"; + const fs::path downloaded_copy = downloads_folder / "cmake-3.9.3-win32-x86" / "bin" / "cmake.exe"; const std::vector from_path = Files::find_from_PATH(L"cmake"); std::vector candidate_paths; -- cgit v1.2.3 From 2c3def2f865188fd088f5f10ccffeb9e5464f815 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sun, 24 Sep 2017 03:07:25 -0700 Subject: `vcpkg portsdiff` Make output format closer to the CHANGELOG formatting --- toolsrc/src/commands_portsdiff.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp index 32bc3de3c..2334b2270 100644 --- a/toolsrc/src/commands_portsdiff.cpp +++ b/toolsrc/src/commands_portsdiff.cpp @@ -68,7 +68,7 @@ namespace vcpkg::Commands::PortsDiff for (const std::string& name : ports_to_print) { const VersionT& version = names_and_versions.at(name); - System::println("%-20s %-16s", name, version); + System::println(" - %-14s %-16s", name, version); } } @@ -147,14 +147,14 @@ namespace vcpkg::Commands::PortsDiff const std::vector& added_ports = setp.only_left; if (!added_ports.empty()) { - System::println("\nThe following %d ports were added:\n", added_ports.size()); + System::println("\nThe following %d ports were added:", added_ports.size()); do_print_name_and_version(added_ports, current_names_and_versions); } const std::vector& removed_ports = setp.only_right; if (!removed_ports.empty()) { - System::println("\nThe following %d ports were removed:\n", removed_ports.size()); + System::println("\nThe following %d ports were removed:", removed_ports.size()); do_print_name_and_version(removed_ports, previous_names_and_versions); } @@ -164,10 +164,10 @@ namespace vcpkg::Commands::PortsDiff if (!updated_ports.empty()) { - System::println("\nThe following %d ports were updated:\n", updated_ports.size()); + System::println("\nThe following %d ports were updated:", updated_ports.size()); for (const UpdatedPort& p : updated_ports) { - System::println("%-20s %-16s", p.port, p.version_diff.to_string()); + System::println(" - %-14s %-16s", p.port, p.version_diff.to_string()); } } -- cgit v1.2.3 From ba0cc3f1d7edb7e2fee271761b2f37d0c740604f Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Mon, 28 Aug 2017 13:54:19 +0300 Subject: WIP: Export IFW Add export to binary crossplatform repository/installer with GUI based on QtIFW: http://doc.qt.io/qtinstallerframework/ifw-overview.html For correct operation of these changes, you must use the corrected QtIFW: https://codereview.qt-project.org/#/c/203958 --- toolsrc/src/commands_export.cpp | 57 ++++++- toolsrc/src/commands_export_ifw.cpp | 319 ++++++++++++++++++++++++++++++++++++ 2 files changed, 369 insertions(+), 7 deletions(-) create mode 100644 toolsrc/src/commands_export_ifw.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index b416a6f3c..139f19026 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -2,6 +2,7 @@ #include "Paragraphs.h" #include "vcpkg_Commands.h" +#include "vcpkg_Commands_Export_IFW.h" #include "vcpkg_Dependencies.h" #include "vcpkg_Input.h" #include "vcpkg_System.h" @@ -215,10 +216,12 @@ namespace vcpkg::Commands::Export static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_RAW = "--raw"; static const std::string OPTION_NUGET = "--nuget"; + static const std::string OPTION_IFW = "--ifw"; static const std::string OPTION_ZIP = "--zip"; static const std::string OPTION_SEVEN_ZIP = "--7zip"; static const std::string OPTION_NUGET_ID = "--nuget-id"; static const std::string OPTION_NUGET_VERSION = "--nuget-version"; + static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url"; // input sanitization static const std::string EXAMPLE = @@ -236,22 +239,25 @@ namespace vcpkg::Commands::Export OPTION_DRY_RUN, OPTION_RAW, OPTION_NUGET, + OPTION_IFW, OPTION_ZIP, OPTION_SEVEN_ZIP, }, { OPTION_NUGET_ID, OPTION_NUGET_VERSION, + OPTION_IFW_REPOSITORY_URL, }); const bool dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); const bool raw = options.switches.find(OPTION_RAW) != options.switches.cend(); const bool nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); + const bool ifw = options.switches.find(OPTION_IFW) != options.switches.cend(); const bool zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); const bool seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend(); - if (!raw && !nuget && !zip && !seven_zip && !dry_run) + if (!raw && !nuget && !ifw && !zip && !seven_zip && !dry_run) { - System::println(System::Color::error, "Must provide at least one export type: --raw --nuget --zip --7zip"); + System::println(System::Color::error, "Must provide at least one export type: --raw --nuget --ifw --zip --7zip"); System::print(EXAMPLE); Checks::exit_fail(VCPKG_LINE_INFO); } @@ -263,6 +269,10 @@ namespace vcpkg::Commands::Export Checks::check_exit( VCPKG_LINE_INFO, !maybe_nuget_version || nuget, "--nuget-version is only valid with --nuget"); + auto maybe_ifw_repository_url = maybe_lookup(options.settings, OPTION_IFW_REPOSITORY_URL); + + Checks::check_exit(VCPKG_LINE_INFO, !maybe_ifw_repository_url || ifw, "--ifw-repository-url is only valid with --ifw"); + // create the plan const StatusParagraphs status_db = database_load_check(paths); std::vector export_plan = Dependencies::create_export_plan(paths, specs, status_db); @@ -305,7 +315,11 @@ namespace vcpkg::Commands::Export Checks::exit_success(VCPKG_LINE_INFO); } - const std::string export_id = create_export_id(); + std::string export_id = create_export_id(); + if (ifw) + { + export_id = "vcpkg-export"; // TODO: Remove after debugging + } Files::Filesystem& fs = paths.get_filesystem(); const fs::path export_to_path = paths.root; @@ -315,6 +329,8 @@ namespace vcpkg::Commands::Export fs.create_directory(raw_exported_dir_path, ec); // execute the plan + std::map unique_packages; + std::set unique_triplets; for (const ExportPlanAction& action : export_plan) { if (action.plan_type != ExportPlanType::ALREADY_BUILT) @@ -327,10 +343,21 @@ namespace vcpkg::Commands::Export const BinaryParagraph& binary_paragraph = action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + unique_packages[action.spec.name()] = &action; + unique_triplets.insert(action.spec.triplet().canonical_name()); + + fs::path spec_exported_dir_path = raw_exported_dir_path / "installed"; + if (ifw) + { + // Export real package and return data dir for installation + spec_exported_dir_path = IFW::export_real_package(raw_exported_dir_path, action, fs); + } + const InstallDir dirs = InstallDir::from_destination_root( - raw_exported_dir_path / "installed", + spec_exported_dir_path, action.spec.triplet().to_string(), - raw_exported_dir_path / "installed" / "vcpkg" / "info" / (binary_paragraph.fullstem() + ".list")); + spec_exported_dir_path / "vcpkg" / "info" / (binary_paragraph.fullstem() + ".list")); Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); System::println(System::Color::success, "Exporting package %s... done", display_name); @@ -351,13 +378,29 @@ namespace vcpkg::Commands::Export for (const fs::path& file : integration_files_relative_to_root) { const fs::path source = paths.root / file; - const fs::path destination = raw_exported_dir_path / file; + fs::path destination = raw_exported_dir_path / file; + if (ifw) + { + destination = raw_exported_dir_path / "integration" / "data" / file; + } fs.create_directories(destination.parent_path(), ec); Checks::check_exit(VCPKG_LINE_INFO, !ec); fs.copy_file(source, destination, fs::copy_options::overwrite_existing, ec); Checks::check_exit(VCPKG_LINE_INFO, !ec); } + if (ifw) + { + // Unigue packages + IFW::export_unique_packages(raw_exported_dir_path, unique_packages, fs); + // Unigue triplets + IFW::export_unique_triplets(raw_exported_dir_path, unique_triplets, fs); + // Integration + IFW::export_integration(raw_exported_dir_path, fs); + // Configuration + IFW::export_config(raw_exported_dir_path, maybe_ifw_repository_url.value_or(""), fs); + } + const auto print_next_step_info = [](const fs::path& prefix) { const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; const CMakeVariable cmake_variable = @@ -417,7 +460,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console print_next_step_info("[...]"); } - if (!raw) + if (!raw && !ifw) { fs.remove_all(raw_exported_dir_path, ec); } diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp new file mode 100644 index 000000000..ceedac9a3 --- /dev/null +++ b/toolsrc/src/commands_export_ifw.cpp @@ -0,0 +1,319 @@ +#include "pch.h" + +#include "vcpkg_Commands_Export_IFW.h" + +namespace vcpkg::Commands::Export::IFW +{ + using Dependencies::ExportPlanAction; + + fs::path export_real_package(const fs::path &raw_exported_dir_path, const ExportPlanAction& action, Files::Filesystem& fs) + { + std::error_code ec; + + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + // Prepare meta dir + const fs::path package_xml_file_path = raw_exported_dir_path / Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "meta" / "package.xml"; + const fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); + std::vector lines; + std::string line; std::string skip = " "; + line = ""; + lines.push_back(line); line.clear(); + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += action.spec.to_string(); + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += binary_paragraph.version; // TODO: Check IFW version format + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "2017-08-31"; // TODO: Get real package release date + line += ""; + //if (!binary_paragraph.depends.empty()) + //{ + // lines.push_back(line); line = skip; + // line += ""; + //// line += Strings::format("triplets.%s:", action.spec.triplet().canonical_name()); + // line += Strings::format("packages.%s.%s:", binary_paragraph.depends[0], action.spec.triplet().canonical_name()); + // for (size_t i = 1; i < binary_paragraph.depends.size(); ++i) + // { + // line += Strings::format(",packages.%s.%s:", binary_paragraph.depends[i], action.spec.triplet().canonical_name()); + // } + // line += ""; + //} + lines.push_back(line); line = skip; + line += ""; + line += Strings::format("packages.%s:,triplets.%s:", action.spec.name(), action.spec.triplet().canonical_name()); + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "true"; // NOTE: hide real package + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "true"; + line += ""; + lines.push_back(line); line.clear(); + line = ""; + lines.push_back(line); line.clear(); + fs.write_lines(package_xml_file_path, lines); + + // Return dir path for export package data + return raw_exported_dir_path / Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "data" / "installed"; + } + + void export_unique_packages(const fs::path &raw_exported_dir_path, std::map unique_packages, Files::Filesystem& fs) + { + std::error_code ec; + + // packages + + fs::path package_xml_file_path = raw_exported_dir_path / "packages" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); + std::vector lines; + std::string line; std::string skip = " "; + line = ""; + lines.push_back(line); line.clear(); + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "Packages"; + line += ""; + lines.push_back(line); line = skip; + line = ""; + line += "1.0.0"; // TODO: Get real packages package version + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "2017-08-31"; // TODO: Get real package release date + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "true"; + line += ""; + lines.push_back(line); line.clear(); + line = ""; + lines.push_back(line); line.clear(); + fs.write_lines(package_xml_file_path, lines); + + for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) + { + const ExportPlanAction& action = *(package->second); + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + package_xml_file_path = raw_exported_dir_path / Strings::format("packages.%s", package->first) / "meta" / "package.xml"; + package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); + lines.clear(); + line.clear(); + skip = " "; + line = ""; + lines.push_back(line); line.clear(); + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += action.spec.name(); + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += binary_paragraph.description; + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += binary_paragraph.version; // TODO: Check IFW version format + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "2017-08-31"; // TODO: Get real package release date + line += ""; + if (!binary_paragraph.depends.empty()) + { + lines.push_back(line); line = skip; + line += ""; + line += Strings::format("packages.%s:", binary_paragraph.depends[0]); + for (size_t i = 1; i < binary_paragraph.depends.size(); ++i) + { + line += Strings::format(",packages.%s:", binary_paragraph.depends[i]); + } + line += ""; + } + lines.push_back(line); line = skip; + line += ""; + line += "true"; + line += ""; + lines.push_back(line); line.clear(); + line = ""; + lines.push_back(line); line.clear(); + fs.write_lines(package_xml_file_path, lines); + } + } + + void export_unique_triplets(const fs::path &raw_exported_dir_path, std::set unique_triplets, Files::Filesystem& fs) + { + std::error_code ec; + + // triplets + + fs::path package_xml_file_path = raw_exported_dir_path / "triplets" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); + std::vector lines; + std::string line; std::string skip = " "; + line = ""; + lines.push_back(line); line.clear(); + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "Triplets"; + line += ""; + lines.push_back(line); line = skip; + line = ""; + line += "1.0.0"; // TODO: Get real triplits package version + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "2017-08-31"; // TODO: Get real package release date + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "true"; + line += ""; + lines.push_back(line); line.clear(); + line = ""; + lines.push_back(line); line.clear(); + fs.write_lines(package_xml_file_path, lines); + + for (const std::string &triplet : unique_triplets) + { + package_xml_file_path = raw_exported_dir_path / Strings::format("triplets.%s", triplet) / "meta" / "package.xml"; + package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); + lines.clear(); + line.clear(); + skip = " "; + line = ""; + lines.push_back(line); line.clear(); + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += triplet; + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "1.0.0"; // TODO: Get real package version + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "2017-08-31"; // TODO: Get real package release date + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "true"; + line += ""; + lines.push_back(line); line.clear(); + line = ""; + lines.push_back(line); line.clear(); + fs.write_lines(package_xml_file_path, lines); + } + } + + void export_integration(const fs::path &raw_exported_dir_path, Files::Filesystem& fs) + { + std::error_code ec; + + // integration + fs::path package_xml_file_path = raw_exported_dir_path / "integration" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); + std::vector lines; + std::string line; std::string skip = " "; + line = ""; + lines.push_back(line); line.clear(); + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "Integration"; + line += ""; + lines.push_back(line); line = skip; + line = ""; + line += "1.0.0"; // TODO: Get real integration package version + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "2017-08-31"; // TODO: Get real package release date + line += ""; + lines.push_back(line); line.clear(); + line = ""; + lines.push_back(line); line.clear(); + fs.write_lines(package_xml_file_path, lines); + } + + void export_config(const fs::path &raw_exported_dir_path, const std::string ifw_repository_url, Files::Filesystem& fs) + { + std::error_code ec; + + // config.xml + fs::path config_xml_file_path = raw_exported_dir_path / "config.xml"; + fs::path config_xml_dir_path = config_xml_file_path.parent_path(); + fs.create_directories(config_xml_dir_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create directory for configuration file %s", config_xml_file_path.generic_string()); + std::vector lines; + std::string line; std::string skip = " "; + line = ""; + lines.push_back(line); line.clear(); + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "vcpkg"; + line += ""; + lines.push_back(line); line = skip; + line += ""; + line += "1.0.0"; // TODO: Get real vcpkg installer version + line += ""; + //lines.push_back(line); line = skip; + //line += "true"; + lines.push_back(line); line = skip; + line += ""; + line += "@RootDir@/src/vcpkg"; + line += ""; + if (!ifw_repository_url.empty()) + { + lines.push_back(line); line = skip; + line += ""; + lines.push_back(line); line = skip + skip; + line += ""; + lines.push_back(line); line = skip + skip + skip; + line += ""; + line += ifw_repository_url; + line += ""; + lines.push_back(line); line = skip + skip; + line += ""; + lines.push_back(line); line = skip; + line += ""; + } + lines.push_back(line); line.clear(); + line = ""; + lines.push_back(line); line.clear(); + fs.write_lines(config_xml_file_path, lines); + } +} -- cgit v1.2.3 From 5199507a5892ab997b1beee2f1b7d2a6c7e75115 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 21 Sep 2017 02:27:00 -0700 Subject: [vcpkg-export-ifw] Use template approach for xml instead of line-by-line --- toolsrc/src/commands_export.cpp | 18 +- toolsrc/src/commands_export_ifw.cpp | 397 ++++++++++++++---------------------- 2 files changed, 161 insertions(+), 254 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index 139f19026..c143fb9c7 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -257,7 +257,8 @@ namespace vcpkg::Commands::Export if (!raw && !nuget && !ifw && !zip && !seven_zip && !dry_run) { - System::println(System::Color::error, "Must provide at least one export type: --raw --nuget --ifw --zip --7zip"); + System::println(System::Color::error, + "Must provide at least one export type: --raw --nuget --ifw --zip --7zip"); System::print(EXAMPLE); Checks::exit_fail(VCPKG_LINE_INFO); } @@ -271,7 +272,8 @@ namespace vcpkg::Commands::Export auto maybe_ifw_repository_url = maybe_lookup(options.settings, OPTION_IFW_REPOSITORY_URL); - Checks::check_exit(VCPKG_LINE_INFO, !maybe_ifw_repository_url || ifw, "--ifw-repository-url is only valid with --ifw"); + Checks::check_exit( + VCPKG_LINE_INFO, !maybe_ifw_repository_url || ifw, "--ifw-repository-url is only valid with --ifw"); // create the plan const StatusParagraphs status_db = database_load_check(paths); @@ -354,10 +356,10 @@ namespace vcpkg::Commands::Export spec_exported_dir_path = IFW::export_real_package(raw_exported_dir_path, action, fs); } - const InstallDir dirs = InstallDir::from_destination_root( - spec_exported_dir_path, - action.spec.triplet().to_string(), - spec_exported_dir_path / "vcpkg" / "info" / (binary_paragraph.fullstem() + ".list")); + const InstallDir dirs = InstallDir::from_destination_root(spec_exported_dir_path, + action.spec.triplet().to_string(), + spec_exported_dir_path / "vcpkg" / "info" / + (binary_paragraph.fullstem() + ".list")); Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); System::println(System::Color::success, "Exporting package %s... done", display_name); @@ -391,9 +393,9 @@ namespace vcpkg::Commands::Export if (ifw) { - // Unigue packages + // Unique packages IFW::export_unique_packages(raw_exported_dir_path, unique_packages, fs); - // Unigue triplets + // Unique triplets IFW::export_unique_triplets(raw_exported_dir_path, unique_triplets, fs); // Integration IFW::export_integration(raw_exported_dir_path, fs); diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp index ceedac9a3..4b5bdb902 100644 --- a/toolsrc/src/commands_export_ifw.cpp +++ b/toolsrc/src/commands_export_ifw.cpp @@ -6,7 +6,9 @@ namespace vcpkg::Commands::Export::IFW { using Dependencies::ExportPlanAction; - fs::path export_real_package(const fs::path &raw_exported_dir_path, const ExportPlanAction& action, Files::Filesystem& fs) + fs::path export_real_package(const fs::path& raw_exported_dir_path, + const ExportPlanAction& action, + Files::Filesystem& fs) { std::error_code ec; @@ -14,97 +16,64 @@ namespace vcpkg::Commands::Export::IFW action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; // Prepare meta dir - const fs::path package_xml_file_path = raw_exported_dir_path / Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "meta" / "package.xml"; + const fs::path package_xml_file_path = + raw_exported_dir_path / + Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "meta" / + "package.xml"; const fs::path package_xml_dir_path = package_xml_file_path.parent_path(); fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - std::vector lines; - std::string line; std::string skip = " "; - line = ""; - lines.push_back(line); line.clear(); - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += action.spec.to_string(); - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += binary_paragraph.version; // TODO: Check IFW version format - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "2017-08-31"; // TODO: Get real package release date - line += ""; - //if (!binary_paragraph.depends.empty()) - //{ - // lines.push_back(line); line = skip; - // line += ""; - //// line += Strings::format("triplets.%s:", action.spec.triplet().canonical_name()); - // line += Strings::format("packages.%s.%s:", binary_paragraph.depends[0], action.spec.triplet().canonical_name()); - // for (size_t i = 1; i < binary_paragraph.depends.size(); ++i) - // { - // line += Strings::format(",packages.%s.%s:", binary_paragraph.depends[i], action.spec.triplet().canonical_name()); - // } - // line += ""; - //} - lines.push_back(line); line = skip; - line += ""; - line += Strings::format("packages.%s:,triplets.%s:", action.spec.name(), action.spec.triplet().canonical_name()); - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "true"; // NOTE: hide real package - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "true"; - line += ""; - lines.push_back(line); line.clear(); - line = ""; - lines.push_back(line); line.clear(); - fs.write_lines(package_xml_file_path, lines); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + fs.write_contents(package_xml_file_path, + Strings::format(R"###( + + + %s + %s + 2017-08-31 + packages.%s:,triplets.%s: + true + true + +)###", + action.spec.to_string(), + binary_paragraph.version, + action.spec.name(), + action.spec.triplet().canonical_name())); // Return dir path for export package data - return raw_exported_dir_path / Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "data" / "installed"; + return raw_exported_dir_path / + Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "data" / + "installed"; } - void export_unique_packages(const fs::path &raw_exported_dir_path, std::map unique_packages, Files::Filesystem& fs) - { - std::error_code ec; - + void export_unique_packages(const fs::path& raw_exported_dir_path, + std::map unique_packages, + Files::Filesystem& fs) + { + std::error_code ec; + // packages fs::path package_xml_file_path = raw_exported_dir_path / "packages" / "meta" / "package.xml"; fs::path package_xml_dir_path = package_xml_file_path.parent_path(); fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - std::vector lines; - std::string line; std::string skip = " "; - line = ""; - lines.push_back(line); line.clear(); - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "Packages"; - line += ""; - lines.push_back(line); line = skip; - line = ""; - line += "1.0.0"; // TODO: Get real packages package version - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "2017-08-31"; // TODO: Get real package release date - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "true"; - line += ""; - lines.push_back(line); line.clear(); - line = ""; - lines.push_back(line); line.clear(); - fs.write_lines(package_xml_file_path, lines); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, R"###( + + + Packages + 1.0.0 + 2017-08-31 + true + +)###"); for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) { @@ -112,56 +81,41 @@ namespace vcpkg::Commands::Export::IFW const BinaryParagraph& binary_paragraph = action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; - package_xml_file_path = raw_exported_dir_path / Strings::format("packages.%s", package->first) / "meta" / "package.xml"; + package_xml_file_path = + raw_exported_dir_path / Strings::format("packages.%s", package->first) / "meta" / "package.xml"; package_xml_dir_path = package_xml_file_path.parent_path(); fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - lines.clear(); - line.clear(); - skip = " "; - line = ""; - lines.push_back(line); line.clear(); - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += action.spec.name(); - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += binary_paragraph.description; - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += binary_paragraph.version; // TODO: Check IFW version format - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "2017-08-31"; // TODO: Get real package release date - line += ""; - if (!binary_paragraph.depends.empty()) - { - lines.push_back(line); line = skip; - line += ""; - line += Strings::format("packages.%s:", binary_paragraph.depends[0]); - for (size_t i = 1; i < binary_paragraph.depends.size(); ++i) - { - line += Strings::format(",packages.%s:", binary_paragraph.depends[i]); - } - line += ""; - } - lines.push_back(line); line = skip; - line += ""; - line += "true"; - line += ""; - lines.push_back(line); line.clear(); - line = ""; - lines.push_back(line); line.clear(); - fs.write_lines(package_xml_file_path, lines); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + auto deps = Strings::join( + ",", binary_paragraph.depends, [](const std::string& dep) { return "packages." + dep + ":"; }); + + if (!deps.empty()) deps = "\n " + deps; + + fs.write_contents(package_xml_file_path, + Strings::format(R"###( + + + %s + %s + %s + 2017-08-31%s + true + +)###", + action.spec.name(), + binary_paragraph.description, + binary_paragraph.version, + deps)); } } - void export_unique_triplets(const fs::path &raw_exported_dir_path, std::set unique_triplets, Files::Filesystem& fs) + void export_unique_triplets(const fs::path& raw_exported_dir_path, + std::set unique_triplets, + Files::Filesystem& fs) { std::error_code ec; @@ -170,71 +124,43 @@ namespace vcpkg::Commands::Export::IFW fs::path package_xml_file_path = raw_exported_dir_path / "triplets" / "meta" / "package.xml"; fs::path package_xml_dir_path = package_xml_file_path.parent_path(); fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - std::vector lines; - std::string line; std::string skip = " "; - line = ""; - lines.push_back(line); line.clear(); - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "Triplets"; - line += ""; - lines.push_back(line); line = skip; - line = ""; - line += "1.0.0"; // TODO: Get real triplits package version - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "2017-08-31"; // TODO: Get real package release date - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "true"; - line += ""; - lines.push_back(line); line.clear(); - line = ""; - lines.push_back(line); line.clear(); - fs.write_lines(package_xml_file_path, lines); - - for (const std::string &triplet : unique_triplets) + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, R"###( + + + Triplets + 1.0.0 + 2017-08-31 + true + +)###"); + + for (const std::string& triplet : unique_triplets) { - package_xml_file_path = raw_exported_dir_path / Strings::format("triplets.%s", triplet) / "meta" / "package.xml"; + package_xml_file_path = + raw_exported_dir_path / Strings::format("triplets.%s", triplet) / "meta" / "package.xml"; package_xml_dir_path = package_xml_file_path.parent_path(); fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - lines.clear(); - line.clear(); - skip = " "; - line = ""; - lines.push_back(line); line.clear(); - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += triplet; - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "1.0.0"; // TODO: Get real package version - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "2017-08-31"; // TODO: Get real package release date - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "true"; - line += ""; - lines.push_back(line); line.clear(); - line = ""; - lines.push_back(line); line.clear(); - fs.write_lines(package_xml_file_path, lines); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, Strings::format(R"###( + + + %s + 1.0.0 + 2017-08-31 + true + +)###", triplet)); } } - void export_integration(const fs::path &raw_exported_dir_path, Files::Filesystem& fs) + void export_integration(const fs::path& raw_exported_dir_path, Files::Filesystem& fs) { std::error_code ec; @@ -242,32 +168,25 @@ namespace vcpkg::Commands::Export::IFW fs::path package_xml_file_path = raw_exported_dir_path / "integration" / "meta" / "package.xml"; fs::path package_xml_dir_path = package_xml_file_path.parent_path(); fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - std::vector lines; - std::string line; std::string skip = " "; - line = ""; - lines.push_back(line); line.clear(); - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "Integration"; - line += ""; - lines.push_back(line); line = skip; - line = ""; - line += "1.0.0"; // TODO: Get real integration package version - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "2017-08-31"; // TODO: Get real package release date - line += ""; - lines.push_back(line); line.clear(); - line = ""; - lines.push_back(line); line.clear(); - fs.write_lines(package_xml_file_path, lines); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + fs.write_contents(package_xml_file_path, R"###( + + + Integration + 1.0.0 + 2017-08-31 + true + +)###"); } - void export_config(const fs::path &raw_exported_dir_path, const std::string ifw_repository_url, Files::Filesystem& fs) + void export_config(const fs::path& raw_exported_dir_path, + const std::string ifw_repository_url, + Files::Filesystem& fs) { std::error_code ec; @@ -275,45 +194,31 @@ namespace vcpkg::Commands::Export::IFW fs::path config_xml_file_path = raw_exported_dir_path / "config.xml"; fs::path config_xml_dir_path = config_xml_file_path.parent_path(); fs.create_directories(config_xml_dir_path, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not create directory for configuration file %s", config_xml_file_path.generic_string()); - std::vector lines; - std::string line; std::string skip = " "; - line = ""; - lines.push_back(line); line.clear(); - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "vcpkg"; - line += ""; - lines.push_back(line); line = skip; - line += ""; - line += "1.0.0"; // TODO: Get real vcpkg installer version - line += ""; - //lines.push_back(line); line = skip; - //line += "true"; - lines.push_back(line); line = skip; - line += ""; - line += "@RootDir@/src/vcpkg"; - line += ""; + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for configuration file %s", + config_xml_file_path.generic_string()); + std::string formatted_repo_url; if (!ifw_repository_url.empty()) { - lines.push_back(line); line = skip; - line += ""; - lines.push_back(line); line = skip + skip; - line += ""; - lines.push_back(line); line = skip + skip + skip; - line += ""; - line += ifw_repository_url; - line += ""; - lines.push_back(line); line = skip + skip; - line += ""; - lines.push_back(line); line = skip; - line += ""; + formatted_repo_url = Strings::format(R"###( + + + %s + + +)###", + formatted_repo_url); } - lines.push_back(line); line.clear(); - line = ""; - lines.push_back(line); line.clear(); - fs.write_lines(config_xml_file_path, lines); + + fs.write_contents(config_xml_file_path, Strings::format(R"###( + + + vcpkg + 1.0.0 + 2017-08-31 + @RootDir@/src/vcpkg%s + +)###", formatted_repo_url)); } } -- cgit v1.2.3 From 68b9c2d8b9119acb48643447a7561a5c2b733d25 Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Fri, 22 Sep 2017 02:16:14 +0300 Subject: [vcpkg-export-ifw] Separate IFW loop Separate IFW loop compatible with main export loop Fixed mistakes in templates Set current date to ReleaseDate tag --- toolsrc/src/commands_export.cpp | 253 ++++++++++++++++++------------------ toolsrc/src/commands_export_ifw.cpp | 183 ++++++++++++++++++++------ 2 files changed, 268 insertions(+), 168 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index c143fb9c7..6632dfe67 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -211,6 +211,32 @@ namespace vcpkg::Commands::Export return nullopt; } + void export_integration_files(const fs::path &raw_exported_dir_path, const VcpkgPaths& paths) + { + const std::vector integration_files_relative_to_root = { + { ".vcpkg-root" }, + { fs::path{ "scripts" } / "buildsystems" / "msbuild" / "applocal.ps1" }, + { fs::path{ "scripts" } / "buildsystems" / "msbuild" / "vcpkg.targets" }, + { fs::path{ "scripts" } / "buildsystems" / "vcpkg.cmake" }, + { fs::path{ "scripts" } / "cmake" / "vcpkg_get_windows_sdk.cmake" }, + { fs::path{ "scripts" } / "getWindowsSDK.ps1" }, + { fs::path{ "scripts" } / "getProgramFilesPlatformBitness.ps1" }, + { fs::path{ "scripts" } / "getProgramFiles32bit.ps1" }, + }; + + for (const fs::path& file : integration_files_relative_to_root) + { + const fs::path source = paths.root / file; + fs::path destination = raw_exported_dir_path / file; + Files::Filesystem& fs = paths.get_filesystem(); + std::error_code ec; + fs.create_directories(destination.parent_path(), ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec); + fs.copy_file(source, destination, fs::copy_options::overwrite_existing, ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec); + } + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { static const std::string OPTION_DRY_RUN = "--dry-run"; @@ -222,6 +248,8 @@ namespace vcpkg::Commands::Export static const std::string OPTION_NUGET_ID = "--nuget-id"; static const std::string OPTION_NUGET_VERSION = "--nuget-version"; static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url"; + static const std::string OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path"; + static const std::string OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path"; // input sanitization static const std::string EXAMPLE = @@ -247,6 +275,8 @@ namespace vcpkg::Commands::Export OPTION_NUGET_ID, OPTION_NUGET_VERSION, OPTION_IFW_REPOSITORY_URL, + OPTION_IFW_PACKAGES_DIR_PATH, + OPTION_IFW_CONFIG_FILE_PATH }); const bool dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); const bool raw = options.switches.find(OPTION_RAW) != options.switches.cend(); @@ -270,10 +300,19 @@ namespace vcpkg::Commands::Export Checks::check_exit( VCPKG_LINE_INFO, !maybe_nuget_version || nuget, "--nuget-version is only valid with --nuget"); - auto maybe_ifw_repository_url = maybe_lookup(options.settings, OPTION_IFW_REPOSITORY_URL); + IFW::Options ifw_options; + + ifw_options.maybe_repository_url = maybe_lookup(options.settings, OPTION_IFW_REPOSITORY_URL); + Checks::check_exit( + VCPKG_LINE_INFO, !ifw_options.maybe_repository_url || ifw, "--ifw-repository-url is only valid with --ifw"); + + ifw_options.maybe_packages_dir_path = maybe_lookup(options.settings, OPTION_IFW_PACKAGES_DIR_PATH); + Checks::check_exit( + VCPKG_LINE_INFO, !ifw_options.maybe_packages_dir_path || ifw, "--ifw-packages-directory-path is only valid with --ifw"); + ifw_options.maybe_config_file_path = maybe_lookup(options.settings, OPTION_IFW_CONFIG_FILE_PATH); Checks::check_exit( - VCPKG_LINE_INFO, !maybe_ifw_repository_url || ifw, "--ifw-repository-url is only valid with --ifw"); + VCPKG_LINE_INFO, !ifw_options.maybe_config_file_path || ifw, "--ifw-configuration-file-path is only valid with --ifw"); // create the plan const StatusParagraphs status_db = database_load_check(paths); @@ -318,153 +357,117 @@ namespace vcpkg::Commands::Export } std::string export_id = create_export_id(); - if (ifw) - { - export_id = "vcpkg-export"; // TODO: Remove after debugging - } - Files::Filesystem& fs = paths.get_filesystem(); - const fs::path export_to_path = paths.root; - const fs::path raw_exported_dir_path = export_to_path / export_id; - std::error_code ec; - fs.remove_all(raw_exported_dir_path, ec); - fs.create_directory(raw_exported_dir_path, ec); + const auto print_next_step_info = [](const fs::path& prefix) { + const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; + const CMakeVariable cmake_variable = + CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); + System::println("\n" + "To use the exported libraries in CMake projects use:" + "\n" + " %s" + "\n", + Strings::to_utf8(cmake_variable.s)); + }; - // execute the plan - std::map unique_packages; - std::set unique_triplets; - for (const ExportPlanAction& action : export_plan) + // Main loop + if (raw || nuget || zip || seven_zip) { - if (action.plan_type != ExportPlanType::ALREADY_BUILT) + Files::Filesystem& fs = paths.get_filesystem(); + const fs::path export_to_path = paths.root; + const fs::path raw_exported_dir_path = export_to_path / export_id; + std::error_code ec; + fs.remove_all(raw_exported_dir_path, ec); + fs.create_directory(raw_exported_dir_path, ec); + + // execute the plan + for (const ExportPlanAction& action : export_plan) { - Checks::unreachable(VCPKG_LINE_INFO); - } + if (action.plan_type != ExportPlanType::ALREADY_BUILT) + { + Checks::unreachable(VCPKG_LINE_INFO); + } - const std::string display_name = action.spec.to_string(); - System::println("Exporting package %s... ", display_name); + const std::string display_name = action.spec.to_string(); + System::println("Exporting package %s... ", display_name); - const BinaryParagraph& binary_paragraph = - action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; - unique_packages[action.spec.name()] = &action; - unique_triplets.insert(action.spec.triplet().canonical_name()); + const InstallDir dirs = InstallDir::from_destination_root( + raw_exported_dir_path / "installed", + action.spec.triplet().to_string(), + raw_exported_dir_path / "installed" / "vcpkg" / "info" / (binary_paragraph.fullstem() + ".list")); - fs::path spec_exported_dir_path = raw_exported_dir_path / "installed"; - if (ifw) - { - // Export real package and return data dir for installation - spec_exported_dir_path = IFW::export_real_package(raw_exported_dir_path, action, fs); + Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); + System::println(System::Color::success, "Exporting package %s... done", display_name); } - const InstallDir dirs = InstallDir::from_destination_root(spec_exported_dir_path, - action.spec.triplet().to_string(), - spec_exported_dir_path / "vcpkg" / "info" / - (binary_paragraph.fullstem() + ".list")); - - Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); - System::println(System::Color::success, "Exporting package %s... done", display_name); - } - - // Copy files needed for integration - const std::vector integration_files_relative_to_root = { - {".vcpkg-root"}, - {fs::path{"scripts"} / "buildsystems" / "msbuild" / "applocal.ps1"}, - {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"}, - {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"}, - {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"}, - {fs::path{"scripts"} / "getWindowsSDK.ps1"}, - {fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"}, - {fs::path{"scripts"} / "getProgramFiles32bit.ps1"}, - }; + // Copy files needed for integration + export_integration_files(raw_exported_dir_path, paths); - for (const fs::path& file : integration_files_relative_to_root) - { - const fs::path source = paths.root / file; - fs::path destination = raw_exported_dir_path / file; - if (ifw) + if (raw) { - destination = raw_exported_dir_path / "integration" / "data" / file; + System::println( + System::Color::success, R"(Files exported at: "%s")", raw_exported_dir_path.generic_string()); + print_next_step_info(export_to_path); } - fs.create_directories(destination.parent_path(), ec); - Checks::check_exit(VCPKG_LINE_INFO, !ec); - fs.copy_file(source, destination, fs::copy_options::overwrite_existing, ec); - Checks::check_exit(VCPKG_LINE_INFO, !ec); - } - if (ifw) - { - // Unique packages - IFW::export_unique_packages(raw_exported_dir_path, unique_packages, fs); - // Unique triplets - IFW::export_unique_triplets(raw_exported_dir_path, unique_triplets, fs); - // Integration - IFW::export_integration(raw_exported_dir_path, fs); - // Configuration - IFW::export_config(raw_exported_dir_path, maybe_ifw_repository_url.value_or(""), fs); - } - - const auto print_next_step_info = [](const fs::path& prefix) { - const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; - const CMakeVariable cmake_variable = - CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); - System::println("\n" - "To use the exported libraries in CMake projects use:" - "\n" - " %s" - "\n", - Strings::to_utf8(cmake_variable.s)); - }; - - if (raw) - { - System::println( - System::Color::success, R"(Files exported at: "%s")", raw_exported_dir_path.generic_string()); - print_next_step_info(export_to_path); - } - - if (nuget) - { - System::println("Creating nuget package... "); + if (nuget) + { + System::println("Creating nuget package... "); - const std::string nuget_id = maybe_nuget_id.value_or(raw_exported_dir_path.filename().string()); - const std::string nuget_version = maybe_nuget_version.value_or("1.0.0"); - const fs::path output_path = - do_nuget_export(paths, nuget_id, nuget_version, raw_exported_dir_path, export_to_path); - System::println(System::Color::success, "Creating nuget package... done"); - System::println(System::Color::success, "NuGet package exported at: %s", output_path.generic_string()); + const std::string nuget_id = maybe_nuget_id.value_or(raw_exported_dir_path.filename().string()); + const std::string nuget_version = maybe_nuget_version.value_or("1.0.0"); + const fs::path output_path = + do_nuget_export(paths, nuget_id, nuget_version, raw_exported_dir_path, export_to_path); + System::println(System::Color::success, "Creating nuget package... done"); + System::println(System::Color::success, "NuGet package exported at: %s", output_path.generic_string()); - System::println(R"( + System::println(R"( With a project open, go to Tools->NuGet Package Manager->Package Manager Console and paste: Install-Package %s -Source "%s" )" - "\n", - nuget_id, - output_path.parent_path().u8string()); - } + "\n", + nuget_id, + output_path.parent_path().u8string()); + } - if (zip) - { - System::println("Creating zip archive... "); - const fs::path output_path = - do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::ZIP); - System::println(System::Color::success, "Creating zip archive... done"); - System::println(System::Color::success, "Zip archive exported at: %s", output_path.generic_string()); - print_next_step_info("[...]"); - } + if (zip) + { + System::println("Creating zip archive... "); + const fs::path output_path = + do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::ZIP); + System::println(System::Color::success, "Creating zip archive... done"); + System::println(System::Color::success, "Zip archive exported at: %s", output_path.generic_string()); + print_next_step_info("[...]"); + } - if (seven_zip) - { - System::println("Creating 7zip archive... "); - const fs::path output_path = - do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::SEVEN_ZIP); - System::println(System::Color::success, "Creating 7zip archive... done"); - System::println(System::Color::success, "7zip archive exported at: %s", output_path.generic_string()); - print_next_step_info("[...]"); + if (seven_zip) + { + System::println("Creating 7zip archive... "); + const fs::path output_path = + do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::SEVEN_ZIP); + System::println(System::Color::success, "Creating 7zip archive... done"); + System::println(System::Color::success, "7zip archive exported at: %s", output_path.generic_string()); + print_next_step_info("[...]"); + } + + if (!raw) + { + fs.remove_all(raw_exported_dir_path, ec); + } } - if (!raw && !ifw) + // IFW loop + if (ifw) { - fs.remove_all(raw_exported_dir_path, ec); + IFW::do_export(export_plan, export_id, ifw_options, paths); + + // TODO: Download corrected QtIFW tools and automate installer creation + System::println("Use corrected QtIFW tools (for more info see: https://codereview.qt-project.org/#/c/203958) to create installer..."); + + print_next_step_info("[...]"); } Checks::exit_success(VCPKG_LINE_INFO); diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp index 4b5bdb902..e2499b75d 100644 --- a/toolsrc/src/commands_export_ifw.cpp +++ b/toolsrc/src/commands_export_ifw.cpp @@ -1,10 +1,30 @@ #include "pch.h" +#include "vcpkg_Commands.h" +#include "vcpkg_Commands_Export.h" #include "vcpkg_Commands_Export_IFW.h" namespace vcpkg::Commands::Export::IFW { using Dependencies::ExportPlanAction; + using Dependencies::ExportPlanType; + using Install::InstallDir; + + static std::string create_release_date() + { + const tm date_time = System::get_current_date_time(); + + // Format is: YYYY-mm-dd + // 10 characters + 1 null terminating character will be written for a total of 11 chars + char mbstr[11]; + const size_t bytes_written = std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%d", &date_time); + Checks::check_exit(VCPKG_LINE_INFO, + bytes_written == 10, + "Expected 10 bytes to be written, but %u were written", + bytes_written); + const std::string date_time_as_string(mbstr); + return date_time_as_string; + } fs::path export_real_package(const fs::path& raw_exported_dir_path, const ExportPlanAction& action, @@ -28,19 +48,19 @@ namespace vcpkg::Commands::Export::IFW package_xml_file_path.generic_string()); fs.write_contents(package_xml_file_path, - Strings::format(R"###( - + Strings::format( +R"###( %s %s - 2017-08-31 - packages.%s:,triplets.%s: + %s + packages.%s:,triplets.%s: true - true )###", action.spec.to_string(), binary_paragraph.version, + create_release_date(), action.spec.name(), action.spec.triplet().canonical_name())); @@ -65,15 +85,15 @@ namespace vcpkg::Commands::Export::IFW !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, R"###( - + fs.write_contents(package_xml_file_path, Strings::format( +R"###( Packages 1.0.0 - 2017-08-31 - true + %s -)###"); +)###", + create_release_date())); for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) { @@ -93,22 +113,22 @@ namespace vcpkg::Commands::Export::IFW auto deps = Strings::join( ",", binary_paragraph.depends, [](const std::string& dep) { return "packages." + dep + ":"; }); - if (!deps.empty()) deps = "\n " + deps; + if (!deps.empty()) deps = "\n " + deps + ""; fs.write_contents(package_xml_file_path, - Strings::format(R"###( - + Strings::format( +R"###( %s %s %s - 2017-08-31%s - true + %s%s )###", action.spec.name(), binary_paragraph.description, binary_paragraph.version, + create_release_date(), deps)); } } @@ -128,15 +148,15 @@ namespace vcpkg::Commands::Export::IFW !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, R"###( - + fs.write_contents(package_xml_file_path, Strings::format( +R"###( Triplets 1.0.0 - 2017-08-31 - true + %s -)###"); +)###", + create_release_date())); for (const std::string& triplet : unique_triplets) { @@ -148,15 +168,16 @@ namespace vcpkg::Commands::Export::IFW !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, Strings::format(R"###( - + fs.write_contents(package_xml_file_path, Strings::format( +R"###( %s 1.0.0 - 2017-08-31 - true + %s -)###", triplet)); +)###", + triplet, + create_release_date())); } } @@ -173,52 +194,128 @@ namespace vcpkg::Commands::Export::IFW "Could not create directory for package file %s", package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, R"###( - + fs.write_contents(package_xml_file_path, Strings::format( +R"###( Integration 1.0.0 - 2017-08-31 - true + %s -)###"); +)###", + create_release_date())); } - void export_config(const fs::path& raw_exported_dir_path, - const std::string ifw_repository_url, - Files::Filesystem& fs) + void export_config(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) { std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + const fs::path config_xml_file_path = ifw_options.maybe_config_file_path.has_value() ? + fs::path(ifw_options.maybe_config_file_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-configuration") / "config.xml"; - // config.xml - fs::path config_xml_file_path = raw_exported_dir_path / "config.xml"; fs::path config_xml_dir_path = config_xml_file_path.parent_path(); fs.create_directories(config_xml_dir_path, ec); Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not create directory for configuration file %s", config_xml_file_path.generic_string()); + std::string formatted_repo_url; - if (!ifw_repository_url.empty()) + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) { formatted_repo_url = Strings::format(R"###( %s - -)###", - formatted_repo_url); + )###", + ifw_repo_url); } - fs.write_contents(config_xml_file_path, Strings::format(R"###( - + fs.write_contents(config_xml_file_path, Strings::format( +R"###( vcpkg 1.0.0 - 2017-08-31 @RootDir@/src/vcpkg%s -)###", formatted_repo_url)); +)###", + formatted_repo_url)); + + System::println("Created ifw configuration file: %s", config_xml_file_path.generic_string()); + } + + void do_export(const std::vector &export_plan, const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + { + System::println("Creating ifw packages... "); + + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + const fs::path ifw_packages_dir_path = ifw_options.maybe_packages_dir_path.has_value() ? + fs::path(ifw_options.maybe_packages_dir_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-packages"); + + fs.remove_all(ifw_packages_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not remove outdated packages directory %s", + ifw_packages_dir_path.generic_string()); + + fs.create_directory(ifw_packages_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create packages directory %s", + ifw_packages_dir_path.generic_string()); + + // execute the plan + std::map unique_packages; + std::set unique_triplets; + for (const ExportPlanAction& action : export_plan) + { + if (action.plan_type != ExportPlanType::ALREADY_BUILT) + { + Checks::unreachable(VCPKG_LINE_INFO); + } + + const std::string display_name = action.spec.to_string(); + System::println("Exporting package %s... ", display_name); + + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + unique_packages[action.spec.name()] = &action; + unique_triplets.insert(action.spec.triplet().canonical_name()); + + // Export real package and return data dir for installation + fs::path ifw_package_dir_path = export_real_package(ifw_packages_dir_path, action, fs); + + // Copy package data + const InstallDir dirs = InstallDir::from_destination_root(ifw_package_dir_path, + action.spec.triplet().to_string(), + ifw_package_dir_path / "vcpkg" / "info" / + (binary_paragraph.fullstem() + ".list")); + + Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); + System::println(System::Color::success, "Exporting package %s... done", display_name); + } + + // Unique packages + export_unique_packages(ifw_packages_dir_path, unique_packages, fs); + + // Unique triplets + export_unique_triplets(ifw_packages_dir_path, unique_triplets, fs); + + // Copy files needed for integration + export_integration_files(ifw_packages_dir_path / "integration" / "data", paths); + // Integration + export_integration(ifw_packages_dir_path, fs); + + System::println("Created ifw packages directory: %s", ifw_packages_dir_path.generic_string()); + + // Configuration + export_config(export_id, ifw_options, paths); } } -- cgit v1.2.3 From c6149fae2f9f33d9ed363650aee6aea642574b0a Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Wed, 27 Sep 2017 02:57:51 +0300 Subject: [vcpkg-export-ifw] Usage QtIFW tools Download and use tools to make repository and installer --- toolsrc/src/VcpkgPaths.cpp | 40 ++++++++++ toolsrc/src/commands_export.cpp | 19 +++-- toolsrc/src/commands_export_ifw.cpp | 145 +++++++++++++++++++++++++++++------- 3 files changed, 174 insertions(+), 30 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 02e238b3f..89435cd38 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -164,6 +164,31 @@ namespace vcpkg return fetch_dependency(scripts_folder, L"git", downloaded_copy, EXPECTED_VERSION); } + static fs::path get_ifw_installerbase_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + { + static constexpr std::array EXPECTED_VERSION = { 3, 1, 81 }; + static const std::wstring VERSION_CHECK_ARGUMENTS = L"--framework-version"; + + const fs::path downloaded_copy = downloads_folder / "QtInstallerFramework-win-x86" / "bin" / "installerbase.exe"; + + std::vector candidate_paths; + candidate_paths.push_back(downloaded_copy); + // TODO: Uncomment later + //const std::vector from_path = Files::find_from_PATH(L"installerbase"); + //candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + //candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe"); + //candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / "QtIFW-3.1.0" / "bin" / "installerbase.exe"); + + const Optional path = + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_dependency(scripts_folder, L"installerbase", downloaded_copy, EXPECTED_VERSION); + } + Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir) { std::error_code ec; @@ -247,6 +272,21 @@ namespace vcpkg return this->nuget_exe.get_lazy([this]() { return get_nuget_path(this->downloads, this->scripts); }); } + const fs::path& VcpkgPaths::get_ifw_installerbase_exe() const + { + return this->ifw_installerbase_exe.get_lazy([this]() { return get_ifw_installerbase_path(this->downloads, this->scripts); }); + } + + const fs::path& VcpkgPaths::get_ifw_binarycreator_exe() const + { + return this->ifw_binarycreator_exe.get_lazy([this]() { return get_ifw_installerbase_exe().parent_path() / "binarycreator.exe"; }); + } + + const fs::path& VcpkgPaths::get_ifw_repogen_exe() const + { + return this->ifw_repogen_exe.get_lazy([this]() { return get_ifw_installerbase_exe().parent_path() / "repogen.exe"; }); + } + static std::vector get_vs2017_installation_instances(const VcpkgPaths& paths) { const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index 6632dfe67..3662a46d8 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -249,7 +249,9 @@ namespace vcpkg::Commands::Export static const std::string OPTION_NUGET_VERSION = "--nuget-version"; static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url"; static const std::string OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path"; + static const std::string OPTION_IFW_REPOSITORY_DIR_PATH = "--ifw-repository-directory-path"; static const std::string OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path"; + static const std::string OPTION_IFW_INSTALLER_FILE_PATH = "--ifw-installer-file-path"; // input sanitization static const std::string EXAMPLE = @@ -276,7 +278,9 @@ namespace vcpkg::Commands::Export OPTION_NUGET_VERSION, OPTION_IFW_REPOSITORY_URL, OPTION_IFW_PACKAGES_DIR_PATH, - OPTION_IFW_CONFIG_FILE_PATH + OPTION_IFW_REPOSITORY_DIR_PATH, + OPTION_IFW_CONFIG_FILE_PATH, + OPTION_IFW_INSTALLER_FILE_PATH }); const bool dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); const bool raw = options.switches.find(OPTION_RAW) != options.switches.cend(); @@ -310,10 +314,18 @@ namespace vcpkg::Commands::Export Checks::check_exit( VCPKG_LINE_INFO, !ifw_options.maybe_packages_dir_path || ifw, "--ifw-packages-directory-path is only valid with --ifw"); + ifw_options.maybe_repository_dir_path = maybe_lookup(options.settings, OPTION_IFW_REPOSITORY_DIR_PATH); + Checks::check_exit( + VCPKG_LINE_INFO, !ifw_options.maybe_repository_dir_path || ifw, "--ifw-repository-directory-path is only valid with --ifw"); + ifw_options.maybe_config_file_path = maybe_lookup(options.settings, OPTION_IFW_CONFIG_FILE_PATH); Checks::check_exit( VCPKG_LINE_INFO, !ifw_options.maybe_config_file_path || ifw, "--ifw-configuration-file-path is only valid with --ifw"); + ifw_options.maybe_installer_file_path = maybe_lookup(options.settings, OPTION_IFW_INSTALLER_FILE_PATH); + Checks::check_exit( + VCPKG_LINE_INFO, !ifw_options.maybe_installer_file_path || ifw, "--ifw-installer-file-path is only valid with --ifw"); + // create the plan const StatusParagraphs status_db = database_load_check(paths); std::vector export_plan = Dependencies::create_export_plan(paths, specs, status_db); @@ -464,10 +476,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console { IFW::do_export(export_plan, export_id, ifw_options, paths); - // TODO: Download corrected QtIFW tools and automate installer creation - System::println("Use corrected QtIFW tools (for more info see: https://codereview.qt-project.org/#/c/203958) to create installer..."); - - print_next_step_info("[...]"); + print_next_step_info("@RootDir@/src/vcpkg"); } Checks::exit_success(VCPKG_LINE_INFO); diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp index e2499b75d..d1428f5d1 100644 --- a/toolsrc/src/commands_export_ifw.cpp +++ b/toolsrc/src/commands_export_ifw.cpp @@ -26,7 +26,35 @@ namespace vcpkg::Commands::Export::IFW return date_time_as_string; } - fs::path export_real_package(const fs::path& raw_exported_dir_path, + fs::path get_packages_dir_path(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_packages_dir_path.has_value() ? + fs::path(ifw_options.maybe_packages_dir_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-packages"); + } + + fs::path get_repository_dir_path(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_packages_dir_path.has_value() ? + fs::path(ifw_options.maybe_repository_dir_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-repository"); + } + + fs::path get_config_file_path(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_config_file_path.has_value() ? + fs::path(ifw_options.maybe_config_file_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-configuration.xml"); + } + + fs::path get_installer_file_path(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_config_file_path.has_value() ? + fs::path(ifw_options.maybe_installer_file_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-installer.exe"); + } + + fs::path export_real_package(const fs::path& ifw_packages_dir_path, const ExportPlanAction& action, Files::Filesystem& fs) { @@ -37,7 +65,7 @@ namespace vcpkg::Commands::Export::IFW // Prepare meta dir const fs::path package_xml_file_path = - raw_exported_dir_path / + ifw_packages_dir_path / Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "meta" / "package.xml"; const fs::path package_xml_dir_path = package_xml_file_path.parent_path(); @@ -47,6 +75,11 @@ namespace vcpkg::Commands::Export::IFW "Could not create directory for package file %s", package_xml_file_path.generic_string()); + auto deps = Strings::join( + ",", binary_paragraph.depends, [](const std::string& dep) { return "packages." + dep + ":"; }); + + if (!deps.empty()) deps = "\n " + deps + ""; + fs.write_contents(package_xml_file_path, Strings::format( R"###( @@ -54,7 +87,7 @@ R"###( %s %s %s - packages.%s:,triplets.%s: + packages.%s:,triplets.%s:%s true )###", @@ -62,10 +95,11 @@ R"###( binary_paragraph.version, create_release_date(), action.spec.name(), - action.spec.triplet().canonical_name())); + action.spec.triplet().canonical_name(), + deps)); // Return dir path for export package data - return raw_exported_dir_path / + return ifw_packages_dir_path / Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "data" / "installed"; } @@ -110,11 +144,6 @@ R"###( "Could not create directory for package file %s", package_xml_file_path.generic_string()); - auto deps = Strings::join( - ",", binary_paragraph.depends, [](const std::string& dep) { return "packages." + dep + ":"; }); - - if (!deps.empty()) deps = "\n " + deps + ""; - fs.write_contents(package_xml_file_path, Strings::format( R"###( @@ -122,14 +151,13 @@ R"###( %s %s %s - %s%s + %s )###", action.spec.name(), binary_paragraph.description, binary_paragraph.version, - create_release_date(), - deps)); + create_release_date())); } } @@ -210,9 +238,7 @@ R"###( std::error_code ec; Files::Filesystem& fs = paths.get_filesystem(); - const fs::path config_xml_file_path = ifw_options.maybe_config_file_path.has_value() ? - fs::path(ifw_options.maybe_config_file_path.value_or_exit(VCPKG_LINE_INFO)) - : paths.root / (export_id + "-ifw-configuration") / "config.xml"; + const fs::path config_xml_file_path = get_config_file_path(export_id, ifw_options, paths); fs::path config_xml_dir_path = config_xml_file_path.parent_path(); fs.create_directories(config_xml_dir_path, ec); @@ -243,21 +269,76 @@ R"###( )###", formatted_repo_url)); + } + + void do_repository(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + { + const fs::path& repogen_exe = paths.get_ifw_repogen_exe(); + const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); + const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); + + System::println("Generating repository %s...", repository_dir.generic_string()); - System::println("Created ifw configuration file: %s", config_xml_file_path.generic_string()); + const std::wstring cmd_line = + Strings::wformat(LR"("%s" --packages "%s" "%s" > nul)", + repogen_exe.native(), + packages_dir.native(), + repository_dir.native()); + + const int exit_code = System::cmd_execute_clean(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW repository generating failed"); + + System::println(System::Color::success, "Generating repository %s... done.", repository_dir.generic_string()); + } + + void do_installer(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + { + const fs::path& binarycreator_exe = paths.get_ifw_binarycreator_exe(); + const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); + const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); + const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); + const fs::path installer_file = get_installer_file_path(export_id, ifw_options, paths); + + System::println("Generating installer %s...", installer_file.generic_string()); + + std::wstring cmd_line; + + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) + { + cmd_line = + Strings::wformat(LR"("%s" --online-only --config "%s" --repository "%s" "%s" > nul)", + binarycreator_exe.native(), + config_file.native(), + repository_dir.native(), + installer_file.native()); + } + else + { + cmd_line = + Strings::wformat(LR"("%s" --config "%s" --packages "%s" "%s" > nul)", + binarycreator_exe.native(), + config_file.native(), + packages_dir.native(), + installer_file.native()); + } + + const int exit_code = System::cmd_execute_clean(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW installer generating failed"); + + System::println(System::Color::success, "Generating installer %s... done.", installer_file.generic_string()); } void do_export(const std::vector &export_plan, const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) { - System::println("Creating ifw packages... "); + const fs::path ifw_packages_dir_path = get_packages_dir_path(export_id, ifw_options, paths); + const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); + + System::println("Exporting packages %s... ", ifw_packages_dir_path.generic_string()); std::error_code ec; Files::Filesystem& fs = paths.get_filesystem(); - const fs::path ifw_packages_dir_path = ifw_options.maybe_packages_dir_path.has_value() ? - fs::path(ifw_options.maybe_packages_dir_path.value_or_exit(VCPKG_LINE_INFO)) - : paths.root / (export_id + "-ifw-packages"); - fs.remove_all(ifw_packages_dir_path, ec); Checks::check_exit(VCPKG_LINE_INFO, !ec, @@ -299,9 +380,13 @@ R"###( (binary_paragraph.fullstem() + ".list")); Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); - System::println(System::Color::success, "Exporting package %s... done", display_name); + System::println("Exporting package %s... done", display_name); } + System::println("Exporting packages %s... done", ifw_packages_dir_path.generic_string()); + + System::println("Generating configuration %s...", config_file.generic_string()); + // Unique packages export_unique_packages(ifw_packages_dir_path, unique_packages, fs); @@ -313,9 +398,19 @@ R"###( // Integration export_integration(ifw_packages_dir_path, fs); - System::println("Created ifw packages directory: %s", ifw_packages_dir_path.generic_string()); - // Configuration export_config(export_id, ifw_options, paths); + + System::println("Generating configuration %s... done.", config_file.generic_string()); + + // Do repository (optional) + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) + { + do_repository(export_id, ifw_options, paths); + } + + // Do installer + do_installer(export_id, ifw_options, paths); } } -- cgit v1.2.3 From d25fd5c7b3b0f21581dd9c44a915c9156683877a Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Thu, 28 Sep 2017 01:00:40 +0300 Subject: [vcpkg-export-ifw] Some improvements Improvements: - fix typos; - remove outdated repository directory. --- toolsrc/src/commands_export_ifw.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp index d1428f5d1..a0692c11e 100644 --- a/toolsrc/src/commands_export_ifw.cpp +++ b/toolsrc/src/commands_export_ifw.cpp @@ -35,7 +35,7 @@ namespace vcpkg::Commands::Export::IFW fs::path get_repository_dir_path(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) { - return ifw_options.maybe_packages_dir_path.has_value() ? + return ifw_options.maybe_repository_dir_path.has_value() ? fs::path(ifw_options.maybe_repository_dir_path.value_or_exit(VCPKG_LINE_INFO)) : paths.root / (export_id + "-ifw-repository"); } @@ -49,7 +49,7 @@ namespace vcpkg::Commands::Export::IFW fs::path get_installer_file_path(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) { - return ifw_options.maybe_config_file_path.has_value() ? + return ifw_options.maybe_installer_file_path.has_value() ? fs::path(ifw_options.maybe_installer_file_path.value_or_exit(VCPKG_LINE_INFO)) : paths.root / (export_id + "-ifw-installer.exe"); } @@ -279,6 +279,15 @@ R"###( System::println("Generating repository %s...", repository_dir.generic_string()); + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + fs.remove_all(repository_dir, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not remove outdated repository directory %s", + repository_dir.generic_string()); + const std::wstring cmd_line = Strings::wformat(LR"("%s" --packages "%s" "%s" > nul)", repogen_exe.native(), -- cgit v1.2.3 From eca068e4c5673b888d6470b42d6b5b44b21c4007 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 27 Sep 2017 17:22:40 -0700 Subject: Extract function for duplicated code --- toolsrc/src/VcpkgPaths.cpp | 51 ++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 27 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 02e238b3f..00f4691cd 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -269,10 +269,29 @@ namespace vcpkg return nullopt; } - static std::vector find_toolset_instances(const VcpkgPaths& paths) + static std::vector detect_supported_architectures(const Files::Filesystem& fs, + const fs::path& vcvarsall_dir) { using CPU = System::CPUArchitecture; + std::vector supported_architectures; + + if (fs.exists(vcvarsall_dir / "vcvars32.bat")) supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); + if (fs.exists(vcvarsall_dir / "vcvars64.bat")) + supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) + supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) + supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) + supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) + supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + + return supported_architectures; + } + static std::vector find_toolset_instances(const VcpkgPaths& paths) + { const auto& fs = paths.get_filesystem(); const std::vector vs2017_installation_instances = get_vs2017_installation_instances(paths); @@ -294,19 +313,8 @@ namespace vcpkg paths_examined.push_back(vs2015_dumpbin_exe); const fs::path vs2015_bin_dir = vs2015_vcvarsall_bat.parent_path() / "bin"; - std::vector supported_architectures; - if (fs.exists(vs2015_bin_dir / "vcvars32.bat")) - supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); - if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat")) - supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); - if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) - supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); - if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) - supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); - if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) - supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); - if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) - supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + const std::vector supported_architectures = + detect_supported_architectures(fs, vs2015_bin_dir); if (fs.exists(vs2015_dumpbin_exe)) { @@ -329,19 +337,8 @@ namespace vcpkg if (!fs.exists(vcvarsall_bat)) continue; // Get all supported architectures - std::vector supported_architectures; - if (fs.exists(vcvarsall_dir / "vcvars32.bat")) - supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvars64.bat")) - supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) - supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) - supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) - supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) - supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + const std::vector supported_architectures = + detect_supported_architectures(fs, vcvarsall_dir); // Locate the "best" MSVC toolchain version const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; -- cgit v1.2.3 From 712491c8223616803220b7f8b807ecb5a3e64ece Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 27 Sep 2017 17:48:51 -0700 Subject: Place line closer to usage --- toolsrc/src/VcpkgPaths.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 00f4691cd..b831b6f46 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -294,7 +294,6 @@ namespace vcpkg { const auto& fs = paths.get_filesystem(); - const std::vector vs2017_installation_instances = get_vs2017_installation_instances(paths); // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. std::vector paths_examined; @@ -324,6 +323,8 @@ namespace vcpkg } } + const std::vector vs2017_installation_instances = get_vs2017_installation_instances(paths); + // VS2017 Optional vs2017_toolset; for (const std::string& instance : vs2017_installation_instances) -- cgit v1.2.3 From f617a711ec4c3d5527911c32340238053901269d Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 27 Sep 2017 18:41:28 -0700 Subject: Fix: Don't break before finding all VS2017 instances --- toolsrc/src/VcpkgPaths.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index b831b6f46..8ce4df3df 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -364,7 +364,6 @@ namespace vcpkg if (const auto value = vs2017_toolset.get()) { found_toolsets.push_back(*value); - break; } } -- cgit v1.2.3 From 0ccea4f3677d92a20935e03c2cb301d8300b43d1 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 27 Sep 2017 18:55:09 -0700 Subject: [Toolset selection] Use VS2017 vcvarsall for v140 if available --- toolsrc/src/VcpkgPaths.cpp | 59 ++++++++++++++++++++++++++++++++++++++++----- toolsrc/src/vcpkg_Build.cpp | 7 +++++- 2 files changed, 59 insertions(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 8ce4df3df..8892207bd 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -10,6 +10,10 @@ namespace vcpkg { + // Intentionally wstring so we can easily use operator== with CWStringView. + static const std::wstring V_140 = L"v140"; + static const std::wstring V_141 = L"v141"; + static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd, const std::array& expected_version) { @@ -318,7 +322,7 @@ namespace vcpkg if (fs.exists(vs2015_dumpbin_exe)) { found_toolsets.push_back( - {vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140", supported_architectures}); + {vs2015_dumpbin_exe, vs2015_vcvarsall_bat, {}, V_140, supported_architectures}); } } } @@ -357,7 +361,7 @@ namespace vcpkg paths_examined.push_back(dumpbin_path); if (fs.exists(dumpbin_path)) { - vs2017_toolset = Toolset{dumpbin_path, vcvarsall_bat, L"v141", supported_architectures}; + vs2017_toolset = Toolset{dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}; break; } } @@ -381,20 +385,63 @@ namespace vcpkg return found_toolsets; } + static std::vector create_vs2017_v140_toolset_instances(const std::vector& vs_toolsets) + { + std::vector vs2017_v140_toolsets; + + // In constrast to v141 and above, there can only be a single instance of v140 (VS2017 vs VS2015). + const auto it = Util::find_if(vs_toolsets, [&](const Toolset& t) { return t.version == V_140; }); + + // If v140 is not available, then VS2017 cant use them. Return empty. + if (it == vs_toolsets.cend()) + { + return vs2017_v140_toolsets; + } + + // If it does exist, then create a matching v140 toolset for each v141 toolset + const Toolset v140_toolset = *it; + for (const Toolset& toolset : vs_toolsets) + { + if (toolset.version != V_141) + { + continue; + } + + Toolset t = Toolset{ + toolset.dumpbin, toolset.vcvarsall, {L"-vcvars_ver=14.0"}, V_140, toolset.supported_architectures}; + vs2017_v140_toolsets.push_back(std::move(t)); + } + + return vs2017_v140_toolsets; + } + const Toolset& VcpkgPaths::get_toolset(const std::string& toolset_version) const { + const std::wstring& w_toolset_version = Strings::to_utf16(toolset_version); + // Invariant: toolsets are non-empty and sorted with newest at back() - const auto& vs_toolsets = this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); + const std::vector& vs_toolsets = + this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); - if (toolset_version.empty()) + if (w_toolset_version.empty()) { return vs_toolsets.back(); } - const auto toolset = Util::find_if( - vs_toolsets, [&](const Toolset& t) { return toolset_version == Strings::to_utf8(t.version); }); + const auto toolset = + Util::find_if(vs_toolsets, [&](const Toolset& t) { return w_toolset_version == t.version; }); Checks::check_exit( VCPKG_LINE_INFO, toolset != vs_toolsets.end(), "Could not find toolset '%s'", toolset_version); + + // If v140 is the selected toolset and VS2017 is available, then use VS2017's vcvarsall with the + // -vcvars_ver=14.0 option + const std::vector& vs2017_v140_toolsets = this->toolsets_vs2017_v140.get_lazy( + [&vs_toolsets]() { return create_vs2017_v140_toolset_instances(vs_toolsets); }); + if (w_toolset_version == V_140 && !vs2017_v140_toolsets.empty()) + { + return vs2017_v140_toolsets.back(); + } + return *toolset; } diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index d40140aca..5ac13c6c6 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -67,7 +67,12 @@ namespace vcpkg::Build const auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset); const auto target = to_vcvarsall_target(pre_build_info.cmake_system_name); - return Strings::wformat(LR"("%s" %s %s %s 2>&1)", toolset.vcvarsall.native(), arch, target, tonull); + return Strings::wformat(LR"("%s" %s %s %s %s 2>&1)", + toolset.vcvarsall.native(), + Strings::join(L" ", toolset.vcvarsall_options), + arch, + target, + tonull); } static void create_binary_feature_control_file(const SourceParagraph& source_paragraph, -- cgit v1.2.3 From 450cb8591a5023f762b4b928cb36ca632d0fe7b3 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 28 Sep 2017 19:39:11 -0700 Subject: Revert "Extract function for duplicated code" This reverts commit eca068e4c5673b888d6470b42d6b5b44b21c4007. --- toolsrc/src/VcpkgPaths.cpp | 51 ++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 8892207bd..4634a87c0 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -273,29 +273,10 @@ namespace vcpkg return nullopt; } - static std::vector detect_supported_architectures(const Files::Filesystem& fs, - const fs::path& vcvarsall_dir) + static std::vector find_toolset_instances(const VcpkgPaths& paths) { using CPU = System::CPUArchitecture; - std::vector supported_architectures; - - if (fs.exists(vcvarsall_dir / "vcvars32.bat")) supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvars64.bat")) - supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) - supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) - supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) - supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) - supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); - - return supported_architectures; - } - static std::vector find_toolset_instances(const VcpkgPaths& paths) - { const auto& fs = paths.get_filesystem(); // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. @@ -316,8 +297,19 @@ namespace vcpkg paths_examined.push_back(vs2015_dumpbin_exe); const fs::path vs2015_bin_dir = vs2015_vcvarsall_bat.parent_path() / "bin"; - const std::vector supported_architectures = - detect_supported_architectures(fs, vs2015_bin_dir); + std::vector supported_architectures; + if (fs.exists(vs2015_bin_dir / "vcvars32.bat")) + supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); + if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat")) + supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); + if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) + supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) + supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); + if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) + supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) + supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); if (fs.exists(vs2015_dumpbin_exe)) { @@ -342,8 +334,19 @@ namespace vcpkg if (!fs.exists(vcvarsall_bat)) continue; // Get all supported architectures - const std::vector supported_architectures = - detect_supported_architectures(fs, vcvarsall_dir); + std::vector supported_architectures; + if (fs.exists(vcvarsall_dir / "vcvars32.bat")) + supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); + if (fs.exists(vcvarsall_dir / "vcvars64.bat")) + supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) + supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) + supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) + supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) + supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); // Locate the "best" MSVC toolchain version const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; -- cgit v1.2.3 From 53d5076f64daa08c18802fda1b7bf8e100109103 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sun, 1 Oct 2017 13:04:10 -0700 Subject: size_t instead of int --- toolsrc/src/tests_package_spec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests_package_spec.cpp b/toolsrc/src/tests_package_spec.cpp index fa201b372..a6b9d5b13 100644 --- a/toolsrc/src/tests_package_spec.cpp +++ b/toolsrc/src/tests_package_spec.cpp @@ -43,7 +43,7 @@ namespace UnitTest1 std::array features = {"", "0", "1", "", "2", "3"}; std::array specs = {&a_spec, &a_spec, &a_spec, &b_spec, &b_spec, &b_spec}; - for (int i = 0; i < features.size(); ++i) + for (size_t i = 0; i < features.size(); ++i) { Assert::AreEqual(features[i], fspecs[i].feature().c_str()); Assert::AreEqual(*specs[i], fspecs[i].spec()); -- cgit v1.2.3 From 2de9f83ff22774d0f70e3ee8158b26c494f5ea30 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sun, 1 Oct 2017 13:22:29 -0700 Subject: Introduce Strings::case_insensitive_ascii_starts_with(); --- toolsrc/src/vcpkg_Strings.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 5ad951399..1bd96fc12 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -110,6 +110,11 @@ namespace vcpkg::Strings return output; } + bool case_insensitive_ascii_starts_with(const std::string& s, const std::string& pattern) + { + return _strnicmp(s.c_str(), pattern.c_str(), pattern.size()) == 0; + } + void trim(std::string* s) { s->erase(std::find_if_not(s->rbegin(), s->rend(), details::isspace).base(), s->end()); @@ -136,8 +141,9 @@ namespace vcpkg::Strings std::vector split(const std::string& s, const std::string& delimiter) { std::vector output; - - if(delimiter.empty()){ + + if (delimiter.empty()) + { output.push_back(s); return output; } -- cgit v1.2.3 From b3e06443eab560d5de848f2a066e1baa477fa57b Mon Sep 17 00:00:00 2001 From: Maria Tavlaki Date: Sun, 1 Oct 2017 22:17:33 +0300 Subject: Create stub autocomplete function --- toolsrc/src/commands_autocomplete.cpp | 22 ++++++++++++++++++++++ toolsrc/src/commands_available_commands.cpp | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 toolsrc/src/commands_autocomplete.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_autocomplete.cpp b/toolsrc/src/commands_autocomplete.cpp new file mode 100644 index 000000000..71154445d --- /dev/null +++ b/toolsrc/src/commands_autocomplete.cpp @@ -0,0 +1,22 @@ +#include "pch.h" + +#include "Paragraphs.h" +#include "SortedVector.h" +#include "vcpkg_Commands.h" +#include "vcpkg_Maps.h" +#include "vcpkg_System.h" + +namespace vcpkg::Commands::Autocomplete +{ + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = + Strings::format("The argument should be a command line to autocomplete.\n%s", + Commands::Help::create_example_string("autocomplete install z")); + + args.check_max_arg_count(1, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/commands_available_commands.cpp b/toolsrc/src/commands_available_commands.cpp index 87cc43dca..d3280e6d7 100644 --- a/toolsrc/src/commands_available_commands.cpp +++ b/toolsrc/src/commands_available_commands.cpp @@ -34,7 +34,7 @@ namespace vcpkg::Commands {"import", &Import::perform_and_exit}, {"cache", &Cache::perform_and_exit}, {"portsdiff", &PortsDiff::perform_and_exit}, - }; + {"autocomplete", &Autocomplete::perform_and_exit}}; return t; } -- cgit v1.2.3 From fe89e72e9565f0515834b925f015fe19324c38da Mon Sep 17 00:00:00 2001 From: Maria Tavlaki Date: Sun, 1 Oct 2017 23:26:36 +0300 Subject: Autocomplete: handle arguments --- toolsrc/src/commands_autocomplete.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_autocomplete.cpp b/toolsrc/src/commands_autocomplete.cpp index 71154445d..a67113aff 100644 --- a/toolsrc/src/commands_autocomplete.cpp +++ b/toolsrc/src/commands_autocomplete.cpp @@ -14,9 +14,34 @@ namespace vcpkg::Commands::Autocomplete Strings::format("The argument should be a command line to autocomplete.\n%s", Commands::Help::create_example_string("autocomplete install z")); - args.check_max_arg_count(1, EXAMPLE); + args.check_min_arg_count(1, EXAMPLE); + args.check_max_arg_count(2, EXAMPLE); args.check_and_get_optional_command_arguments({}); + const std::string requested_command = args.command_arguments.at(0); + const std::string start_with = + args.command_arguments.size() > 1 ? args.command_arguments.at(1) : Strings::EMPTY; + + auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + auto& source_paragraphs = sources_and_errors.paragraphs; + + const auto& istartswith = Strings::case_insensitive_ascii_starts_with; + + std::vector results; + for (const auto& source_control_file : source_paragraphs) + { + auto&& sp = *source_control_file->core_paragraph; + + if (istartswith(sp.name, start_with)) + { + results.push_back(sp.name); + } + } + + System::println(Strings::join(" ", results)); + + auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + Checks::exit_success(VCPKG_LINE_INFO); } } -- cgit v1.2.3 From 7c2239f980197096a13e8fb4b96297b08616eb78 Mon Sep 17 00:00:00 2001 From: Maria Tavlaki Date: Mon, 2 Oct 2017 00:03:39 +0300 Subject: Autocomplete: check if first argument is "install" --- toolsrc/src/commands_autocomplete.cpp | 37 ++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_autocomplete.cpp b/toolsrc/src/commands_autocomplete.cpp index a67113aff..013cea320 100644 --- a/toolsrc/src/commands_autocomplete.cpp +++ b/toolsrc/src/commands_autocomplete.cpp @@ -8,6 +8,23 @@ namespace vcpkg::Commands::Autocomplete { + std::vector autocomplete_install( + const std::vector>& source_paragraphs, const std::string& start_with) + { + std::vector results; + const auto& istartswith = Strings::case_insensitive_ascii_starts_with; + + for (const auto& source_control_file : source_paragraphs) + { + auto&& sp = *source_control_file->core_paragraph; + + if (istartswith(sp.name, start_with)) + { + results.push_back(sp.name); + } + } + return results; + } void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { static const std::string EXAMPLE = @@ -21,27 +38,15 @@ namespace vcpkg::Commands::Autocomplete const std::string requested_command = args.command_arguments.at(0); const std::string start_with = args.command_arguments.size() > 1 ? args.command_arguments.at(1) : Strings::EMPTY; - - auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); - auto& source_paragraphs = sources_and_errors.paragraphs; - - const auto& istartswith = Strings::case_insensitive_ascii_starts_with; - std::vector results; - for (const auto& source_control_file : source_paragraphs) + if (requested_command == "install") { - auto&& sp = *source_control_file->core_paragraph; + auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + auto& source_paragraphs = sources_and_errors.paragraphs; - if (istartswith(sp.name, start_with)) - { - results.push_back(sp.name); - } + results = autocomplete_install(source_paragraphs, start_with); } - System::println(Strings::join(" ", results)); - - auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); - Checks::exit_success(VCPKG_LINE_INFO); } } -- cgit v1.2.3 From 016c53e231f353bdfa35f8e265b281e8d56031ed Mon Sep 17 00:00:00 2001 From: Maria Tavlaki Date: Mon, 2 Oct 2017 00:38:53 +0300 Subject: Autocomplete: remove --- toolsrc/src/commands_autocomplete.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_autocomplete.cpp b/toolsrc/src/commands_autocomplete.cpp index 013cea320..3963f904b 100644 --- a/toolsrc/src/commands_autocomplete.cpp +++ b/toolsrc/src/commands_autocomplete.cpp @@ -5,6 +5,7 @@ #include "vcpkg_Commands.h" #include "vcpkg_Maps.h" #include "vcpkg_System.h" +#include "vcpkglib.h" namespace vcpkg::Commands::Autocomplete { @@ -25,6 +26,25 @@ namespace vcpkg::Commands::Autocomplete } return results; } + + std::vector autocomplete_remove(std::vector installed_packages, + const std::string& start_with) + { + std::vector results; + const auto& istartswith = Strings::case_insensitive_ascii_starts_with; + + for (const auto& installed_package : installed_packages) + { + auto sp = installed_package->package.displayname(); + + if (istartswith(sp, start_with)) + { + results.push_back(sp); + } + } + return results; + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { static const std::string EXAMPLE = @@ -46,6 +66,13 @@ namespace vcpkg::Commands::Autocomplete results = autocomplete_install(source_paragraphs, start_with); } + else if (requested_command == "remove") + { + const StatusParagraphs status_db = database_load_check(paths); + std::vector installed_packages = get_installed_ports(status_db); + results = autocomplete_remove(installed_packages, start_with); + } + System::println(Strings::join(" ", results)); Checks::exit_success(VCPKG_LINE_INFO); } -- cgit v1.2.3 From 20d911a91508c16bd01272ae94a3ca239a4d984e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 2 Oct 2017 13:57:55 -0700 Subject: [vcpkg] Fix use of UNICODE-sensitive Windows APIs --- toolsrc/src/commands_integrate.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_integrate.cpp b/toolsrc/src/commands_integrate.cpp index 1bf26910c..fd2f11294 100644 --- a/toolsrc/src/commands_integrate.cpp +++ b/toolsrc/src/commands_integrate.cpp @@ -113,19 +113,20 @@ namespace vcpkg::Commands::Integrate static ElevationPromptChoice elevated_cmd_execute(const std::string& param) { - SHELLEXECUTEINFO sh_ex_info = {0}; + SHELLEXECUTEINFOW sh_ex_info = {0}; sh_ex_info.cbSize = sizeof(sh_ex_info); sh_ex_info.fMask = SEE_MASK_NOCLOSEPROCESS; sh_ex_info.hwnd = nullptr; - sh_ex_info.lpVerb = "runas"; - sh_ex_info.lpFile = "cmd"; // Application to start + sh_ex_info.lpVerb = L"runas"; + sh_ex_info.lpFile = L"cmd"; // Application to start - sh_ex_info.lpParameters = param.c_str(); // Additional parameters + auto wparam = Strings::to_utf16(param); + sh_ex_info.lpParameters = wparam.c_str(); // Additional parameters sh_ex_info.lpDirectory = nullptr; sh_ex_info.nShow = SW_HIDE; sh_ex_info.hInstApp = nullptr; - if (!ShellExecuteExA(&sh_ex_info)) + if (!ShellExecuteExW(&sh_ex_info)) { return ElevationPromptChoice::NO; } -- cgit v1.2.3 From bdbf00c7ab6f7dc5ca096391c913a0af5e291d19 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 2 Oct 2017 14:44:41 -0700 Subject: Add message when downloading cmake/git/nuget --- toolsrc/src/VcpkgPaths.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 4634a87c0..f227f9114 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -67,14 +67,18 @@ namespace vcpkg const fs::path& expected_downloaded_path, const std::array& version) { + const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); + System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", + Strings::to_utf8(tool_name), + version_as_string, + Strings::to_utf8(tool_name), + version_as_string); const fs::path script = scripts_folder / "fetchDependency.ps1"; const auto install_cmd = System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name)); const System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd); if (rc.exit_code) { - const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); - System::println(System::Color::error, "Launching powershell failed or was denied when trying to fetch %s version %s.\n" "(No sufficient installed version was found)", -- cgit v1.2.3 From d25a072c76ff81934813f20116788140621619ba Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 2 Oct 2017 14:57:52 -0700 Subject: Show warning instead of failing if port cannot be parsed --- toolsrc/src/Paragraphs.cpp | 18 +++++++++++++++--- toolsrc/src/commands_install.cpp | 4 ++-- toolsrc/src/commands_search.cpp | 21 +-------------------- 3 files changed, 18 insertions(+), 25 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index a7dee4fd3..6a6f191df 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -254,7 +254,7 @@ namespace vcpkg::Paragraphs for (auto&& path : fs.get_files_non_recursive(ports_dir)) { auto maybe_spgh = try_load_port(fs, path); - if (auto spgh = maybe_spgh.get()) + if (const auto spgh = maybe_spgh.get()) { ret.paragraphs.emplace_back(std::move(*spgh)); } @@ -272,8 +272,20 @@ namespace vcpkg::Paragraphs auto results = try_load_all_ports(fs, ports_dir); if (!results.errors.empty()) { - print_error_message(results.errors); - Checks::exit_fail(VCPKG_LINE_INFO); + if (GlobalState::debugging) + { + print_error_message(results.errors); + } + else + { + for (auto&& error : results.errors) + { + System::println( + System::Color::warning, "Warning: an error occurred while parsing '%s'", error->name); + } + System::println(System::Color::warning, + "Use '--debug' to get more information about the parse failures.\n"); + } } return std::move(results.paragraphs); } diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index aca25996e..d815332fe 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -568,8 +568,8 @@ namespace vcpkg::Commands::Install if (GlobalState::feature_packages) { std::unordered_map scf_map; - auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); - for (auto&& port : all_ports.paragraphs) + auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + for (auto&& port : all_ports) { scf_map[port->core_paragraph->name] = std::move(*port); } diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index 1ccec9fbe..d35a546c4 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -87,27 +87,8 @@ namespace vcpkg::Commands::Search const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC}); - auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + auto source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - if (!sources_and_errors.errors.empty()) - { - if (GlobalState::debugging) - { - print_error_message(sources_and_errors.errors); - } - else - { - for (auto&& error : sources_and_errors.errors) - { - System::println( - System::Color::warning, "Warning: an error occurred while parsing '%s'", error->name); - } - System::println(System::Color::warning, - "Use '--debug' to get more information about the parse failures.\n"); - } - } - - auto& source_paragraphs = sources_and_errors.paragraphs; if (options.find(OPTION_GRAPH) != options.cend()) { const std::string graph_as_string = create_graph_as_string(source_paragraphs); -- cgit v1.2.3 From 4c4e6c7c7af52732de07ca247cf62e2a3c5d2f25 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 2 Oct 2017 16:00:45 -0700 Subject: Extract local variable --- toolsrc/src/VcpkgPaths.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index f227f9114..d491cb7fb 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -67,11 +67,12 @@ namespace vcpkg const fs::path& expected_downloaded_path, const std::array& version) { + const std::string tool_name_utf8 = Strings::to_utf8(tool_name); const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", - Strings::to_utf8(tool_name), + tool_name_utf8, version_as_string, - Strings::to_utf8(tool_name), + tool_name_utf8, version_as_string); const fs::path script = scripts_folder / "fetchDependency.ps1"; const auto install_cmd = @@ -82,7 +83,7 @@ namespace vcpkg System::println(System::Color::error, "Launching powershell failed or was denied when trying to fetch %s version %s.\n" "(No sufficient installed version was found)", - Strings::to_utf8(tool_name), + tool_name_utf8, version_as_string); { auto locked_metrics = Metrics::g_metrics.lock(); -- cgit v1.2.3 From ca692e52cee55da2f9d65d66e5f3997f3a335743 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 2 Oct 2017 16:40:18 -0700 Subject: Replace deprecated std::codecvt/std::wstring_convert. Fixes building with v141 --- toolsrc/src/vcpkg_Strings.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 1bd96fc12..964ed73d0 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -73,14 +73,20 @@ namespace vcpkg::Strings { std::wstring to_utf16(const CStringView s) { - std::wstring_convert, wchar_t> conversion; - return conversion.from_bytes(s); + const size_t size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0); + std::wstring output; + output.resize(size - 1); + MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, output.data(), size - 1); + return output; } std::string to_utf8(const CWStringView w) { - std::wstring_convert, wchar_t> conversion; - return conversion.to_bytes(w); + const size_t size = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr); + std::string output; + output.resize(size - 1); + WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, output.data(), size - 1, nullptr, nullptr); + return output; } std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern) -- cgit v1.2.3 From f72cf87ab21c1b6966c09ec3e7fd5d7f9052ea0a Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 2 Oct 2017 16:41:52 -0700 Subject: Change size_t to int (which is the actual return type) --- toolsrc/src/vcpkg_Strings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 964ed73d0..07147862f 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -73,7 +73,7 @@ namespace vcpkg::Strings { std::wstring to_utf16(const CStringView s) { - const size_t size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0); + const int size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0); std::wstring output; output.resize(size - 1); MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, output.data(), size - 1); @@ -82,7 +82,7 @@ namespace vcpkg::Strings std::string to_utf8(const CWStringView w) { - const size_t size = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr); + const int size = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr); std::string output; output.resize(size - 1); WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, output.data(), size - 1, nullptr, nullptr); -- cgit v1.2.3 From e25a31eca8550780ce96586ef27063728441b2e2 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 2 Oct 2017 16:55:06 -0700 Subject: Suppress 4768 warning from shlobj.h --- toolsrc/src/vcpkg.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index f4300a73c..706c641fb 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -11,7 +11,10 @@ #include "vcpkg_Strings.h" #include "vcpkg_System.h" #include "vcpkglib.h" +#pragma warning(push) +#pragma warning(disable : 4768) #include +#pragma warning(pop) #include #include #include -- cgit v1.2.3 From 3838d5880470fdc884f035ed3d1c67d3bdd1e16e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 3 Oct 2017 15:51:04 -0700 Subject: [vcpkg] Add more operator== to CStringView. Uppercase Span to follow naming convention. --- toolsrc/src/PostBuildLint.cpp | 4 ++-- toolsrc/src/SourceParagraph.cpp | 4 ++-- toolsrc/src/VcpkgPaths.cpp | 6 +++--- toolsrc/src/vcpkg_Build.cpp | 2 +- toolsrc/src/vcpkg_Strings.cpp | 2 +- toolsrc/src/vcpkg_System.cpp | 13 +++++++------ 6 files changed, 16 insertions(+), 15 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 1fd48d3ec..416d4a636 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -38,7 +38,7 @@ namespace vcpkg::PostBuildLint } }; - const std::vector& get_outdated_dynamic_crts() + Span get_outdated_dynamic_crts(CStringView toolset) { static const std::vector V_NO_MSVCRT = { {"msvcp100.dll", R"(msvcp100\.dll)"}, @@ -662,7 +662,7 @@ namespace vcpkg::PostBuildLint "Running command:\n %s\n failed", Strings::to_utf8(cmd_line)); - for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts()) + for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts("v141")) { if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), outdated_crt.regex)) { diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 171689ce7..0f1a38d19 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -25,7 +25,7 @@ namespace vcpkg static const std::string VERSION = "Version"; } - static span get_list_of_valid_fields() + static Span get_list_of_valid_fields() { static const std::string valid_fields[] = { Fields::SOURCE, @@ -38,7 +38,7 @@ namespace vcpkg return valid_fields; } - void print_error_message(span> error_info_list) + void print_error_message(Span> error_info_list) { Checks::check_exit(VCPKG_LINE_INFO, error_info_list.size() > 0); diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index d491cb7fb..cb00183fd 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -10,9 +10,9 @@ namespace vcpkg { - // Intentionally wstring so we can easily use operator== with CWStringView. - static const std::wstring V_140 = L"v140"; - static const std::wstring V_141 = L"v141"; + static constexpr CWStringView V_120 = L"v120"; + static constexpr CWStringView V_140 = L"v140"; + static constexpr CWStringView V_141 = L"v141"; static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd, const std::array& expected_version) diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index 5ac13c6c6..853f84998 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -165,7 +165,7 @@ namespace vcpkg::Build {L"PORT", config.src.name}, {L"CURRENT_PORT_DIR", config.port_dir / "/."}, {L"TARGET_TRIPLET", triplet.canonical_name()}, - {L"VCPKG_PLATFORM_TOOLSET", toolset.version}, + {L"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, {L"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? L"1" : L"0"}, {L"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? L"1" : L"0"}, {L"GIT", git_exe_path}, diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 07147862f..21df2c309 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -106,7 +106,7 @@ namespace vcpkg::Strings int case_insensitive_ascii_compare(const CStringView left, const CStringView right) { - return _stricmp(left, right); + return _stricmp(left.c_str(), right.c_str()); } std::string ascii_to_lowercase(const std::string& input) diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 40e335117..4d2e88b73 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -226,7 +226,7 @@ namespace vcpkg::System void println() { println(Strings::EMPTY); } - void print(const CStringView message) { fputs(message, stdout); } + void print(const CStringView message) { fputs(message.c_str(), stdout); } void println(const CStringView message) { @@ -255,13 +255,13 @@ namespace vcpkg::System Optional get_environment_variable(const CWStringView varname) noexcept { - const auto sz = GetEnvironmentVariableW(varname, nullptr, 0); + const auto sz = GetEnvironmentVariableW(varname.c_str(), nullptr, 0); if (sz == 0) return nullopt; std::wstring ret(sz, L'\0'); Checks::check_exit(VCPKG_LINE_INFO, MAXDWORD >= ret.size()); - const auto sz2 = GetEnvironmentVariableW(varname, ret.data(), static_cast(ret.size())); + const auto sz2 = GetEnvironmentVariableW(varname.c_str(), ret.data(), static_cast(ret.size())); Checks::check_exit(VCPKG_LINE_INFO, sz2 + 1 == sz); ret.pop_back(); return ret; @@ -275,19 +275,20 @@ namespace vcpkg::System Optional get_registry_string(HKEY base, const CWStringView sub_key, const CWStringView valuename) { HKEY k = nullptr; - const LSTATUS ec = RegOpenKeyExW(base, sub_key, NULL, KEY_READ, &k); + const LSTATUS ec = RegOpenKeyExW(base, sub_key.c_str(), NULL, KEY_READ, &k); if (ec != ERROR_SUCCESS) return nullopt; DWORD dw_buffer_size = 0; DWORD dw_type = 0; - auto rc = RegQueryValueExW(k, valuename, nullptr, &dw_type, nullptr, &dw_buffer_size); + auto rc = RegQueryValueExW(k, valuename.c_str(), nullptr, &dw_type, nullptr, &dw_buffer_size); if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size == 0 || dw_buffer_size % sizeof(wchar_t) != 0) return nullopt; std::wstring ret; ret.resize(dw_buffer_size / sizeof(wchar_t)); - rc = RegQueryValueExW(k, valuename, nullptr, &dw_type, reinterpret_cast(ret.data()), &dw_buffer_size); + rc = RegQueryValueExW( + k, valuename.c_str(), nullptr, &dw_type, reinterpret_cast(ret.data()), &dw_buffer_size); if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size != sizeof(wchar_t) * ret.size()) return nullopt; -- cgit v1.2.3 From 63753e86a60ef508760d9f4dd98b7f2336cd089c Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 3 Oct 2017 16:00:23 -0700 Subject: [vcpkg] Split toolset searches based on triplet's specification (don't pick v120 if it's blank). --- toolsrc/src/PostBuildLint.cpp | 31 +++++++++++++------ toolsrc/src/VcpkgPaths.cpp | 71 ++++++++++++++++++++++++++++--------------- 2 files changed, 67 insertions(+), 35 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 69008fab3..58d6f987b 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -40,26 +40,36 @@ namespace vcpkg::PostBuildLint Span get_outdated_dynamic_crts(CStringView toolset) { - static const std::vector V_NO_MSVCRT = { + static const std::vector V_NO_120 = { {"msvcp100.dll", R"(msvcp100\.dll)"}, {"msvcp100d.dll", R"(msvcp100d\.dll)"}, {"msvcp110.dll", R"(msvcp110\.dll)"}, {"msvcp110_win.dll", R"(msvcp110_win\.dll)"}, - //{"msvcp120.dll", R"(msvcp120\.dll)"}, - //{"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"}, {"msvcp60.dll", R"(msvcp60\.dll)"}, {"msvcp60.dll", R"(msvcp60\.dll)"}, + {"msvcrt.dll", R"(msvcrt\.dll)"}, {"msvcr100.dll", R"(msvcr100\.dll)"}, {"msvcr100d.dll", R"(msvcr100d\.dll)"}, {"msvcr100_clr0400.dll", R"(msvcr100_clr0400\.dll)"}, {"msvcr110.dll", R"(msvcr110\.dll)"}, - //{"msvcr120.dll", R"(msvcr120\.dll)"}, - //{"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"}, {"msvcrt20.dll", R"(msvcrt20\.dll)"}, - {"msvcrt40.dll", R"(msvcrt40\.dll)"}}; + {"msvcrt40.dll", R"(msvcrt40\.dll)"}, + }; - return V_NO_MSVCRT; + static const std::vector V = [&]() { + auto ret = V_NO_120; + ret.push_back({"msvcp120.dll", R"(msvcp120\.dll)"}); + ret.push_back({"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"}); + ret.push_back({"msvcr120.dll", R"(msvcr120\.dll)"}); + ret.push_back({"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"}); + return ret; + }(); + + if (toolset == "v120") + return V_NO_120; + else + return V; } static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs, @@ -646,7 +656,8 @@ namespace vcpkg::PostBuildLint static LintStatus check_outdated_crt_linkage_of_dlls(const std::vector& dlls, const fs::path dumpbin_exe, - const BuildInfo& build_info) + const BuildInfo& build_info, + const PreBuildInfo& pre_build_info) { if (build_info.policies.is_enabled(BuildPolicy::ALLOW_OBSOLETE_MSVCRT)) return LintStatus::SUCCESS; @@ -662,7 +673,7 @@ namespace vcpkg::PostBuildLint "Running command:\n %s\n failed", Strings::to_utf8(cmd_line)); - for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts("v141")) + for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts(pre_build_info.platform_toolset)) { if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), outdated_crt.regex)) { @@ -788,7 +799,7 @@ namespace vcpkg::PostBuildLint error_count += check_uwp_bit_of_dlls(pre_build_info.cmake_system_name, dlls, toolset.dumpbin); error_count += check_dll_architecture(pre_build_info.target_architecture, dlls); - error_count += check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info); + error_count += check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info, pre_build_info); break; } case Build::LinkageType::STATIC: diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 651d4d834..e8eb4f01c 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -277,48 +277,38 @@ namespace vcpkg return nullopt; } - - static Optional get_vs2013_installation_instance() - { - const Optional vs2013_cmntools_optional = System::get_environment_variable(L"VS120COMNTOOLS"); - if (const auto v = vs2013_cmntools_optional.get()) - { - const fs::path vs2013_cmntools = fs::path(*v).parent_path(); // The call to parent_path() is needed because - // the env variable has a trailing backslash - return vs2013_cmntools.parent_path().parent_path(); - } - return nullopt; - } - - static std::vector find_toolset_instances(const VcpkgPaths& paths) + static std::vector find_v120_toolset_instances(const Files::Filesystem& fs) { using CPU = System::CPUArchitecture; - const auto& fs = paths.get_filesystem(); - // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. std::vector paths_examined; std::vector found_toolsets; // VS2013 - const Optional vs_2013_installation_instance = get_vs2013_installation_instance(); - if (const auto v = vs_2013_installation_instance.get()) + const Optional vs2013_cmntools_optional = System::get_environment_variable(L"VS120COMNTOOLS"); + if (const auto vs120comntools = vs2013_cmntools_optional.get()) { - const fs::path vs2013_vcvarsall_bat = *v / "VC" / "vcvarsall.bat"; + const fs::path vs2013_cmntools = + fs::path(*vs120comntools).parent_path(); // The call to parent_path() is needed because + // the env variable has a trailing backslash + auto v = vs2013_cmntools.parent_path().parent_path(); + + const fs::path vs2013_vcvarsall_bat = v / "VC" / "vcvarsall.bat"; paths_examined.push_back(vs2013_vcvarsall_bat); if (fs.exists(vs2013_vcvarsall_bat)) { - const fs::path vs2013_dumpbin_exe = *v / "VC" / "bin" / "dumpbin.exe"; + const fs::path vs2013_dumpbin_exe = v / "VC" / "bin" / "dumpbin.exe"; paths_examined.push_back(vs2013_dumpbin_exe); const fs::path vs2013_bin_dir = vs2013_vcvarsall_bat.parent_path() / "bin"; std::vector supported_architectures; if (fs.exists(vs2013_bin_dir / "vcvars32.bat")) supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); - if (fs.exists(3 / "amd64\\vcvars64.bat")) + if (fs.exists(vs2013_bin_dir / "amd64\\vcvars64.bat")) supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); if (fs.exists(vs2013_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); @@ -332,11 +322,36 @@ namespace vcpkg if (fs.exists(vs2013_dumpbin_exe)) { found_toolsets.push_back( - {vs2013_dumpbin_exe, vs2013_vcvarsall_bat, L"v120", supported_architectures}); + {vs2013_dumpbin_exe, vs2013_vcvarsall_bat, {}, V_120, supported_architectures}); } } } - + + if (found_toolsets.empty()) + { + System::println(System::Color::error, "Could not locate a complete toolset."); + System::println("The following paths were examined:"); + for (const fs::path& path : paths_examined) + { + System::println(" %s", path.u8string()); + } + Checks::exit_fail(VCPKG_LINE_INFO); + } + + return found_toolsets; + } + + static std::vector find_toolset_instances(const VcpkgPaths& paths) + { + using CPU = System::CPUArchitecture; + + const auto& fs = paths.get_filesystem(); + + // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. + std::vector paths_examined; + + std::vector found_toolsets; + // VS2015 const Optional vs_2015_installation_instance = get_vs2015_installation_instance(); if (const auto v = vs_2015_installation_instance.get()) @@ -372,8 +387,6 @@ namespace vcpkg } } - const std::vector vs2017_installation_instances = get_vs2017_installation_instances(paths); - // VS2017 Optional vs2017_toolset; const std::vector vs2017_installation_instances = get_vs2017_installation_instances(paths); @@ -476,6 +489,14 @@ namespace vcpkg { const std::wstring& w_toolset_version = Strings::to_utf16(toolset_version); + if (w_toolset_version == V_120) + { + const auto& v120_toolsets = this->toolsets_vs2013.get_lazy( + [this]() { return find_v120_toolset_instances(this->get_filesystem()); }); + Checks::check_exit(VCPKG_LINE_INFO, v120_toolsets.size() > 0); + return v120_toolsets.back(); + } + // Invariant: toolsets are non-empty and sorted with newest at back() const std::vector& vs_toolsets = this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); -- cgit v1.2.3 From 1b71053ad9954ffb0cb3c2955f42a86f62f66372 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 4 Oct 2017 16:01:29 -0700 Subject: [vcpkg] Reformat and refactor to reduce function size --- toolsrc/src/VcpkgPaths.cpp | 24 ++- toolsrc/src/commands_export.cpp | 324 ++++++++++++++++++++---------------- toolsrc/src/commands_export_ifw.cpp | 167 ++++++++++--------- 3 files changed, 278 insertions(+), 237 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 19210facf..9f85992be 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -175,18 +175,21 @@ namespace vcpkg static fs::path get_ifw_installerbase_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array EXPECTED_VERSION = { 3, 1, 81 }; + static constexpr std::array EXPECTED_VERSION = {3, 1, 81}; static const std::wstring VERSION_CHECK_ARGUMENTS = L"--framework-version"; - const fs::path downloaded_copy = downloads_folder / "QtInstallerFramework-win-x86" / "bin" / "installerbase.exe"; + const fs::path downloaded_copy = + downloads_folder / "QtInstallerFramework-win-x86" / "bin" / "installerbase.exe"; std::vector candidate_paths; candidate_paths.push_back(downloaded_copy); // TODO: Uncomment later - //const std::vector from_path = Files::find_from_PATH(L"installerbase"); - //candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - //candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe"); - //candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / "QtIFW-3.1.0" / "bin" / "installerbase.exe"); + // const std::vector from_path = Files::find_from_PATH(L"installerbase"); + // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / + // "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe"); + // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / + // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); const Optional path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); @@ -283,17 +286,20 @@ namespace vcpkg const fs::path& VcpkgPaths::get_ifw_installerbase_exe() const { - return this->ifw_installerbase_exe.get_lazy([this]() { return get_ifw_installerbase_path(this->downloads, this->scripts); }); + return this->ifw_installerbase_exe.get_lazy( + [this]() { return get_ifw_installerbase_path(this->downloads, this->scripts); }); } const fs::path& VcpkgPaths::get_ifw_binarycreator_exe() const { - return this->ifw_binarycreator_exe.get_lazy([this]() { return get_ifw_installerbase_exe().parent_path() / "binarycreator.exe"; }); + return this->ifw_binarycreator_exe.get_lazy( + [this]() { return get_ifw_installerbase_exe().parent_path() / "binarycreator.exe"; }); } const fs::path& VcpkgPaths::get_ifw_repogen_exe() const { - return this->ifw_repogen_exe.get_lazy([this]() { return get_ifw_installerbase_exe().parent_path() / "repogen.exe"; }); + return this->ifw_repogen_exe.get_lazy( + [this]() { return get_ifw_installerbase_exe().parent_path() / "repogen.exe"; }); } static std::vector get_vs2017_installation_instances(const VcpkgPaths& paths) diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index 3662a46d8..a24f2eac7 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -211,17 +211,17 @@ namespace vcpkg::Commands::Export return nullopt; } - void export_integration_files(const fs::path &raw_exported_dir_path, const VcpkgPaths& paths) + void export_integration_files(const fs::path& raw_exported_dir_path, const VcpkgPaths& paths) { const std::vector integration_files_relative_to_root = { - { ".vcpkg-root" }, - { fs::path{ "scripts" } / "buildsystems" / "msbuild" / "applocal.ps1" }, - { fs::path{ "scripts" } / "buildsystems" / "msbuild" / "vcpkg.targets" }, - { fs::path{ "scripts" } / "buildsystems" / "vcpkg.cmake" }, - { fs::path{ "scripts" } / "cmake" / "vcpkg_get_windows_sdk.cmake" }, - { fs::path{ "scripts" } / "getWindowsSDK.ps1" }, - { fs::path{ "scripts" } / "getProgramFilesPlatformBitness.ps1" }, - { fs::path{ "scripts" } / "getProgramFiles32bit.ps1" }, + {".vcpkg-root"}, + {fs::path{"scripts"} / "buildsystems" / "msbuild" / "applocal.ps1"}, + {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"}, + {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"}, + {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"}, + {fs::path{"scripts"} / "getWindowsSDK.ps1"}, + {fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"}, + {fs::path{"scripts"} / "getProgramFiles32bit.ps1"}, }; for (const fs::path& file : integration_files_relative_to_root) @@ -237,8 +237,27 @@ namespace vcpkg::Commands::Export } } - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + struct ExportArguments + { + bool dry_run; + bool raw; + bool nuget; + bool ifw; + bool zip; + bool seven_zip; + + Optional maybe_nuget_id; + Optional maybe_nuget_version; + + IFW::Options ifw_options; + std::vector specs; + }; + + static ExportArguments handle_export_command_arguments(const VcpkgCmdArguments& args, + const Triplet& default_triplet) { + ExportArguments ret; + static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_RAW = "--raw"; static const std::string OPTION_NUGET = "--nuget"; @@ -258,11 +277,9 @@ namespace vcpkg::Commands::Export Commands::Help::create_example_string("export zlib zlib:x64-windows boost --nuget"); args.check_min_arg_count(1, EXAMPLE); - const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + ret.specs = Util::fmap(args.command_arguments, [&](auto&& arg) { return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); }); - for (auto&& spec : specs) - Input::check_triplet(spec.triplet(), paths); const auto options = args.check_and_get_optional_command_arguments( { @@ -280,16 +297,16 @@ namespace vcpkg::Commands::Export OPTION_IFW_PACKAGES_DIR_PATH, OPTION_IFW_REPOSITORY_DIR_PATH, OPTION_IFW_CONFIG_FILE_PATH, - OPTION_IFW_INSTALLER_FILE_PATH + OPTION_IFW_INSTALLER_FILE_PATH, }); - const bool dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); - const bool raw = options.switches.find(OPTION_RAW) != options.switches.cend(); - const bool nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); - const bool ifw = options.switches.find(OPTION_IFW) != options.switches.cend(); - const bool zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); - const bool seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend(); - - if (!raw && !nuget && !ifw && !zip && !seven_zip && !dry_run) + ret.dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); + ret.raw = options.switches.find(OPTION_RAW) != options.switches.cend(); + ret.nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); + ret.ifw = options.switches.find(OPTION_IFW) != options.switches.cend(); + ret.zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); + ret.seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend(); + + if (!ret.raw && !ret.nuget && !ret.ifw && !ret.zip && !ret.seven_zip && !ret.dry_run) { System::println(System::Color::error, "Must provide at least one export type: --raw --nuget --ifw --zip --7zip"); @@ -297,38 +314,152 @@ namespace vcpkg::Commands::Export Checks::exit_fail(VCPKG_LINE_INFO); } - auto maybe_nuget_id = maybe_lookup(options.settings, OPTION_NUGET_ID); - auto maybe_nuget_version = maybe_lookup(options.settings, OPTION_NUGET_VERSION); + ret.maybe_nuget_id = maybe_lookup(options.settings, OPTION_NUGET_ID); + ret.maybe_nuget_version = maybe_lookup(options.settings, OPTION_NUGET_VERSION); - Checks::check_exit(VCPKG_LINE_INFO, !maybe_nuget_id || nuget, "--nuget-id is only valid with --nuget"); + Checks::check_exit(VCPKG_LINE_INFO, !ret.maybe_nuget_id || ret.nuget, "--nuget-id is only valid with --nuget"); Checks::check_exit( - VCPKG_LINE_INFO, !maybe_nuget_version || nuget, "--nuget-version is only valid with --nuget"); + VCPKG_LINE_INFO, !ret.maybe_nuget_version || ret.nuget, "--nuget-version is only valid with --nuget"); - IFW::Options ifw_options; + ret.ifw_options.maybe_repository_url = maybe_lookup(options.settings, OPTION_IFW_REPOSITORY_URL); + Checks::check_exit(VCPKG_LINE_INFO, + !ret.ifw_options.maybe_repository_url || ret.ifw, + "--ifw-repository-url is only valid with --ifw"); - ifw_options.maybe_repository_url = maybe_lookup(options.settings, OPTION_IFW_REPOSITORY_URL); - Checks::check_exit( - VCPKG_LINE_INFO, !ifw_options.maybe_repository_url || ifw, "--ifw-repository-url is only valid with --ifw"); + ret.ifw_options.maybe_packages_dir_path = maybe_lookup(options.settings, OPTION_IFW_PACKAGES_DIR_PATH); + Checks::check_exit(VCPKG_LINE_INFO, + !ret.ifw_options.maybe_packages_dir_path || ret.ifw, + "--ifw-packages-directory-path is only valid with --ifw"); - ifw_options.maybe_packages_dir_path = maybe_lookup(options.settings, OPTION_IFW_PACKAGES_DIR_PATH); - Checks::check_exit( - VCPKG_LINE_INFO, !ifw_options.maybe_packages_dir_path || ifw, "--ifw-packages-directory-path is only valid with --ifw"); + ret.ifw_options.maybe_repository_dir_path = maybe_lookup(options.settings, OPTION_IFW_REPOSITORY_DIR_PATH); + Checks::check_exit(VCPKG_LINE_INFO, + !ret.ifw_options.maybe_repository_dir_path || ret.ifw, + "--ifw-repository-directory-path is only valid with --ifw"); - ifw_options.maybe_repository_dir_path = maybe_lookup(options.settings, OPTION_IFW_REPOSITORY_DIR_PATH); - Checks::check_exit( - VCPKG_LINE_INFO, !ifw_options.maybe_repository_dir_path || ifw, "--ifw-repository-directory-path is only valid with --ifw"); + ret.ifw_options.maybe_config_file_path = maybe_lookup(options.settings, OPTION_IFW_CONFIG_FILE_PATH); + Checks::check_exit(VCPKG_LINE_INFO, + !ret.ifw_options.maybe_config_file_path || ret.ifw, + "--ifw-configuration-file-path is only valid with --ifw"); - ifw_options.maybe_config_file_path = maybe_lookup(options.settings, OPTION_IFW_CONFIG_FILE_PATH); - Checks::check_exit( - VCPKG_LINE_INFO, !ifw_options.maybe_config_file_path || ifw, "--ifw-configuration-file-path is only valid with --ifw"); + ret.ifw_options.maybe_installer_file_path = maybe_lookup(options.settings, OPTION_IFW_INSTALLER_FILE_PATH); + Checks::check_exit(VCPKG_LINE_INFO, + !ret.ifw_options.maybe_installer_file_path || ret.ifw, + "--ifw-installer-file-path is only valid with --ifw"); + return ret; + } - ifw_options.maybe_installer_file_path = maybe_lookup(options.settings, OPTION_IFW_INSTALLER_FILE_PATH); - Checks::check_exit( - VCPKG_LINE_INFO, !ifw_options.maybe_installer_file_path || ifw, "--ifw-installer-file-path is only valid with --ifw"); + static void print_next_step_info(const fs::path& prefix) + { + const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; + const CMakeVariable cmake_variable = CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); + System::println("\n" + "To use the exported libraries in CMake projects use:" + "\n" + " %s" + "\n", + Strings::to_utf8(cmake_variable.s)); + }; + + static void handle_raw_based_export(Span export_plan, + const ExportArguments& opts, + const std::string& export_id, + const VcpkgPaths& paths) + { + Files::Filesystem& fs = paths.get_filesystem(); + const fs::path export_to_path = paths.root; + const fs::path raw_exported_dir_path = export_to_path / export_id; + std::error_code ec; + fs.remove_all(raw_exported_dir_path, ec); + fs.create_directory(raw_exported_dir_path, ec); + + // execute the plan + for (const ExportPlanAction& action : export_plan) + { + if (action.plan_type != ExportPlanType::ALREADY_BUILT) + { + Checks::unreachable(VCPKG_LINE_INFO); + } + + const std::string display_name = action.spec.to_string(); + System::println("Exporting package %s... ", display_name); + + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + const InstallDir dirs = InstallDir::from_destination_root( + raw_exported_dir_path / "installed", + action.spec.triplet().to_string(), + raw_exported_dir_path / "installed" / "vcpkg" / "info" / (binary_paragraph.fullstem() + ".list")); + + Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); + System::println(System::Color::success, "Exporting package %s... done", display_name); + } + + // Copy files needed for integration + export_integration_files(raw_exported_dir_path, paths); + + if (opts.raw) + { + System::println( + System::Color::success, R"(Files exported at: "%s")", raw_exported_dir_path.generic_string()); + print_next_step_info(export_to_path); + } + + if (opts.nuget) + { + System::println("Creating nuget package... "); + + const std::string nuget_id = opts.maybe_nuget_id.value_or(raw_exported_dir_path.filename().string()); + const std::string nuget_version = opts.maybe_nuget_version.value_or("1.0.0"); + const fs::path output_path = + do_nuget_export(paths, nuget_id, nuget_version, raw_exported_dir_path, export_to_path); + System::println(System::Color::success, "Creating nuget package... done"); + System::println(System::Color::success, "NuGet package exported at: %s", output_path.generic_string()); + + System::println(R"( +With a project open, go to Tools->NuGet Package Manager->Package Manager Console and paste: + Install-Package %s -Source "%s" +)" + "\n", + nuget_id, + output_path.parent_path().u8string()); + } + + if (opts.zip) + { + System::println("Creating zip archive... "); + const fs::path output_path = + do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::ZIP); + System::println(System::Color::success, "Creating zip archive... done"); + System::println(System::Color::success, "Zip archive exported at: %s", output_path.generic_string()); + print_next_step_info("[...]"); + } + + if (opts.seven_zip) + { + System::println("Creating 7zip archive... "); + const fs::path output_path = + do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::SEVEN_ZIP); + System::println(System::Color::success, "Creating 7zip archive... done"); + System::println(System::Color::success, "7zip archive exported at: %s", output_path.generic_string()); + print_next_step_info("[...]"); + } + + if (!opts.raw) + { + fs.remove_all(raw_exported_dir_path, ec); + } + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + const auto opts = handle_export_command_arguments(args, default_triplet); + for (auto&& spec : opts.specs) + Input::check_triplet(spec.triplet(), paths); // create the plan const StatusParagraphs status_db = database_load_check(paths); - std::vector export_plan = Dependencies::create_export_plan(paths, specs, status_db); + std::vector export_plan = Dependencies::create_export_plan(paths, opts.specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty"); std::map> group_by_plan_type; @@ -363,118 +494,21 @@ namespace vcpkg::Commands::Export Checks::exit_fail(VCPKG_LINE_INFO); } - if (dry_run) + if (opts.dry_run) { Checks::exit_success(VCPKG_LINE_INFO); } std::string export_id = create_export_id(); - const auto print_next_step_info = [](const fs::path& prefix) { - const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; - const CMakeVariable cmake_variable = - CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); - System::println("\n" - "To use the exported libraries in CMake projects use:" - "\n" - " %s" - "\n", - Strings::to_utf8(cmake_variable.s)); - }; - - // Main loop - if (raw || nuget || zip || seven_zip) + if (opts.raw || opts.nuget || opts.zip || opts.seven_zip) { - Files::Filesystem& fs = paths.get_filesystem(); - const fs::path export_to_path = paths.root; - const fs::path raw_exported_dir_path = export_to_path / export_id; - std::error_code ec; - fs.remove_all(raw_exported_dir_path, ec); - fs.create_directory(raw_exported_dir_path, ec); - - // execute the plan - for (const ExportPlanAction& action : export_plan) - { - if (action.plan_type != ExportPlanType::ALREADY_BUILT) - { - Checks::unreachable(VCPKG_LINE_INFO); - } - - const std::string display_name = action.spec.to_string(); - System::println("Exporting package %s... ", display_name); - - const BinaryParagraph& binary_paragraph = - action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; - - const InstallDir dirs = InstallDir::from_destination_root( - raw_exported_dir_path / "installed", - action.spec.triplet().to_string(), - raw_exported_dir_path / "installed" / "vcpkg" / "info" / (binary_paragraph.fullstem() + ".list")); - - Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); - System::println(System::Color::success, "Exporting package %s... done", display_name); - } - - // Copy files needed for integration - export_integration_files(raw_exported_dir_path, paths); - - if (raw) - { - System::println( - System::Color::success, R"(Files exported at: "%s")", raw_exported_dir_path.generic_string()); - print_next_step_info(export_to_path); - } - - if (nuget) - { - System::println("Creating nuget package... "); - - const std::string nuget_id = maybe_nuget_id.value_or(raw_exported_dir_path.filename().string()); - const std::string nuget_version = maybe_nuget_version.value_or("1.0.0"); - const fs::path output_path = - do_nuget_export(paths, nuget_id, nuget_version, raw_exported_dir_path, export_to_path); - System::println(System::Color::success, "Creating nuget package... done"); - System::println(System::Color::success, "NuGet package exported at: %s", output_path.generic_string()); - - System::println(R"( -With a project open, go to Tools->NuGet Package Manager->Package Manager Console and paste: - Install-Package %s -Source "%s" -)" - "\n", - nuget_id, - output_path.parent_path().u8string()); - } - - if (zip) - { - System::println("Creating zip archive... "); - const fs::path output_path = - do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::ZIP); - System::println(System::Color::success, "Creating zip archive... done"); - System::println(System::Color::success, "Zip archive exported at: %s", output_path.generic_string()); - print_next_step_info("[...]"); - } - - if (seven_zip) - { - System::println("Creating 7zip archive... "); - const fs::path output_path = - do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::SEVEN_ZIP); - System::println(System::Color::success, "Creating 7zip archive... done"); - System::println(System::Color::success, "7zip archive exported at: %s", output_path.generic_string()); - print_next_step_info("[...]"); - } - - if (!raw) - { - fs.remove_all(raw_exported_dir_path, ec); - } + handle_raw_based_export(export_plan, opts, export_id, paths); } - // IFW loop - if (ifw) + if (opts.ifw) { - IFW::do_export(export_plan, export_id, ifw_options, paths); + IFW::do_export(export_plan, export_id, opts.ifw_options, paths); print_next_step_info("@RootDir@/src/vcpkg"); } diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp index a0692c11e..0dc8a7d31 100644 --- a/toolsrc/src/commands_export_ifw.cpp +++ b/toolsrc/src/commands_export_ifw.cpp @@ -19,39 +19,39 @@ namespace vcpkg::Commands::Export::IFW char mbstr[11]; const size_t bytes_written = std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%d", &date_time); Checks::check_exit(VCPKG_LINE_INFO, - bytes_written == 10, - "Expected 10 bytes to be written, but %u were written", - bytes_written); + bytes_written == 10, + "Expected 10 bytes to be written, but %u were written", + bytes_written); const std::string date_time_as_string(mbstr); return date_time_as_string; } - fs::path get_packages_dir_path(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + fs::path get_packages_dir_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) { - return ifw_options.maybe_packages_dir_path.has_value() ? - fs::path(ifw_options.maybe_packages_dir_path.value_or_exit(VCPKG_LINE_INFO)) - : paths.root / (export_id + "-ifw-packages"); + return ifw_options.maybe_packages_dir_path.has_value() + ? fs::path(ifw_options.maybe_packages_dir_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-packages"); } - fs::path get_repository_dir_path(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + fs::path get_repository_dir_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) { - return ifw_options.maybe_repository_dir_path.has_value() ? - fs::path(ifw_options.maybe_repository_dir_path.value_or_exit(VCPKG_LINE_INFO)) - : paths.root / (export_id + "-ifw-repository"); + return ifw_options.maybe_repository_dir_path.has_value() + ? fs::path(ifw_options.maybe_repository_dir_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-repository"); } - fs::path get_config_file_path(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + fs::path get_config_file_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) { - return ifw_options.maybe_config_file_path.has_value() ? - fs::path(ifw_options.maybe_config_file_path.value_or_exit(VCPKG_LINE_INFO)) - : paths.root / (export_id + "-ifw-configuration.xml"); + return ifw_options.maybe_config_file_path.has_value() + ? fs::path(ifw_options.maybe_config_file_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-configuration.xml"); } - fs::path get_installer_file_path(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + fs::path get_installer_file_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) { - return ifw_options.maybe_installer_file_path.has_value() ? - fs::path(ifw_options.maybe_installer_file_path.value_or_exit(VCPKG_LINE_INFO)) - : paths.root / (export_id + "-ifw-installer.exe"); + return ifw_options.maybe_installer_file_path.has_value() + ? fs::path(ifw_options.maybe_installer_file_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-installer.exe"); } fs::path export_real_package(const fs::path& ifw_packages_dir_path, @@ -82,7 +82,7 @@ namespace vcpkg::Commands::Export::IFW fs.write_contents(package_xml_file_path, Strings::format( -R"###( + R"###( %s %s @@ -91,12 +91,12 @@ R"###( true )###", - action.spec.to_string(), - binary_paragraph.version, - create_release_date(), - action.spec.name(), - action.spec.triplet().canonical_name(), - deps)); + action.spec.to_string(), + binary_paragraph.version, + create_release_date(), + action.spec.name(), + action.spec.triplet().canonical_name(), + deps)); // Return dir path for export package data return ifw_packages_dir_path / @@ -119,15 +119,16 @@ R"###( !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, Strings::format( -R"###( + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( Packages 1.0.0 %s )###", - create_release_date())); + create_release_date())); for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) { @@ -146,7 +147,7 @@ R"###( fs.write_contents(package_xml_file_path, Strings::format( -R"###( + R"###( %s %s @@ -154,10 +155,10 @@ R"###( %s )###", - action.spec.name(), - binary_paragraph.description, - binary_paragraph.version, - create_release_date())); + action.spec.name(), + binary_paragraph.description, + binary_paragraph.version, + create_release_date())); } } @@ -176,15 +177,16 @@ R"###( !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, Strings::format( -R"###( + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( Triplets 1.0.0 %s )###", - create_release_date())); + create_release_date())); for (const std::string& triplet : unique_triplets) { @@ -196,16 +198,17 @@ R"###( !ec, "Could not create directory for package file %s", package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, Strings::format( -R"###( + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( %s 1.0.0 %s )###", - triplet, - create_release_date())); + triplet, + create_release_date())); } } @@ -222,18 +225,19 @@ R"###( "Could not create directory for package file %s", package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, Strings::format( -R"###( + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( Integration 1.0.0 %s )###", - create_release_date())); + create_release_date())); } - void export_config(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + void export_config(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) { std::error_code ec; Files::Filesystem& fs = paths.get_filesystem(); @@ -257,21 +261,22 @@ R"###( %s )###", - ifw_repo_url); + ifw_repo_url); } - fs.write_contents(config_xml_file_path, Strings::format( -R"###( + fs.write_contents(config_xml_file_path, + Strings::format( + R"###( vcpkg 1.0.0 @RootDir@/src/vcpkg%s )###", - formatted_repo_url)); + formatted_repo_url)); } - void do_repository(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + void do_repository(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) { const fs::path& repogen_exe = paths.get_ifw_repogen_exe(); const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); @@ -283,16 +288,13 @@ R"###( Files::Filesystem& fs = paths.get_filesystem(); fs.remove_all(repository_dir, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not remove outdated repository directory %s", - repository_dir.generic_string()); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not remove outdated repository directory %s", repository_dir.generic_string()); - const std::wstring cmd_line = - Strings::wformat(LR"("%s" --packages "%s" "%s" > nul)", - repogen_exe.native(), - packages_dir.native(), - repository_dir.native()); + const std::wstring cmd_line = Strings::wformat(LR"("%s" --packages "%s" "%s" > nul)", + repogen_exe.native(), + packages_dir.native(), + repository_dir.native()); const int exit_code = System::cmd_execute_clean(cmd_line); Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW repository generating failed"); @@ -300,7 +302,7 @@ R"###( System::println(System::Color::success, "Generating repository %s... done.", repository_dir.generic_string()); } - void do_installer(const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + void do_installer(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) { const fs::path& binarycreator_exe = paths.get_ifw_binarycreator_exe(); const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); @@ -315,21 +317,19 @@ R"###( std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); if (!ifw_repo_url.empty()) { - cmd_line = - Strings::wformat(LR"("%s" --online-only --config "%s" --repository "%s" "%s" > nul)", - binarycreator_exe.native(), - config_file.native(), - repository_dir.native(), - installer_file.native()); + cmd_line = Strings::wformat(LR"("%s" --online-only --config "%s" --repository "%s" "%s" > nul)", + binarycreator_exe.native(), + config_file.native(), + repository_dir.native(), + installer_file.native()); } else { - cmd_line = - Strings::wformat(LR"("%s" --config "%s" --packages "%s" "%s" > nul)", - binarycreator_exe.native(), - config_file.native(), - packages_dir.native(), - installer_file.native()); + cmd_line = Strings::wformat(LR"("%s" --config "%s" --packages "%s" "%s" > nul)", + binarycreator_exe.native(), + config_file.native(), + packages_dir.native(), + installer_file.native()); } const int exit_code = System::cmd_execute_clean(cmd_line); @@ -338,7 +338,10 @@ R"###( System::println(System::Color::success, "Generating installer %s... done.", installer_file.generic_string()); } - void do_export(const std::vector &export_plan, const std::string &export_id, const Options &ifw_options, const VcpkgPaths& paths) + void do_export(const std::vector& export_plan, + const std::string& export_id, + const Options& ifw_options, + const VcpkgPaths& paths) { const fs::path ifw_packages_dir_path = get_packages_dir_path(export_id, ifw_options, paths); const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); @@ -350,15 +353,13 @@ R"###( fs.remove_all(ifw_packages_dir_path, ec); Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not remove outdated packages directory %s", - ifw_packages_dir_path.generic_string()); + !ec, + "Could not remove outdated packages directory %s", + ifw_packages_dir_path.generic_string()); fs.create_directory(ifw_packages_dir_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create packages directory %s", - ifw_packages_dir_path.generic_string()); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create packages directory %s", ifw_packages_dir_path.generic_string()); // execute the plan std::map unique_packages; @@ -384,9 +385,9 @@ R"###( // Copy package data const InstallDir dirs = InstallDir::from_destination_root(ifw_package_dir_path, - action.spec.triplet().to_string(), - ifw_package_dir_path / "vcpkg" / "info" / - (binary_paragraph.fullstem() + ".list")); + action.spec.triplet().to_string(), + ifw_package_dir_path / "vcpkg" / "info" / + (binary_paragraph.fullstem() + ".list")); Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); System::println("Exporting package %s... done", display_name); -- cgit v1.2.3 From c98db7541594eadccf6823d4fdde2ff8c53c5fe9 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 4 Oct 2017 16:24:03 -0700 Subject: [vcpkg] Refactor out implication in option parsing for export --- toolsrc/src/commands_export.cpp | 70 +++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 31 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index a24f2eac7..20838f5a5 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -314,37 +314,45 @@ namespace vcpkg::Commands::Export Checks::exit_fail(VCPKG_LINE_INFO); } - ret.maybe_nuget_id = maybe_lookup(options.settings, OPTION_NUGET_ID); - ret.maybe_nuget_version = maybe_lookup(options.settings, OPTION_NUGET_VERSION); - - Checks::check_exit(VCPKG_LINE_INFO, !ret.maybe_nuget_id || ret.nuget, "--nuget-id is only valid with --nuget"); - Checks::check_exit( - VCPKG_LINE_INFO, !ret.maybe_nuget_version || ret.nuget, "--nuget-version is only valid with --nuget"); - - ret.ifw_options.maybe_repository_url = maybe_lookup(options.settings, OPTION_IFW_REPOSITORY_URL); - Checks::check_exit(VCPKG_LINE_INFO, - !ret.ifw_options.maybe_repository_url || ret.ifw, - "--ifw-repository-url is only valid with --ifw"); - - ret.ifw_options.maybe_packages_dir_path = maybe_lookup(options.settings, OPTION_IFW_PACKAGES_DIR_PATH); - Checks::check_exit(VCPKG_LINE_INFO, - !ret.ifw_options.maybe_packages_dir_path || ret.ifw, - "--ifw-packages-directory-path is only valid with --ifw"); - - ret.ifw_options.maybe_repository_dir_path = maybe_lookup(options.settings, OPTION_IFW_REPOSITORY_DIR_PATH); - Checks::check_exit(VCPKG_LINE_INFO, - !ret.ifw_options.maybe_repository_dir_path || ret.ifw, - "--ifw-repository-directory-path is only valid with --ifw"); - - ret.ifw_options.maybe_config_file_path = maybe_lookup(options.settings, OPTION_IFW_CONFIG_FILE_PATH); - Checks::check_exit(VCPKG_LINE_INFO, - !ret.ifw_options.maybe_config_file_path || ret.ifw, - "--ifw-configuration-file-path is only valid with --ifw"); - - ret.ifw_options.maybe_installer_file_path = maybe_lookup(options.settings, OPTION_IFW_INSTALLER_FILE_PATH); - Checks::check_exit(VCPKG_LINE_INFO, - !ret.ifw_options.maybe_installer_file_path || ret.ifw, - "--ifw-installer-file-path is only valid with --ifw"); + struct OptionPair + { + const std::string& name; + Optional& out_opt; + }; + const auto options_implies = + [&](const std::string& main_opt_name, bool main_opt, Span implying_opts) { + if (main_opt) + { + for (auto&& opt : implying_opts) + opt.out_opt = maybe_lookup(options.settings, opt.name); + } + else + { + for (auto&& opt : implying_opts) + Checks::check_exit(VCPKG_LINE_INFO, + !maybe_lookup(options.settings, opt.name), + "%s is only valid with %s", + opt.name, + main_opt_name); + } + }; + + options_implies(OPTION_NUGET, + ret.nuget, + { + {OPTION_NUGET_ID, ret.maybe_nuget_id}, + {OPTION_NUGET_VERSION, ret.maybe_nuget_version}, + }); + + options_implies(OPTION_IFW, + ret.ifw, + { + {OPTION_IFW_REPOSITORY_URL, ret.ifw_options.maybe_repository_url}, + {OPTION_IFW_PACKAGES_DIR_PATH, ret.ifw_options.maybe_packages_dir_path}, + {OPTION_IFW_REPOSITORY_DIR_PATH, ret.ifw_options.maybe_repository_dir_path}, + {OPTION_IFW_CONFIG_FILE_PATH, ret.ifw_options.maybe_config_file_path}, + {OPTION_IFW_INSTALLER_FILE_PATH, ret.ifw_options.maybe_installer_file_path}, + }); return ret; } -- cgit v1.2.3 From 6f763c5ca830c9e461e106c63959a60d33eb5e5b Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Thu, 5 Oct 2017 21:24:32 +0300 Subject: [vcpkg-export-ifw] Maintenance Tool Install maintenance tool and create Start menu shortcuts to manage, update and uninstall packages. --- toolsrc/src/commands_export_ifw.cpp | 69 ++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp index 0dc8a7d31..4ab0ae537 100644 --- a/toolsrc/src/commands_export_ifw.cpp +++ b/toolsrc/src/commands_export_ifw.cpp @@ -270,12 +270,66 @@ namespace vcpkg::Commands::Export::IFW vcpkg 1.0.0 + vcpkg @RootDir@/src/vcpkg%s )###", formatted_repo_url)); } + void export_maintenance_tool(const fs::path& ifw_packages_dir_path, const VcpkgPaths& paths) + { + System::println("Exporting maintenance tool... "); + + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + const fs::path& installerbase_exe = paths.get_ifw_installerbase_exe(); + fs::path tempmaintenancetool = ifw_packages_dir_path / "maintenance" / "data" / "tempmaintenancetool.exe"; + fs.create_directories(tempmaintenancetool.parent_path(), ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + tempmaintenancetool.generic_string()); + fs.copy_file(installerbase_exe, tempmaintenancetool, fs::copy_options::overwrite_existing, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not write package file %s", + tempmaintenancetool.generic_string()); + + fs::path package_xml_file_path = ifw_packages_dir_path / "maintenance" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( + + Maintenance Tool + Maintenance Tool + 1.0.0 + %s + + true + true + true + +)###", +create_release_date())); + const fs::path script_source = paths.root / "scripts" / "ifw" / "maintenance.qs"; + const fs::path script_destination = ifw_packages_dir_path / "maintenance" / "meta" / "maintenance.qs"; + fs.copy_file(script_source, script_destination, fs::copy_options::overwrite_existing, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not write package file %s", + script_destination.generic_string()); + + System::println("Exporting maintenance tool... done"); + } + void do_repository(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) { const fs::path& repogen_exe = paths.get_ifw_repogen_exe(); @@ -343,14 +397,12 @@ namespace vcpkg::Commands::Export::IFW const Options& ifw_options, const VcpkgPaths& paths) { - const fs::path ifw_packages_dir_path = get_packages_dir_path(export_id, ifw_options, paths); - const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); - - System::println("Exporting packages %s... ", ifw_packages_dir_path.generic_string()); - std::error_code ec; Files::Filesystem& fs = paths.get_filesystem(); + // Prepare packages directory + const fs::path ifw_packages_dir_path = get_packages_dir_path(export_id, ifw_options, paths); + fs.remove_all(ifw_packages_dir_path, ec); Checks::check_exit(VCPKG_LINE_INFO, !ec, @@ -361,6 +413,11 @@ namespace vcpkg::Commands::Export::IFW Checks::check_exit( VCPKG_LINE_INFO, !ec, "Could not create packages directory %s", ifw_packages_dir_path.generic_string()); + // Export maintenance tool + export_maintenance_tool(ifw_packages_dir_path, paths); + + System::println("Exporting packages %s... ", ifw_packages_dir_path.generic_string()); + // execute the plan std::map unique_packages; std::set unique_triplets; @@ -395,6 +452,8 @@ namespace vcpkg::Commands::Export::IFW System::println("Exporting packages %s... done", ifw_packages_dir_path.generic_string()); + const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); + System::println("Generating configuration %s...", config_file.generic_string()); // Unique packages -- cgit v1.2.3 From a518ded266259141edd278e3f4025a3ab3211215 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 5 Oct 2017 14:36:29 -0700 Subject: [vcpkg] Check size and don't perform stripping if string is too small. --- toolsrc/src/vcpkg_System.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 4d2e88b73..7a6e7f028 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -179,6 +179,7 @@ namespace vcpkg::System // On Win7, output from powershell calls contain a byte order mark, so we strip it out if it is present static void remove_byte_order_mark(std::wstring* s) { + if (s->size() < 3) return; const wchar_t* a = s->c_str(); // This is the UTF-8 byte-order mark if (a[0] == 0xEF && a[1] == 0xBB && a[2] == 0xBF) -- cgit v1.2.3 From 9b0c2cb2524ef3fa1e8e7e8f2512c32e40eb5815 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 5 Oct 2017 18:07:29 -0700 Subject: [vcpkg] Remove multiple byte order marks --- toolsrc/src/vcpkg_System.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 7a6e7f028..3b4c440d8 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -177,12 +177,11 @@ namespace vcpkg::System } // On Win7, output from powershell calls contain a byte order mark, so we strip it out if it is present - static void remove_byte_order_mark(std::wstring* s) + static void remove_byte_order_marks(std::wstring* s) { - if (s->size() < 3) return; const wchar_t* a = s->c_str(); // This is the UTF-8 byte-order mark - if (a[0] == 0xEF && a[1] == 0xBB && a[2] == 0xBF) + while (s->size() >= 3 && a[0] == 0xEF && a[1] == 0xBB && a[2] == 0xBF) { s->erase(0, 3); } @@ -214,7 +213,7 @@ namespace vcpkg::System const auto ec = _pclose(pipe); Debug::println("_pclose() returned %d", ec); - remove_byte_order_mark(&output); + remove_byte_order_marks(&output); return {ec, Strings::to_utf8(output)}; } -- cgit v1.2.3 From 13385293e62561166c490671630e92458e630b1b Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 5 Oct 2017 18:14:08 -0700 Subject: [vcpkg] Clang-format on commands_export_ifw --- toolsrc/src/commands_export_ifw.cpp | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp index 4ab0ae537..191dbb763 100644 --- a/toolsrc/src/commands_export_ifw.cpp +++ b/toolsrc/src/commands_export_ifw.cpp @@ -288,25 +288,23 @@ namespace vcpkg::Commands::Export::IFW fs::path tempmaintenancetool = ifw_packages_dir_path / "maintenance" / "data" / "tempmaintenancetool.exe"; fs.create_directories(tempmaintenancetool.parent_path(), ec); Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create directory for package file %s", - tempmaintenancetool.generic_string()); + !ec, + "Could not create directory for package file %s", + tempmaintenancetool.generic_string()); fs.copy_file(installerbase_exe, tempmaintenancetool, fs::copy_options::overwrite_existing, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not write package file %s", - tempmaintenancetool.generic_string()); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not write package file %s", tempmaintenancetool.generic_string()); fs::path package_xml_file_path = ifw_packages_dir_path / "maintenance" / "meta" / "package.xml"; fs::path package_xml_dir_path = package_xml_file_path.parent_path(); fs.create_directories(package_xml_dir_path, ec); Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create directory for package file %s", - package_xml_file_path.generic_string()); + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); fs.write_contents(package_xml_file_path, - Strings::format( - R"###( + Strings::format( + R"###( Maintenance Tool Maintenance Tool @@ -318,14 +316,12 @@ namespace vcpkg::Commands::Export::IFW true )###", -create_release_date())); + create_release_date())); const fs::path script_source = paths.root / "scripts" / "ifw" / "maintenance.qs"; const fs::path script_destination = ifw_packages_dir_path / "maintenance" / "meta" / "maintenance.qs"; fs.copy_file(script_source, script_destination, fs::copy_options::overwrite_existing, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not write package file %s", - script_destination.generic_string()); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not write package file %s", script_destination.generic_string()); System::println("Exporting maintenance tool... done"); } -- cgit v1.2.3 From 9a963f7eff1981d4e894ea8b297d092cda60b764 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Oct 2017 13:51:28 -0700 Subject: Overhaul VS selection. Add triplet option to specify VS instance --- toolsrc/src/PostBuildLint.cpp | 2 +- toolsrc/src/VcpkgPaths.cpp | 120 ++++++++++++++++++++++-------------------- toolsrc/src/commands_env.cpp | 4 +- toolsrc/src/vcpkg_Build.cpp | 12 ++++- 4 files changed, 75 insertions(+), 63 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 416d4a636..a0699e15c 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -722,7 +722,7 @@ namespace vcpkg::PostBuildLint const auto& fs = paths.get_filesystem(); // for dumpbin - const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); const fs::path package_dir = paths.package_dir(spec); size_t error_count = 0; diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 9f85992be..f080783c4 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -337,14 +337,14 @@ namespace vcpkg // VS2015 const Optional vs_2015_installation_instance = get_vs2015_installation_instance(); - if (const auto v = vs_2015_installation_instance.get()) + if (const auto vs_2015_root_path = vs_2015_installation_instance.get()) { - const fs::path vs2015_vcvarsall_bat = *v / "VC" / "vcvarsall.bat"; + const fs::path vs2015_vcvarsall_bat = *vs_2015_root_path / "VC" / "vcvarsall.bat"; paths_examined.push_back(vs2015_vcvarsall_bat); if (fs.exists(vs2015_vcvarsall_bat)) { - const fs::path vs2015_dumpbin_exe = *v / "VC" / "bin" / "dumpbin.exe"; + const fs::path vs2015_dumpbin_exe = *vs_2015_root_path / "VC" / "bin" / "dumpbin.exe"; paths_examined.push_back(vs2015_dumpbin_exe); const fs::path vs2015_bin_dir = vs2015_vcvarsall_bat.parent_path() / "bin"; @@ -364,19 +364,25 @@ namespace vcpkg if (fs.exists(vs2015_dumpbin_exe)) { - found_toolsets.push_back( - {vs2015_dumpbin_exe, vs2015_vcvarsall_bat, {}, V_140, supported_architectures}); + found_toolsets.push_back({*vs_2015_root_path, + vs2015_dumpbin_exe, + vs2015_vcvarsall_bat, + {}, + V_140, + supported_architectures}); } } } + const bool v140_is_available = !found_toolsets.empty(); + const std::vector vs2017_installation_instances = get_vs2017_installation_instances(paths); // VS2017 - Optional vs2017_toolset; for (const std::string& instance : vs2017_installation_instances) { - const fs::path vc_dir = fs::path{instance} / "VC"; + const fs::path vs_root_path = fs::path{instance}; + const fs::path vc_dir = vs_root_path / "VC"; // Skip any instances that do not have vcvarsall. const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build"; @@ -415,14 +421,22 @@ namespace vcpkg paths_examined.push_back(dumpbin_path); if (fs.exists(dumpbin_path)) { - vs2017_toolset = Toolset{dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}; + found_toolsets.push_back( + Toolset{vs_root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}); + + if (v140_is_available) + { + found_toolsets.push_back(Toolset{vs_root_path, + dumpbin_path, + vcvarsall_bat, + {L"-vcvars_ver=14.0"}, + V_140, + supported_architectures}); + } + break; } } - if (const auto value = vs2017_toolset.get()) - { - found_toolsets.push_back(*value); - } } if (found_toolsets.empty()) @@ -439,64 +453,54 @@ namespace vcpkg return found_toolsets; } - static std::vector create_vs2017_v140_toolset_instances(const std::vector& vs_toolsets) - { - std::vector vs2017_v140_toolsets; - - // In constrast to v141 and above, there can only be a single instance of v140 (VS2017 vs VS2015). - const auto it = Util::find_if(vs_toolsets, [&](const Toolset& t) { return t.version == V_140; }); - - // If v140 is not available, then VS2017 cant use them. Return empty. - if (it == vs_toolsets.cend()) - { - return vs2017_v140_toolsets; - } - - // If it does exist, then create a matching v140 toolset for each v141 toolset - const Toolset v140_toolset = *it; - for (const Toolset& toolset : vs_toolsets) - { - if (toolset.version != V_141) - { - continue; - } - - Toolset t = Toolset{ - toolset.dumpbin, toolset.vcvarsall, {L"-vcvars_ver=14.0"}, V_140, toolset.supported_architectures}; - vs2017_v140_toolsets.push_back(std::move(t)); - } - - return vs2017_v140_toolsets; - } - - const Toolset& VcpkgPaths::get_toolset(const std::string& toolset_version) const + const Toolset& VcpkgPaths::get_toolset(const Optional& toolset_version, + const Optional& visual_studio_path) const { - const std::wstring& w_toolset_version = Strings::to_utf16(toolset_version); - // Invariant: toolsets are non-empty and sorted with newest at back() const std::vector& vs_toolsets = this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); - if (w_toolset_version.empty()) + std::vector candidates = Util::to_vector_of_const_pointers(vs_toolsets); + const auto tsv = toolset_version.get(); + const auto vsp = visual_studio_path.get(); + + if (tsv && vsp) { - return vs_toolsets.back(); + const std::wstring w_toolset_version = Strings::to_utf16(*tsv); + const fs::path vs_root_path = *vsp; + Util::stable_keep_if(candidates, [&](const Toolset* t) { + return w_toolset_version == t->version && vs_root_path == t->visual_studio_root_path; + }); + Checks::check_exit(VCPKG_LINE_INFO, + !candidates.empty(), + "Could not find Visual Studio instace at %s with %s toolset.", + vs_root_path.generic_string(), + *tsv); + + Checks::check_exit(VCPKG_LINE_INFO, candidates.size() == 1); + return *candidates.back(); } - const auto toolset = - Util::find_if(vs_toolsets, [&](const Toolset& t) { return w_toolset_version == t.version; }); - Checks::check_exit( - VCPKG_LINE_INFO, toolset != vs_toolsets.end(), "Could not find toolset '%s'", toolset_version); + if (tsv) + { + const std::wstring w_toolset_version = Strings::to_utf16(*tsv); + Util::stable_keep_if(candidates, [&](const Toolset* t) { return w_toolset_version == t->version; }); + Checks::check_exit( + VCPKG_LINE_INFO, !candidates.empty(), "Could not find Visual Studio instace with %s toolset.", *tsv); + } - // If v140 is the selected toolset and VS2017 is available, then use VS2017's vcvarsall with the - // -vcvars_ver=14.0 option - const std::vector& vs2017_v140_toolsets = this->toolsets_vs2017_v140.get_lazy( - [&vs_toolsets]() { return create_vs2017_v140_toolset_instances(vs_toolsets); }); - if (w_toolset_version == V_140 && !vs2017_v140_toolsets.empty()) + if (vsp) { - return vs2017_v140_toolsets.back(); + const fs::path vs_root_path = *vsp; + Util::stable_keep_if(candidates, + [&](const Toolset* t) { return vs_root_path == t->visual_studio_root_path; }); + Checks::check_exit(VCPKG_LINE_INFO, + !candidates.empty(), + "Could not find Visual Studio instace at %s.", + vs_root_path.generic_string()); } - return *toolset; + return *candidates.back(); } Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); } diff --git a/toolsrc/src/commands_env.cpp b/toolsrc/src/commands_env.cpp index 073c501f5..6dad3e882 100644 --- a/toolsrc/src/commands_env.cpp +++ b/toolsrc/src/commands_env.cpp @@ -13,8 +13,8 @@ namespace vcpkg::Commands::Env args.check_and_get_optional_command_arguments({}); const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); - System::cmd_execute_clean( - Build::make_build_env_cmd(pre_build_info, paths.get_toolset(pre_build_info.platform_toolset)) + L" && cmd"); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); + System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, toolset) + L" && cmd"); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index 853f84998..9be20629d 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -138,7 +138,7 @@ namespace vcpkg::Build const fs::path ports_cmake_script_path = paths.ports_cmake; const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); - const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); std::string features; @@ -386,7 +386,15 @@ namespace vcpkg::Build if (variable_name == "VCPKG_PLATFORM_TOOLSET") { - pre_build_info.platform_toolset = variable_value; + pre_build_info.platform_toolset = + variable_value.empty() ? nullopt : Optional{variable_value}; + continue; + } + + if (variable_name == "VCPKG_VISUAL_STUDIO_PATH") + { + pre_build_info.visual_studio_path = + variable_value.empty() ? nullopt : Optional{variable_value}; continue; } -- cgit v1.2.3 From 86f3a9dbbdc360db3716b878dd37f2dbec8e983c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Oct 2017 18:12:17 -0700 Subject: Fix Strings::split() to handle delimiters of arbitrary size --- toolsrc/src/vcpkg_Strings.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 21df2c309..bbe6b29cd 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -154,11 +154,13 @@ namespace vcpkg::Strings return output; } + const size_t delimiter_length = delimiter.length(); size_t i = 0; for (size_t pos = s.find(delimiter); pos != std::string::npos; pos = s.find(delimiter, pos)) { output.push_back(s.substr(i, pos - i)); - i = ++pos; + pos += delimiter_length; + i = pos; } // Add the rest of the string after the last delimiter, unless there is nothing after it -- cgit v1.2.3 From f0c23aeb6b238ee0ba2dc272ee4c193f2f777460 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Oct 2017 18:25:34 -0700 Subject: Completely rework Visual Studio detection - Now using vswhere.exe to detect all VS instance (2015 + 2017) - Default version preference order is now: stable, prerelease, legacy - Within each preference weight, the latest one is chosen - findVisualStudioInstallationInstances.ps1 now has a parameter to choose VS instance --- toolsrc/src/VcpkgPaths.cpp | 209 ++++++++++++++++++++++++--------------------- 1 file changed, 113 insertions(+), 96 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index f080783c4..8264ec293 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -302,26 +302,33 @@ namespace vcpkg [this]() { return get_ifw_installerbase_exe().parent_path() / "repogen.exe"; }); } - static std::vector get_vs2017_installation_instances(const VcpkgPaths& paths) + struct VisualStudioInstance + { + fs::path root_path; + std::string version; + std::string release_type; + std::string preference_weight; // Mostly unused, just for verification that order is as intended + + std::string major_version() const { return version.substr(0, 2); } + }; + + static std::vector get_visual_studio_instances(const VcpkgPaths& paths) { const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; const std::wstring cmd = System::create_powershell_script_cmd(script); const System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); - Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect VS 2017 instances"); - return Strings::split(ec_data.output, "\n"); - } + Checks::check_exit( + VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect Visual Studio instances"); - static Optional get_vs2015_installation_instance() - { - const Optional vs2015_cmntools_optional = System::get_environment_variable(L"VS140COMNTOOLS"); - if (const auto v = vs2015_cmntools_optional.get()) + const std::vector instances_as_strings = Strings::split(ec_data.output, "\n"); + std::vector output; + for (const std::string& instance_as_string : instances_as_strings) { - const fs::path vs2015_cmntools = fs::path(*v).parent_path(); // The call to parent_path() is needed because - // the env variable has a trailing backslash - return vs2015_cmntools.parent_path().parent_path(); + const std::vector split = Strings::split(instance_as_string, "::"); + output.push_back({split.at(3), split.at(2), split.at(1), split.at(0)}); } - return nullopt; + return output; } static std::vector find_toolset_instances(const VcpkgPaths& paths) @@ -335,108 +342,118 @@ namespace vcpkg std::vector found_toolsets; - // VS2015 - const Optional vs_2015_installation_instance = get_vs2015_installation_instance(); - if (const auto vs_2015_root_path = vs_2015_installation_instance.get()) - { - const fs::path vs2015_vcvarsall_bat = *vs_2015_root_path / "VC" / "vcvarsall.bat"; + const std::vector vs_instances = get_visual_studio_instances(paths); + const bool v140_is_available = Util::find_if(vs_instances, [&](const VisualStudioInstance& vs_instance) { + return vs_instance.major_version() == "14"; + }) != vs_instances.cend(); - paths_examined.push_back(vs2015_vcvarsall_bat); - if (fs.exists(vs2015_vcvarsall_bat)) + // VS2017 + for (const VisualStudioInstance& vs_instance : vs_instances) + { + const std::string major_version = vs_instance.major_version(); + if (major_version == "15") { - const fs::path vs2015_dumpbin_exe = *vs_2015_root_path / "VC" / "bin" / "dumpbin.exe"; - paths_examined.push_back(vs2015_dumpbin_exe); + const fs::path vc_dir = vs_instance.root_path / "VC"; + + // Skip any instances that do not have vcvarsall. + const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build"; + const fs::path vcvarsall_bat = vcvarsall_dir / "vcvarsall.bat"; + paths_examined.push_back(vcvarsall_bat); + if (!fs.exists(vcvarsall_bat)) continue; - const fs::path vs2015_bin_dir = vs2015_vcvarsall_bat.parent_path() / "bin"; + // Get all supported architectures std::vector supported_architectures; - if (fs.exists(vs2015_bin_dir / "vcvars32.bat")) + if (fs.exists(vcvarsall_dir / "vcvars32.bat")) supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); - if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat")) - supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); - if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) + if (fs.exists(vcvarsall_dir / "vcvars64.bat")) + supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); - if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) + if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); - if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) + if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); - if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) + if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); - if (fs.exists(vs2015_dumpbin_exe)) + // Locate the "best" MSVC toolchain version + const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; + std::vector msvc_subdirectories = fs.get_files_non_recursive(msvc_path); + Util::unstable_keep_if(msvc_subdirectories, + [&fs](const fs::path& path) { return fs.is_directory(path); }); + + // Sort them so that latest comes first + std::sort( + msvc_subdirectories.begin(), + msvc_subdirectories.end(), + [](const fs::path& left, const fs::path& right) { return left.filename() > right.filename(); }); + + for (const fs::path& subdir : msvc_subdirectories) { - found_toolsets.push_back({*vs_2015_root_path, - vs2015_dumpbin_exe, - vs2015_vcvarsall_bat, - {}, - V_140, - supported_architectures}); + const fs::path dumpbin_path = subdir / "bin" / "HostX86" / "x86" / "dumpbin.exe"; + paths_examined.push_back(dumpbin_path); + if (fs.exists(dumpbin_path)) + { + found_toolsets.push_back(Toolset{ + vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}); + + if (v140_is_available) + { + found_toolsets.push_back(Toolset{vs_instance.root_path, + dumpbin_path, + vcvarsall_bat, + {L"-vcvars_ver=14.0"}, + V_140, + supported_architectures}); + } + + break; + } } - } - } - const bool v140_is_available = !found_toolsets.empty(); - - const std::vector vs2017_installation_instances = get_vs2017_installation_instances(paths); + continue; + } - // VS2017 - for (const std::string& instance : vs2017_installation_instances) - { - const fs::path vs_root_path = fs::path{instance}; - const fs::path vc_dir = vs_root_path / "VC"; - - // Skip any instances that do not have vcvarsall. - const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build"; - const fs::path vcvarsall_bat = vcvarsall_dir / "vcvarsall.bat"; - paths_examined.push_back(vcvarsall_bat); - if (!fs.exists(vcvarsall_bat)) continue; - - // Get all supported architectures - std::vector supported_architectures; - if (fs.exists(vcvarsall_dir / "vcvars32.bat")) - supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvars64.bat")) - supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) - supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) - supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) - supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) - supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); - - // Locate the "best" MSVC toolchain version - const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; - std::vector msvc_subdirectories = fs.get_files_non_recursive(msvc_path); - Util::unstable_keep_if(msvc_subdirectories, [&fs](const fs::path& path) { return fs.is_directory(path); }); - - // Sort them so that latest comes first - std::sort(msvc_subdirectories.begin(), - msvc_subdirectories.end(), - [](const fs::path& left, const fs::path& right) { return left.filename() > right.filename(); }); - - for (const fs::path& subdir : msvc_subdirectories) + if (major_version == "14") { - const fs::path dumpbin_path = subdir / "bin" / "HostX86" / "x86" / "dumpbin.exe"; - paths_examined.push_back(dumpbin_path); - if (fs.exists(dumpbin_path)) - { - found_toolsets.push_back( - Toolset{vs_root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}); + const fs::path vcvarsall_bat = vs_instance.root_path / "VC" / "vcvarsall.bat"; - if (v140_is_available) + paths_examined.push_back(vcvarsall_bat); + if (fs.exists(vcvarsall_bat)) + { + const fs::path vs2015_dumpbin_exe = vs_instance.root_path / "VC" / "bin" / "dumpbin.exe"; + paths_examined.push_back(vs2015_dumpbin_exe); + + const fs::path vs2015_bin_dir = vcvarsall_bat.parent_path() / "bin"; + std::vector supported_architectures; + if (fs.exists(vs2015_bin_dir / "vcvars32.bat")) + supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); + if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat")) + supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); + if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) + supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) + supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); + if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) + supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) + supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + + if (fs.exists(vs2015_dumpbin_exe)) { - found_toolsets.push_back(Toolset{vs_root_path, - dumpbin_path, - vcvarsall_bat, - {L"-vcvars_ver=14.0"}, - V_140, - supported_architectures}); + found_toolsets.push_back({vs_instance.root_path, + vs2015_dumpbin_exe, + vcvarsall_bat, + {}, + V_140, + supported_architectures}); } - - break; } + + continue; } + + Checks::exit_with_message(VCPKG_LINE_INFO, "Expected major version 14 or 15 but got: %s", major_version); } if (found_toolsets.empty()) @@ -460,7 +477,7 @@ namespace vcpkg const std::vector& vs_toolsets = this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); - std::vector candidates = Util::to_vector_of_const_pointers(vs_toolsets); + std::vector candidates = Util::element_pointers(vs_toolsets); const auto tsv = toolset_version.get(); const auto vsp = visual_studio_path.get(); @@ -500,7 +517,7 @@ namespace vcpkg vs_root_path.generic_string()); } - return *candidates.back(); + return *candidates.front(); } Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); } -- cgit v1.2.3 From 540046b564f95d262f5e4d2a4f988485e6469742 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 5 Oct 2017 22:16:43 -0700 Subject: [vcpkg] Remove assert that vswhere returns only 14 or 15. --- toolsrc/src/VcpkgPaths.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 8264ec293..d84a2d281 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -452,8 +452,6 @@ namespace vcpkg continue; } - - Checks::exit_with_message(VCPKG_LINE_INFO, "Expected major version 14 or 15 but got: %s", major_version); } if (found_toolsets.empty()) -- cgit v1.2.3 From 3a6e34804a878ce0c3f74b208f9a5c0bdc75ec7b Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Oct 2017 22:46:55 -0700 Subject: Remove stray comment --- toolsrc/src/VcpkgPaths.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index d84a2d281..08f21df34 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -347,7 +347,6 @@ namespace vcpkg return vs_instance.major_version() == "14"; }) != vs_instances.cend(); - // VS2017 for (const VisualStudioInstance& vs_instance : vs_instances) { const std::string major_version = vs_instance.major_version(); -- cgit v1.2.3 From 03c17e20268bb8bdbfec8710be80fd1310d38dff Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Oct 2017 22:47:45 -0700 Subject: Remove unneeded "continue" --- toolsrc/src/VcpkgPaths.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 08f21df34..e3e83af30 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -448,8 +448,6 @@ namespace vcpkg supported_architectures}); } } - - continue; } } -- cgit v1.2.3 From cd4142d3cac144c6f4e558cdfe8403e1987ff833 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 6 Oct 2017 14:06:02 -0700 Subject: Bump version of nuget to 4.3.0 (was 4.1.0) --- toolsrc/src/VcpkgPaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index e3e83af30..d14002e47 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -130,10 +130,10 @@ namespace vcpkg fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array EXPECTED_VERSION = {4, 1, 0}; + static constexpr std::array EXPECTED_VERSION = {4, 3, 0}; static const std::wstring VERSION_CHECK_ARGUMENTS = Strings::WEMPTY; - const fs::path downloaded_copy = downloads_folder / "nuget-4.1.0" / "nuget.exe"; + const fs::path downloaded_copy = downloads_folder / "nuget-4.3.0" / "nuget.exe"; const std::vector from_path = Files::find_from_PATH(L"nuget"); std::vector candidate_paths; -- cgit v1.2.3 From 7cd465b8897bd9487db6d990e58dcac472b3d4d6 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 11 Oct 2017 17:56:01 -0700 Subject: `vcpkg install` Print summary when using the --keep-going flag --- toolsrc/src/commands_install.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index d815332fe..4411dd3ae 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -556,6 +556,7 @@ namespace vcpkg::Commands::Install const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); const KeepGoing keep_going = to_keep_going(options.find(OPTION_KEEP_GOING) != options.cend()); + const PrintSummary print_summary = to_print_summary(keep_going == KeepGoing::YES); // create the plan StatusParagraphs status_db = database_load_check(paths); @@ -606,7 +607,7 @@ namespace vcpkg::Commands::Install Checks::exit_success(VCPKG_LINE_INFO); } - perform_and_exit(action_plan, install_plan_options, keep_going, PrintSummary::NO, paths, status_db); + perform_and_exit(action_plan, install_plan_options, keep_going, print_summary, paths, status_db); Checks::exit_success(VCPKG_LINE_INFO); } -- cgit v1.2.3 From 00d89dbd66a658174233920d6be2a85f282ef29f Mon Sep 17 00:00:00 2001 From: Mikhail Paulyshka Date: Sun, 24 Sep 2017 16:01:37 +0300 Subject: vcpkg: initial ARM64 support --- toolsrc/src/PostBuildLint.cpp | 1 + toolsrc/src/VcpkgPaths.cpp | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index a0699e15c..6d9a0da73 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -361,6 +361,7 @@ namespace vcpkg::PostBuildLint case MachineType::I386: return "x86"; case MachineType::ARM: case MachineType::ARMNT: return "arm"; + case MachineType::ARM64: return "arm64"; default: return "Machine Type Code = " + std::to_string(static_cast(machine_type)); } } diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index d14002e47..dac9e40e7 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -370,10 +370,14 @@ namespace vcpkg supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_arm64.bat")) + supported_architectures.push_back({L"x86_arm64", CPU::X86, CPU::ARM64}); if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm64.bat")) + supported_architectures.push_back({L"amd64_arm64", CPU::X64, CPU::ARM64}); // Locate the "best" MSVC toolchain version const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; -- cgit v1.2.3 From dcfb9d45c13ba3adc22a47d62642f6acd2ee239b Mon Sep 17 00:00:00 2001 From: jasjuang Date: Thu, 12 Oct 2017 04:09:52 -0700 Subject: add NVCUDASAMPLES_ROOT to whitelist --- toolsrc/src/vcpkg_System.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 3b4c440d8..5293638e3 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -106,6 +106,8 @@ namespace vcpkg::System L"HTTPS_PROXY", // Enables find_package(CUDA) in CMake L"CUDA_PATH", + // Environmental variable generated automatically by CUDA after installation + L"NVCUDASAMPLES_ROOT", }; // Flush stdout before launching external process -- cgit v1.2.3 From 9e19c24d2911ff1ef648aeed0c596e3987eafebf Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 12 Oct 2017 14:03:01 -0700 Subject: `vcpkg autocomplete` More work on autocomplete --- toolsrc/src/commands_autocomplete.cpp | 83 +++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 22 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_autocomplete.cpp b/toolsrc/src/commands_autocomplete.cpp index 3963f904b..abad19df7 100644 --- a/toolsrc/src/commands_autocomplete.cpp +++ b/toolsrc/src/commands_autocomplete.cpp @@ -1,9 +1,8 @@ #include "pch.h" #include "Paragraphs.h" -#include "SortedVector.h" +#include "metrics.h" #include "vcpkg_Commands.h" -#include "vcpkg_Maps.h" #include "vcpkg_System.h" #include "vcpkglib.h" @@ -35,7 +34,7 @@ namespace vcpkg::Commands::Autocomplete for (const auto& installed_package : installed_packages) { - auto sp = installed_package->package.displayname(); + const auto sp = installed_package->package.displayname(); if (istartswith(sp, start_with)) { @@ -47,33 +46,73 @@ namespace vcpkg::Commands::Autocomplete void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string EXAMPLE = - Strings::format("The argument should be a command line to autocomplete.\n%s", - Commands::Help::create_example_string("autocomplete install z")); + Metrics::g_metrics.lock()->set_send_metrics(false); - args.check_min_arg_count(1, EXAMPLE); - args.check_max_arg_count(2, EXAMPLE); - args.check_and_get_optional_command_arguments({}); + if (args.command_arguments.size() != 1) + { + Checks::exit_success(VCPKG_LINE_INFO); + } - const std::string requested_command = args.command_arguments.at(0); - const std::string start_with = - args.command_arguments.size() > 1 ? args.command_arguments.at(1) : Strings::EMPTY; - std::vector results; - if (requested_command == "install") + const std::string to_autocomplete = args.command_arguments.at(0); + const std::vector tokens = Strings::split(to_autocomplete, " "); + if (tokens.size() == 1) { - auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); - auto& source_paragraphs = sources_and_errors.paragraphs; + const std::string requested_command = tokens[0]; + + std::vector valid_commands = {"install", + "search", + "remove", + "list", + "update", + "hash", + "help", + "integrate", + "export", + "edit", + "create", + "owns", + "cache", + "version", + "contact"}; + + Util::unstable_keep_if(valid_commands, [&](const std::string& s) { + return Strings::case_insensitive_ascii_starts_with(s, requested_command); + }); - results = autocomplete_install(source_paragraphs, start_with); + if (valid_commands.size() == 1) + { + System::println(valid_commands[0] + " "); + } + else + { + System::println(Strings::join("\n", valid_commands)); + } + + Checks::exit_success(VCPKG_LINE_INFO); } - else if (requested_command == "remove") + + if (tokens.size() == 2) { - const StatusParagraphs status_db = database_load_check(paths); - std::vector installed_packages = get_installed_ports(status_db); - results = autocomplete_remove(installed_packages, start_with); + const std::string requested_command = tokens[0]; + const std::string start_with = tokens[1]; + std::vector results; + if (requested_command == "install") + { + auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + auto& source_paragraphs = sources_and_errors.paragraphs; + + results = autocomplete_install(source_paragraphs, start_with); + } + else if (requested_command == "remove") + { + const StatusParagraphs status_db = database_load_check(paths); + const std::vector installed_packages = get_installed_ports(status_db); + results = autocomplete_remove(installed_packages, start_with); + } + + System::println(Strings::join("\n", results)); } - System::println(Strings::join(" ", results)); Checks::exit_success(VCPKG_LINE_INFO); } } -- cgit v1.2.3 From 37fba399ef5c57573a1218206cb2c55f5f6bc13c Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Fri, 13 Oct 2017 05:33:32 +0300 Subject: [vcpkg-export-ifw] Safe description QtIFW support rich text for component description, bu some port has not safe ampersand symbol in description text (for example 'openexr' package), that should be replaced to '&' symbol name --- toolsrc/src/commands_export_ifw.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp index 191dbb763..c001a93ed 100644 --- a/toolsrc/src/commands_export_ifw.cpp +++ b/toolsrc/src/commands_export_ifw.cpp @@ -26,6 +26,14 @@ namespace vcpkg::Commands::Export::IFW return date_time_as_string; } + std::string safe_rich_from_plain_text(const std::string& text) + { + // match standalone ampersand, no HTML number or name + std::regex standalone_ampersand(R"###(&(?!(#[0-9]+|\w+);))###"); + + return std::regex_replace(text, standalone_ampersand, "&"); + } + fs::path get_packages_dir_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) { return ifw_options.maybe_packages_dir_path.has_value() @@ -156,7 +164,7 @@ namespace vcpkg::Commands::Export::IFW )###", action.spec.name(), - binary_paragraph.description, + safe_rich_from_plain_text(binary_paragraph.description), binary_paragraph.version, create_release_date())); } -- cgit v1.2.3 From f6a0d78c82789af482eb3c885cbbb73aba7dfb38 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 13 Oct 2017 14:54:31 -0700 Subject: `autocomplete` Rework command, fixing a lot of corner cases in the process --- toolsrc/src/commands_autocomplete.cpp | 66 ++++++++++++++++------------------- 1 file changed, 30 insertions(+), 36 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_autocomplete.cpp b/toolsrc/src/commands_autocomplete.cpp index abad19df7..478a3c478 100644 --- a/toolsrc/src/commands_autocomplete.cpp +++ b/toolsrc/src/commands_autocomplete.cpp @@ -5,6 +5,7 @@ #include "vcpkg_Commands.h" #include "vcpkg_System.h" #include "vcpkglib.h" +#include namespace vcpkg::Commands::Autocomplete { @@ -44,20 +45,26 @@ namespace vcpkg::Commands::Autocomplete return results; } + [[noreturn]] static void output_sorted_results_and_exit(const LineInfo& line_info, + std::vector&& results) + { + const SortedVector sorted_results(results); + System::println(Strings::join("\n", sorted_results)); + Checks::exit_success(line_info); + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { Metrics::g_metrics.lock()->set_send_metrics(false); + const std::string to_autocomplete = Strings::join(" ", args.command_arguments); + const std::vector tokens = Strings::split(to_autocomplete, " "); - if (args.command_arguments.size() != 1) - { - Checks::exit_success(VCPKG_LINE_INFO); - } + std::smatch match; - const std::string to_autocomplete = args.command_arguments.at(0); - const std::vector tokens = Strings::split(to_autocomplete, " "); - if (tokens.size() == 1) + // Handles vcpkg + if (std::regex_match(to_autocomplete, match, std::regex{R"###(^(\S*)$)###"})) { - const std::string requested_command = tokens[0]; + const std::string requested_command = match[1].str(); std::vector valid_commands = {"install", "search", @@ -79,38 +86,25 @@ namespace vcpkg::Commands::Autocomplete return Strings::case_insensitive_ascii_starts_with(s, requested_command); }); - if (valid_commands.size() == 1) - { - System::println(valid_commands[0] + " "); - } - else - { - System::println(Strings::join("\n", valid_commands)); - } - - Checks::exit_success(VCPKG_LINE_INFO); + output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(valid_commands)); } - if (tokens.size() == 2) + // Handles vcpkg install + if (std::regex_match(to_autocomplete, match, std::regex{R"###(^install.* (\S*)$)###"})) { - const std::string requested_command = tokens[0]; - const std::string start_with = tokens[1]; - std::vector results; - if (requested_command == "install") - { - auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); - auto& source_paragraphs = sources_and_errors.paragraphs; - - results = autocomplete_install(source_paragraphs, start_with); - } - else if (requested_command == "remove") - { - const StatusParagraphs status_db = database_load_check(paths); - const std::vector installed_packages = get_installed_ports(status_db); - results = autocomplete_remove(installed_packages, start_with); - } + const std::string start_with = match[1].str(); + auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + auto& source_paragraphs = sources_and_errors.paragraphs; + output_sorted_results_and_exit(VCPKG_LINE_INFO, autocomplete_install(source_paragraphs, start_with)); + } - System::println(Strings::join("\n", results)); + // Handles vcpkg remove + if (std::regex_match(to_autocomplete, match, std::regex{R"###(^remove.* (\S*)$)###"})) + { + const std::string start_with = match[1].str(); + const StatusParagraphs status_db = database_load_check(paths); + const std::vector installed_packages = get_installed_ports(status_db); + output_sorted_results_and_exit(VCPKG_LINE_INFO, autocomplete_remove(installed_packages, start_with)); } Checks::exit_success(VCPKG_LINE_INFO); -- cgit v1.2.3 From d46a992b3cbbbf3479ad3906aecd07e73174cd40 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 13 Oct 2017 15:17:11 -0700 Subject: Don't do function "aliasing" --- toolsrc/src/commands_autocomplete.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands_autocomplete.cpp b/toolsrc/src/commands_autocomplete.cpp index 478a3c478..6ded74f9b 100644 --- a/toolsrc/src/commands_autocomplete.cpp +++ b/toolsrc/src/commands_autocomplete.cpp @@ -13,13 +13,12 @@ namespace vcpkg::Commands::Autocomplete const std::vector>& source_paragraphs, const std::string& start_with) { std::vector results; - const auto& istartswith = Strings::case_insensitive_ascii_starts_with; for (const auto& source_control_file : source_paragraphs) { auto&& sp = *source_control_file->core_paragraph; - if (istartswith(sp.name, start_with)) + if (Strings::case_insensitive_ascii_starts_with(sp.name, start_with)) { results.push_back(sp.name); } @@ -31,13 +30,12 @@ namespace vcpkg::Commands::Autocomplete const std::string& start_with) { std::vector results; - const auto& istartswith = Strings::case_insensitive_ascii_starts_with; for (const auto& installed_package : installed_packages) { const auto sp = installed_package->package.displayname(); - if (istartswith(sp, start_with)) + if (Strings::case_insensitive_ascii_starts_with(sp, start_with)) { results.push_back(sp); } -- cgit v1.2.3 From e17de99599a2f114faab1bb4821fbaad4d266c95 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 13 Oct 2017 18:37:41 -0700 Subject: [vcpkg] Re-layout all files using new organization scheme. All filenames and directories are lowercase. Use dots for namespace separation. --- toolsrc/src/BinaryParagraph.cpp | 123 ---- toolsrc/src/LineInfo.cpp | 9 - toolsrc/src/MachineType.cpp | 41 -- toolsrc/src/PackageSpec.cpp | 175 ------ toolsrc/src/PackageSpecParseResult.cpp | 20 - toolsrc/src/ParagraphParseResult.cpp | 34 -- toolsrc/src/Paragraphs.cpp | 304 --------- toolsrc/src/PostBuildLint.cpp | 846 -------------------------- toolsrc/src/PostBuildLint_BuildType.cpp | 70 --- toolsrc/src/SourceParagraph.cpp | 262 -------- toolsrc/src/StatusParagraph.cpp | 86 --- toolsrc/src/StatusParagraphs.cpp | 90 --- toolsrc/src/VcpkgCmdArguments.cpp | 283 --------- toolsrc/src/VcpkgPaths.cpp | 519 ---------------- toolsrc/src/VersionT.cpp | 19 - toolsrc/src/coff_file_reader.cpp | 308 ---------- toolsrc/src/commands_autocomplete.cpp | 79 --- toolsrc/src/commands_available_commands.cpp | 50 -- toolsrc/src/commands_build.cpp | 102 ---- toolsrc/src/commands_build_external.cpp | 21 - toolsrc/src/commands_cache.cpp | 68 --- toolsrc/src/commands_ci.cpp | 60 -- toolsrc/src/commands_contact.cpp | 22 - toolsrc/src/commands_create.cpp | 38 -- toolsrc/src/commands_depends.cpp | 55 -- toolsrc/src/commands_edit.cpp | 86 --- toolsrc/src/commands_env.cpp | 21 - toolsrc/src/commands_export.cpp | 526 ---------------- toolsrc/src/commands_export_ifw.cpp | 481 --------------- toolsrc/src/commands_hash.cpp | 55 -- toolsrc/src/commands_help.cpp | 131 ---- toolsrc/src/commands_import.cpp | 119 ---- toolsrc/src/commands_install.cpp | 613 ------------------- toolsrc/src/commands_integrate.cpp | 342 ----------- toolsrc/src/commands_list.cpp | 74 --- toolsrc/src/commands_owns.cpp | 37 -- toolsrc/src/commands_portsdiff.cpp | 181 ------ toolsrc/src/commands_remove.cpp | 249 -------- toolsrc/src/commands_search.cpp | 145 ----- toolsrc/src/commands_update.cpp | 73 --- toolsrc/src/commands_version.cpp | 67 -- toolsrc/src/metrics.cpp | 395 ------------ toolsrc/src/test_install_plan.cpp | 486 --------------- toolsrc/src/tests.arguments.cpp | 58 ++ toolsrc/src/tests.dependencies.cpp | 110 ++++ toolsrc/src/tests.installplan.cpp | 487 +++++++++++++++ toolsrc/src/tests.packagespec.cpp | 120 ++++ toolsrc/src/tests.paragraph.cpp | 389 ++++++++++++ toolsrc/src/tests_arguments.cpp | 58 -- toolsrc/src/tests_dependencies.cpp | 110 ---- toolsrc/src/tests_package_spec.cpp | 119 ---- toolsrc/src/tests_paragraph.cpp | 388 ------------ toolsrc/src/triplet.cpp | 55 -- toolsrc/src/vcpkg.cpp | 56 +- toolsrc/src/vcpkg/base/checks.cpp | 81 +++ toolsrc/src/vcpkg/base/chrono.cpp | 61 ++ toolsrc/src/vcpkg/base/cofffilereader.cpp | 308 ++++++++++ toolsrc/src/vcpkg/base/enums.cpp | 14 + toolsrc/src/vcpkg/base/files.cpp | 208 +++++++ toolsrc/src/vcpkg/base/lineinfo.cpp | 9 + toolsrc/src/vcpkg/base/machinetype.cpp | 41 ++ toolsrc/src/vcpkg/base/strings.cpp | 174 ++++++ toolsrc/src/vcpkg/base/system.cpp | 350 +++++++++++ toolsrc/src/vcpkg/binaryparagraph.cpp | 123 ++++ toolsrc/src/vcpkg/build.cpp | 533 ++++++++++++++++ toolsrc/src/vcpkg/commands.autocomplete.cpp | 78 +++ toolsrc/src/vcpkg/commands.buildexternal.cpp | 23 + toolsrc/src/vcpkg/commands.cache.cpp | 69 +++ toolsrc/src/vcpkg/commands.ci.cpp | 62 ++ toolsrc/src/vcpkg/commands.contact.cpp | 22 + toolsrc/src/vcpkg/commands.cpp | 56 ++ toolsrc/src/vcpkg/commands.create.cpp | 39 ++ toolsrc/src/vcpkg/commands.dependinfo.cpp | 56 ++ toolsrc/src/vcpkg/commands.edit.cpp | 87 +++ toolsrc/src/vcpkg/commands.env.cpp | 22 + toolsrc/src/vcpkg/commands.exportifw.cpp | 482 +++++++++++++++ toolsrc/src/vcpkg/commands.hash.cpp | 55 ++ toolsrc/src/vcpkg/commands.import.cpp | 120 ++++ toolsrc/src/vcpkg/commands.integrate.cpp | 342 +++++++++++ toolsrc/src/vcpkg/commands.list.cpp | 75 +++ toolsrc/src/vcpkg/commands.owns.cpp | 38 ++ toolsrc/src/vcpkg/commands.portsdiff.cpp | 182 ++++++ toolsrc/src/vcpkg/commands.search.cpp | 146 +++++ toolsrc/src/vcpkg/commands.version.cpp | 67 ++ toolsrc/src/vcpkg/dependencies.cpp | 669 ++++++++++++++++++++ toolsrc/src/vcpkg/export.cpp | 528 ++++++++++++++++ toolsrc/src/vcpkg/globalstate.cpp | 13 + toolsrc/src/vcpkg/help.cpp | 131 ++++ toolsrc/src/vcpkg/input.cpp | 55 ++ toolsrc/src/vcpkg/install.cpp | 615 +++++++++++++++++++ toolsrc/src/vcpkg/metrics.cpp | 398 ++++++++++++ toolsrc/src/vcpkg/packagespec.cpp | 175 ++++++ toolsrc/src/vcpkg/packagespecparseresult.cpp | 21 + toolsrc/src/vcpkg/paragraphparseresult.cpp | 34 ++ toolsrc/src/vcpkg/paragraphs.cpp | 304 +++++++++ toolsrc/src/vcpkg/parse.cpp | 81 +++ toolsrc/src/vcpkg/postbuildlint.buildtype.cpp | 70 +++ toolsrc/src/vcpkg/postbuildlint.cpp | 846 ++++++++++++++++++++++++++ toolsrc/src/vcpkg/remove.cpp | 251 ++++++++ toolsrc/src/vcpkg/sourceparagraph.cpp | 264 ++++++++ toolsrc/src/vcpkg/statusparagraph.cpp | 86 +++ toolsrc/src/vcpkg/statusparagraphs.cpp | 89 +++ toolsrc/src/vcpkg/triplet.cpp | 55 ++ toolsrc/src/vcpkg/update.cpp | 75 +++ toolsrc/src/vcpkg/vcpkgcmdarguments.cpp | 284 +++++++++ toolsrc/src/vcpkg/vcpkglib.cpp | 247 ++++++++ toolsrc/src/vcpkg/vcpkgpaths.cpp | 519 ++++++++++++++++ toolsrc/src/vcpkg/versiont.cpp | 19 + toolsrc/src/vcpkg_Build.cpp | 406 ------------ toolsrc/src/vcpkg_Build_BuildPolicy.cpp | 40 -- toolsrc/src/vcpkg_Checks.cpp | 81 --- toolsrc/src/vcpkg_Chrono.cpp | 61 -- toolsrc/src/vcpkg_Dependencies.cpp | 669 -------------------- toolsrc/src/vcpkg_Enums.cpp | 14 - toolsrc/src/vcpkg_Files.cpp | 209 ------- toolsrc/src/vcpkg_GlobalState.cpp | 13 - toolsrc/src/vcpkg_Input.cpp | 54 -- toolsrc/src/vcpkg_Parse.cpp | 80 --- toolsrc/src/vcpkg_Strings.cpp | 174 ------ toolsrc/src/vcpkg_System.cpp | 349 ----------- toolsrc/src/vcpkg_metrics_uploader.cpp | 18 - toolsrc/src/vcpkglib.cpp | 247 -------- toolsrc/src/vcpkgmetricsuploader.cpp | 20 + 123 files changed, 10973 insertions(+), 10929 deletions(-) delete mode 100644 toolsrc/src/BinaryParagraph.cpp delete mode 100644 toolsrc/src/LineInfo.cpp delete mode 100644 toolsrc/src/MachineType.cpp delete mode 100644 toolsrc/src/PackageSpec.cpp delete mode 100644 toolsrc/src/PackageSpecParseResult.cpp delete mode 100644 toolsrc/src/ParagraphParseResult.cpp delete mode 100644 toolsrc/src/Paragraphs.cpp delete mode 100644 toolsrc/src/PostBuildLint.cpp delete mode 100644 toolsrc/src/PostBuildLint_BuildType.cpp delete mode 100644 toolsrc/src/SourceParagraph.cpp delete mode 100644 toolsrc/src/StatusParagraph.cpp delete mode 100644 toolsrc/src/StatusParagraphs.cpp delete mode 100644 toolsrc/src/VcpkgCmdArguments.cpp delete mode 100644 toolsrc/src/VcpkgPaths.cpp delete mode 100644 toolsrc/src/VersionT.cpp delete mode 100644 toolsrc/src/coff_file_reader.cpp delete mode 100644 toolsrc/src/commands_autocomplete.cpp delete mode 100644 toolsrc/src/commands_available_commands.cpp delete mode 100644 toolsrc/src/commands_build.cpp delete mode 100644 toolsrc/src/commands_build_external.cpp delete mode 100644 toolsrc/src/commands_cache.cpp delete mode 100644 toolsrc/src/commands_ci.cpp delete mode 100644 toolsrc/src/commands_contact.cpp delete mode 100644 toolsrc/src/commands_create.cpp delete mode 100644 toolsrc/src/commands_depends.cpp delete mode 100644 toolsrc/src/commands_edit.cpp delete mode 100644 toolsrc/src/commands_env.cpp delete mode 100644 toolsrc/src/commands_export.cpp delete mode 100644 toolsrc/src/commands_export_ifw.cpp delete mode 100644 toolsrc/src/commands_hash.cpp delete mode 100644 toolsrc/src/commands_help.cpp delete mode 100644 toolsrc/src/commands_import.cpp delete mode 100644 toolsrc/src/commands_install.cpp delete mode 100644 toolsrc/src/commands_integrate.cpp delete mode 100644 toolsrc/src/commands_list.cpp delete mode 100644 toolsrc/src/commands_owns.cpp delete mode 100644 toolsrc/src/commands_portsdiff.cpp delete mode 100644 toolsrc/src/commands_remove.cpp delete mode 100644 toolsrc/src/commands_search.cpp delete mode 100644 toolsrc/src/commands_update.cpp delete mode 100644 toolsrc/src/commands_version.cpp delete mode 100644 toolsrc/src/metrics.cpp delete mode 100644 toolsrc/src/test_install_plan.cpp create mode 100644 toolsrc/src/tests.arguments.cpp create mode 100644 toolsrc/src/tests.dependencies.cpp create mode 100644 toolsrc/src/tests.installplan.cpp create mode 100644 toolsrc/src/tests.packagespec.cpp create mode 100644 toolsrc/src/tests.paragraph.cpp delete mode 100644 toolsrc/src/tests_arguments.cpp delete mode 100644 toolsrc/src/tests_dependencies.cpp delete mode 100644 toolsrc/src/tests_package_spec.cpp delete mode 100644 toolsrc/src/tests_paragraph.cpp delete mode 100644 toolsrc/src/triplet.cpp create mode 100644 toolsrc/src/vcpkg/base/checks.cpp create mode 100644 toolsrc/src/vcpkg/base/chrono.cpp create mode 100644 toolsrc/src/vcpkg/base/cofffilereader.cpp create mode 100644 toolsrc/src/vcpkg/base/enums.cpp create mode 100644 toolsrc/src/vcpkg/base/files.cpp create mode 100644 toolsrc/src/vcpkg/base/lineinfo.cpp create mode 100644 toolsrc/src/vcpkg/base/machinetype.cpp create mode 100644 toolsrc/src/vcpkg/base/strings.cpp create mode 100644 toolsrc/src/vcpkg/base/system.cpp create mode 100644 toolsrc/src/vcpkg/binaryparagraph.cpp create mode 100644 toolsrc/src/vcpkg/build.cpp create mode 100644 toolsrc/src/vcpkg/commands.autocomplete.cpp create mode 100644 toolsrc/src/vcpkg/commands.buildexternal.cpp create mode 100644 toolsrc/src/vcpkg/commands.cache.cpp create mode 100644 toolsrc/src/vcpkg/commands.ci.cpp create mode 100644 toolsrc/src/vcpkg/commands.contact.cpp create mode 100644 toolsrc/src/vcpkg/commands.cpp create mode 100644 toolsrc/src/vcpkg/commands.create.cpp create mode 100644 toolsrc/src/vcpkg/commands.dependinfo.cpp create mode 100644 toolsrc/src/vcpkg/commands.edit.cpp create mode 100644 toolsrc/src/vcpkg/commands.env.cpp create mode 100644 toolsrc/src/vcpkg/commands.exportifw.cpp create mode 100644 toolsrc/src/vcpkg/commands.hash.cpp create mode 100644 toolsrc/src/vcpkg/commands.import.cpp create mode 100644 toolsrc/src/vcpkg/commands.integrate.cpp create mode 100644 toolsrc/src/vcpkg/commands.list.cpp create mode 100644 toolsrc/src/vcpkg/commands.owns.cpp create mode 100644 toolsrc/src/vcpkg/commands.portsdiff.cpp create mode 100644 toolsrc/src/vcpkg/commands.search.cpp create mode 100644 toolsrc/src/vcpkg/commands.version.cpp create mode 100644 toolsrc/src/vcpkg/dependencies.cpp create mode 100644 toolsrc/src/vcpkg/export.cpp create mode 100644 toolsrc/src/vcpkg/globalstate.cpp create mode 100644 toolsrc/src/vcpkg/help.cpp create mode 100644 toolsrc/src/vcpkg/input.cpp create mode 100644 toolsrc/src/vcpkg/install.cpp create mode 100644 toolsrc/src/vcpkg/metrics.cpp create mode 100644 toolsrc/src/vcpkg/packagespec.cpp create mode 100644 toolsrc/src/vcpkg/packagespecparseresult.cpp create mode 100644 toolsrc/src/vcpkg/paragraphparseresult.cpp create mode 100644 toolsrc/src/vcpkg/paragraphs.cpp create mode 100644 toolsrc/src/vcpkg/parse.cpp create mode 100644 toolsrc/src/vcpkg/postbuildlint.buildtype.cpp create mode 100644 toolsrc/src/vcpkg/postbuildlint.cpp create mode 100644 toolsrc/src/vcpkg/remove.cpp create mode 100644 toolsrc/src/vcpkg/sourceparagraph.cpp create mode 100644 toolsrc/src/vcpkg/statusparagraph.cpp create mode 100644 toolsrc/src/vcpkg/statusparagraphs.cpp create mode 100644 toolsrc/src/vcpkg/triplet.cpp create mode 100644 toolsrc/src/vcpkg/update.cpp create mode 100644 toolsrc/src/vcpkg/vcpkgcmdarguments.cpp create mode 100644 toolsrc/src/vcpkg/vcpkglib.cpp create mode 100644 toolsrc/src/vcpkg/vcpkgpaths.cpp create mode 100644 toolsrc/src/vcpkg/versiont.cpp delete mode 100644 toolsrc/src/vcpkg_Build.cpp delete mode 100644 toolsrc/src/vcpkg_Build_BuildPolicy.cpp delete mode 100644 toolsrc/src/vcpkg_Checks.cpp delete mode 100644 toolsrc/src/vcpkg_Chrono.cpp delete mode 100644 toolsrc/src/vcpkg_Dependencies.cpp delete mode 100644 toolsrc/src/vcpkg_Enums.cpp delete mode 100644 toolsrc/src/vcpkg_Files.cpp delete mode 100644 toolsrc/src/vcpkg_GlobalState.cpp delete mode 100644 toolsrc/src/vcpkg_Input.cpp delete mode 100644 toolsrc/src/vcpkg_Parse.cpp delete mode 100644 toolsrc/src/vcpkg_Strings.cpp delete mode 100644 toolsrc/src/vcpkg_System.cpp delete mode 100644 toolsrc/src/vcpkg_metrics_uploader.cpp delete mode 100644 toolsrc/src/vcpkglib.cpp create mode 100644 toolsrc/src/vcpkgmetricsuploader.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp deleted file mode 100644 index 1504912ab..000000000 --- a/toolsrc/src/BinaryParagraph.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include "pch.h" - -#include "BinaryParagraph.h" -#include "vcpkg_Checks.h" -#include "vcpkg_Parse.h" - -namespace vcpkg -{ - namespace Fields - { - static const std::string PACKAGE = "Package"; - static const std::string VERSION = "Version"; - static const std::string ARCHITECTURE = "Architecture"; - static const std::string MULTI_ARCH = "Multi-Arch"; - } - - namespace Fields - { - static const std::string FEATURE = "Feature"; - static const std::string DESCRIPTION = "Description"; - static const std::string MAINTAINER = "Maintainer"; - static const std::string DEPENDS = "Depends"; - static const std::string DEFAULTFEATURES = "Default-Features"; - } - - BinaryParagraph::BinaryParagraph() = default; - - BinaryParagraph::BinaryParagraph(std::unordered_map fields) - { - using namespace vcpkg::Parse; - - ParagraphParser parser(std::move(fields)); - - { - std::string name; - parser.required_field(Fields::PACKAGE, name); - std::string architecture; - parser.required_field(Fields::ARCHITECTURE, architecture); - this->spec = PackageSpec::from_name_and_triplet(name, Triplet::from_canonical_name(architecture)) - .value_or_exit(VCPKG_LINE_INFO); - } - - // one or the other - this->version = parser.optional_field(Fields::VERSION); - this->feature = parser.optional_field(Fields::FEATURE); - - this->description = parser.optional_field(Fields::DESCRIPTION); - this->maintainer = parser.optional_field(Fields::MAINTAINER); - - std::string multi_arch; - parser.required_field(Fields::MULTI_ARCH, multi_arch); - - this->depends = parse_comma_list(parser.optional_field(Fields::DEPENDS)); - if (this->feature.empty()) - { - this->default_features = parse_comma_list(parser.optional_field(Fields::DEFAULTFEATURES)); - } - - if (const auto err = parser.error_info(this->spec.to_string())) - { - System::println( - System::Color::error, "Error: while parsing the Binary Paragraph for %s", this->spec.to_string()); - print_error_message(err); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - // prefer failing above when possible because it gives better information - Checks::check_exit(VCPKG_LINE_INFO, multi_arch == "same", "Multi-Arch must be 'same' but was %s", multi_arch); - } - - BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const Triplet& triplet) - { - this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); - this->version = spgh.version; - this->description = spgh.description; - this->maintainer = spgh.maintainer; - this->depends = filter_dependencies(spgh.depends, triplet); - } - - BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, const Triplet& triplet) - { - this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); - this->version = Strings::EMPTY; - this->feature = fpgh.name; - this->description = fpgh.description; - this->maintainer = Strings::EMPTY; - this->depends = filter_dependencies(fpgh.depends, triplet); - } - - std::string BinaryParagraph::displayname() const - { - const auto f = this->feature.empty() ? "core" : this->feature; - return Strings::format("%s[%s]:%s", this->spec.name(), f, this->spec.triplet()); - } - - std::string BinaryParagraph::dir() const { return this->spec.dir(); } - - std::string BinaryParagraph::fullstem() const - { - return Strings::format("%s_%s_%s", this->spec.name(), this->version, this->spec.triplet()); - } - - void serialize(const BinaryParagraph& pgh, std::string& out_str) - { - out_str.append("Package: ").append(pgh.spec.name()).push_back('\n'); - if (!pgh.version.empty()) - out_str.append("Version: ").append(pgh.version).push_back('\n'); - else if (!pgh.feature.empty()) - out_str.append("Feature: ").append(pgh.feature).push_back('\n'); - if (!pgh.depends.empty()) - { - out_str.append("Depends: "); - out_str.append(Strings::join(", ", pgh.depends)); - out_str.push_back('\n'); - } - - out_str.append("Architecture: ").append(pgh.spec.triplet().to_string()).push_back('\n'); - out_str.append("Multi-Arch: same\n"); - - if (!pgh.maintainer.empty()) out_str.append("Maintainer: ").append(pgh.maintainer).push_back('\n'); - if (!pgh.description.empty()) out_str.append("Description: ").append(pgh.description).push_back('\n'); - } -} diff --git a/toolsrc/src/LineInfo.cpp b/toolsrc/src/LineInfo.cpp deleted file mode 100644 index d1bf9a4b1..000000000 --- a/toolsrc/src/LineInfo.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "pch.h" - -#include "LineInfo.h" -#include "vcpkg_Strings.h" - -namespace vcpkg -{ - std::string LineInfo::to_string() const { return Strings::format("%s(%d)", this->file_name, this->line_number); } -} diff --git a/toolsrc/src/MachineType.cpp b/toolsrc/src/MachineType.cpp deleted file mode 100644 index af6378c88..000000000 --- a/toolsrc/src/MachineType.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "pch.h" - -#include "MachineType.h" -#include "vcpkg_Checks.h" - -namespace vcpkg -{ - MachineType to_machine_type(const uint16_t value) - { - const MachineType t = static_cast(value); - switch (t) - { - case MachineType::UNKNOWN: - case MachineType::AM33: - case MachineType::AMD64: - case MachineType::ARM: - case MachineType::ARM64: - case MachineType::ARMNT: - case MachineType::EBC: - case MachineType::I386: - case MachineType::IA64: - case MachineType::M32R: - case MachineType::MIPS16: - case MachineType::MIPSFPU: - case MachineType::MIPSFPU16: - case MachineType::POWERPC: - case MachineType::POWERPCFP: - case MachineType::R4000: - case MachineType::RISCV32: - case MachineType::RISCV64: - case MachineType::RISCV128: - case MachineType::SH3: - case MachineType::SH3DSP: - case MachineType::SH4: - case MachineType::SH5: - case MachineType::THUMB: - case MachineType::WCEMIPSV2: return t; - default: Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown machine type code 0x%x", value); - } - } -} diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp deleted file mode 100644 index 890de8899..000000000 --- a/toolsrc/src/PackageSpec.cpp +++ /dev/null @@ -1,175 +0,0 @@ -#include "pch.h" - -#include "PackageSpec.h" -#include "vcpkg_Parse.h" -#include "vcpkg_Util.h" - -using vcpkg::Parse::parse_comma_list; - -namespace vcpkg -{ - static bool is_valid_package_spec_char(char c) - { - return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)) || (c == '[') || (c == ']'); - } - - std::string FeatureSpec::to_string() const - { - if (feature().empty()) return spec().to_string(); - return Strings::format("%s[%s]:%s", name(), feature(), triplet()); - } - - std::vector FeatureSpec::from_strings_and_triplet(const std::vector& depends, - const Triplet& triplet) - { - std::vector f_specs; - for (auto&& depend : depends) - { - auto maybe_spec = ParsedSpecifier::from_string(depend); - if (auto spec = maybe_spec.get()) - { - Checks::check_exit(VCPKG_LINE_INFO, - spec->triplet.empty(), - "error: triplets cannot currently be specified in this context: %s", - depend); - PackageSpec pspec = - PackageSpec::from_name_and_triplet(spec->name, triplet).value_or_exit(VCPKG_LINE_INFO); - - for (auto&& feature : spec->features) - f_specs.push_back(FeatureSpec{pspec, feature}); - - if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, Strings::EMPTY}); - } - else - { - Checks::exit_with_message(VCPKG_LINE_INFO, - "error while parsing feature list: %s: %s", - vcpkg::to_string(maybe_spec.error()), - depend); - } - } - return f_specs; - } - - std::vector FullPackageSpec::to_feature_specs(const std::vector& specs) - { - std::vector ret; - for (auto&& spec : specs) - { - ret.emplace_back(spec.package_spec, Strings::EMPTY); - for (auto&& feature : spec.features) - ret.emplace_back(spec.package_spec, feature); - } - return ret; - } - - ExpectedT FullPackageSpec::from_string(const std::string& spec_as_string, - const Triplet& default_triplet) - { - auto res = ParsedSpecifier::from_string(spec_as_string); - if (auto p = res.get()) - { - FullPackageSpec fspec; - Triplet t = p->triplet.empty() ? default_triplet : Triplet::from_canonical_name(p->triplet); - fspec.package_spec = PackageSpec::from_name_and_triplet(p->name, t).value_or_exit(VCPKG_LINE_INFO); - fspec.features = std::move(p->features); - return fspec; - } - return res.error(); - } - - ExpectedT PackageSpec::from_name_and_triplet(const std::string& name, - const Triplet& triplet) - { - if (Util::find_if_not(name, is_valid_package_spec_char) != name.end()) - { - return PackageSpecParseResult::INVALID_CHARACTERS; - } - - PackageSpec p; - p.m_name = name; - p.m_triplet = triplet; - return p; - } - - const std::string& PackageSpec::name() const { return this->m_name; } - - const Triplet& PackageSpec::triplet() const { return this->m_triplet; } - - std::string PackageSpec::dir() const { return Strings::format("%s_%s", this->m_name, this->m_triplet); } - - std::string PackageSpec::to_string() const { return Strings::format("%s:%s", this->name(), this->triplet()); } - - bool operator==(const PackageSpec& left, const PackageSpec& right) - { - return left.name() == right.name() && left.triplet() == right.triplet(); - } - - bool operator!=(const PackageSpec& left, const PackageSpec& right) { return !(left == right); } - - ExpectedT ParsedSpecifier::from_string(const std::string& input) - { - auto pos = input.find(':'); - auto pos_l_bracket = input.find('['); - auto pos_r_bracket = input.find(']'); - - ParsedSpecifier f; - if (pos == std::string::npos && pos_l_bracket == std::string::npos) - { - f.name = input; - return f; - } - else if (pos == std::string::npos) - { - if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) - { - return PackageSpecParseResult::INVALID_CHARACTERS; - } - const std::string name = input.substr(0, pos_l_bracket); - f.name = name; - f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); - return f; - } - else if (pos_l_bracket == std::string::npos && pos_r_bracket == std::string::npos) - { - const std::string name = input.substr(0, pos); - f.triplet = input.substr(pos + 1); - f.name = name; - } - else - { - if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) - { - return PackageSpecParseResult::INVALID_CHARACTERS; - } - const std::string name = input.substr(0, pos_l_bracket); - f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); - f.triplet = input.substr(pos + 1); - f.name = name; - } - - auto pos2 = input.find(':', pos + 1); - if (pos2 != std::string::npos) - { - return PackageSpecParseResult::TOO_MANY_COLONS; - } - return f; - } - - ExpectedT Features::from_string(const std::string& name) - { - auto maybe_spec = ParsedSpecifier::from_string(name); - if (auto spec = maybe_spec.get()) - { - Checks::check_exit( - VCPKG_LINE_INFO, spec->triplet.empty(), "error: triplet not allowed in specifier: %s", name); - - Features f; - f.name = spec->name; - f.features = spec->features; - return f; - } - - return maybe_spec.error(); - } -} diff --git a/toolsrc/src/PackageSpecParseResult.cpp b/toolsrc/src/PackageSpecParseResult.cpp deleted file mode 100644 index 838c788ba..000000000 --- a/toolsrc/src/PackageSpecParseResult.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "pch.h" - -#include "PackageSpecParseResult.h" -#include "vcpkg_Checks.h" - -namespace vcpkg -{ - CStringView to_string(PackageSpecParseResult ev) noexcept - { - switch (ev) - { - case PackageSpecParseResult::SUCCESS: return "OK"; - case PackageSpecParseResult::TOO_MANY_COLONS: return "Too many colons"; - case PackageSpecParseResult::INVALID_CHARACTERS: - return "Contains invalid characters. Only alphanumeric lowercase ASCII characters and dashes are " - "allowed"; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } -} diff --git a/toolsrc/src/ParagraphParseResult.cpp b/toolsrc/src/ParagraphParseResult.cpp deleted file mode 100644 index 5c8c1d59d..000000000 --- a/toolsrc/src/ParagraphParseResult.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "pch.h" - -#include "ParagraphParseResult.h" -#include "vcpkg_Checks.h" - -namespace vcpkg -{ - const char* ParagraphParseResultCategoryImpl::name() const noexcept { return "ParagraphParseResult"; } - - std::string ParagraphParseResultCategoryImpl::message(int ev) const noexcept - { - switch (static_cast(ev)) - { - case ParagraphParseResult::SUCCESS: return "OK"; - case ParagraphParseResult::EXPECTED_ONE_PARAGRAPH: return "There should be exactly one paragraph"; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - - const std::error_category& paragraph_parse_result_category() - { - static ParagraphParseResultCategoryImpl instance; - return instance; - } - - std::error_code make_error_code(ParagraphParseResult e) - { - return std::error_code(static_cast(e), paragraph_parse_result_category()); - } - - ParagraphParseResult to_paragraph_parse_result(int i) { return static_cast(i); } - - ParagraphParseResult to_paragraph_parse_result(std::error_code ec) { return to_paragraph_parse_result(ec.value()); } -} diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp deleted file mode 100644 index 6a6f191df..000000000 --- a/toolsrc/src/Paragraphs.cpp +++ /dev/null @@ -1,304 +0,0 @@ -#include "pch.h" - -#include "ParagraphParseResult.h" -#include "Paragraphs.h" -#include "vcpkg_Files.h" -#include "vcpkg_GlobalState.h" -#include "vcpkg_Util.h" - -using namespace vcpkg::Parse; - -namespace vcpkg::Paragraphs -{ - struct Parser - { - Parser(const char* c, const char* e) : cur(c), end(e) {} - - private: - const char* cur; - const char* const end; - - void peek(char& ch) const - { - if (cur == end) - ch = 0; - else - ch = *cur; - } - - void next(char& ch) - { - if (cur == end) - ch = 0; - else - { - ++cur; - peek(ch); - } - } - - void skip_comment(char& ch) - { - while (ch != '\r' && ch != '\n' && ch != '\0') - next(ch); - if (ch == '\r') next(ch); - if (ch == '\n') next(ch); - } - - void skip_spaces(char& ch) - { - while (ch == ' ' || ch == '\t') - next(ch); - } - - static bool is_alphanum(char ch) - { - return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'); - } - - static bool is_comment(char ch) { return (ch == '#'); } - - static bool is_lineend(char ch) { return ch == '\r' || ch == '\n' || ch == 0; } - - void get_fieldvalue(char& ch, std::string& fieldvalue) - { - fieldvalue.clear(); - - auto beginning_of_line = cur; - do - { - // scan to end of current line (it is part of the field value) - while (!is_lineend(ch)) - next(ch); - - fieldvalue.append(beginning_of_line, cur); - - if (ch == '\r') next(ch); - if (ch == '\n') next(ch); - - if (is_alphanum(ch) || is_comment(ch)) - { - // Line begins a new field. - return; - } - - beginning_of_line = cur; - - // Line may continue the current field with data or terminate the paragraph, - // depending on first nonspace character. - skip_spaces(ch); - - if (is_lineend(ch)) - { - // Line was whitespace or empty. - // This terminates the field and the paragraph. - // We leave the blank line's whitespace consumed, because it doesn't matter. - return; - } - - // First nonspace is not a newline. This continues the current field value. - // We forcibly convert all newlines into single '\n' for ease of text handling later on. - fieldvalue.push_back('\n'); - } while (true); - } - - void get_fieldname(char& ch, std::string& fieldname) - { - auto begin_fieldname = cur; - while (is_alphanum(ch) || ch == '-') - next(ch); - Checks::check_exit(VCPKG_LINE_INFO, ch == ':', "Expected ':'"); - fieldname = std::string(begin_fieldname, cur); - - // skip ': ' - next(ch); - skip_spaces(ch); - } - - void get_paragraph(char& ch, std::unordered_map& fields) - { - fields.clear(); - std::string fieldname; - std::string fieldvalue; - do - { - if (is_comment(ch)) - { - skip_comment(ch); - continue; - } - - get_fieldname(ch, fieldname); - - auto it = fields.find(fieldname); - Checks::check_exit(VCPKG_LINE_INFO, it == fields.end(), "Duplicate field"); - - get_fieldvalue(ch, fieldvalue); - - fields.emplace(fieldname, fieldvalue); - } while (!is_lineend(ch)); - } - - public: - std::vector> get_paragraphs() - { - std::vector> paragraphs; - - char ch; - peek(ch); - - while (ch != 0) - { - if (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t') - { - next(ch); - continue; - } - - paragraphs.emplace_back(); - get_paragraph(ch, paragraphs.back()); - } - - return paragraphs; - } - }; - - Expected> get_single_paragraph(const Files::Filesystem& fs, - const fs::path& control_path) - { - const Expected contents = fs.read_contents(control_path); - if (auto spgh = contents.get()) - { - return parse_single_paragraph(*spgh); - } - - return contents.error(); - } - - Expected>> get_paragraphs(const Files::Filesystem& fs, - const fs::path& control_path) - { - const Expected contents = fs.read_contents(control_path); - if (auto spgh = contents.get()) - { - return parse_paragraphs(*spgh); - } - - return contents.error(); - } - - Expected> parse_single_paragraph(const std::string& str) - { - const std::vector> p = - Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); - - if (p.size() == 1) - { - return p.at(0); - } - - return std::error_code(ParagraphParseResult::EXPECTED_ONE_PARAGRAPH); - } - - Expected>> parse_paragraphs(const std::string& str) - { - return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); - } - - ParseExpected try_load_port(const Files::Filesystem& fs, const fs::path& path) - { - Expected>> pghs = get_paragraphs(fs, path / "CONTROL"); - if (auto vector_pghs = pghs.get()) - { - auto csf = SourceControlFile::parse_control_file(std::move(*vector_pghs)); - if (!GlobalState::feature_packages) - { - if (auto ptr = csf.get()) - { - Checks::check_exit(VCPKG_LINE_INFO, ptr->get() != nullptr); - ptr->get()->core_paragraph->default_features.clear(); - ptr->get()->feature_paragraphs.clear(); - } - } - return csf; - } - auto error_info = std::make_unique(); - error_info->name = path.filename().generic_u8string(); - error_info->error = pghs.error(); - return error_info; - } - - Expected try_load_cached_control_package(const VcpkgPaths& paths, const PackageSpec& spec) - { - Expected>> pghs = - get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL"); - - if (auto p = pghs.get()) - { - BinaryControlFile bcf; - bcf.core_paragraph = BinaryParagraph(p->front()); - p->erase(p->begin()); - - bcf.features = - Util::fmap(*p, [&](auto&& raw_feature) -> BinaryParagraph { return BinaryParagraph(raw_feature); }); - - return bcf; - } - - return pghs.error(); - } - - LoadResults try_load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) - { - LoadResults ret; - for (auto&& path : fs.get_files_non_recursive(ports_dir)) - { - auto maybe_spgh = try_load_port(fs, path); - if (const auto spgh = maybe_spgh.get()) - { - ret.paragraphs.emplace_back(std::move(*spgh)); - } - else - { - ret.errors.emplace_back(std::move(maybe_spgh).error()); - } - } - return ret; - } - - std::vector> load_all_ports(const Files::Filesystem& fs, - const fs::path& ports_dir) - { - auto results = try_load_all_ports(fs, ports_dir); - if (!results.errors.empty()) - { - if (GlobalState::debugging) - { - print_error_message(results.errors); - } - else - { - for (auto&& error : results.errors) - { - System::println( - System::Color::warning, "Warning: an error occurred while parsing '%s'", error->name); - } - System::println(System::Color::warning, - "Use '--debug' to get more information about the parse failures.\n"); - } - } - return std::move(results.paragraphs); - } - - std::map load_all_port_names_and_versions(const Files::Filesystem& fs, - const fs::path& ports_dir) - { - auto all_ports = load_all_ports(fs, ports_dir); - - std::map names_and_versions; - for (auto&& port : all_ports) - names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version); - - return names_and_versions; - } -} diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp deleted file mode 100644 index a0699e15c..000000000 --- a/toolsrc/src/PostBuildLint.cpp +++ /dev/null @@ -1,846 +0,0 @@ -#include "pch.h" - -#include "PackageSpec.h" -#include "PostBuildLint.h" -#include "PostBuildLint_BuildType.h" -#include "VcpkgPaths.h" -#include "coff_file_reader.h" -#include "vcpkg_Build.h" -#include "vcpkg_Files.h" -#include "vcpkg_System.h" -#include "vcpkg_Util.h" - -using vcpkg::Build::BuildInfo; -using vcpkg::Build::BuildPolicy; -using vcpkg::Build::PreBuildInfo; - -namespace vcpkg::PostBuildLint -{ - static auto has_extension_pred(const Files::Filesystem& fs, const std::string& ext) - { - return [&fs, ext](const fs::path& path) { return !fs.is_directory(path) && path.extension() == ext; }; - } - - enum class LintStatus - { - SUCCESS = 0, - ERROR_DETECTED = 1 - }; - - struct OutdatedDynamicCrt - { - std::string name; - std::regex regex; - - OutdatedDynamicCrt(const std::string& name, const std::string& regex_as_string) - : name(name), regex(std::regex(regex_as_string, std::regex_constants::icase)) - { - } - }; - - Span get_outdated_dynamic_crts(CStringView toolset) - { - static const std::vector V_NO_MSVCRT = { - {"msvcp100.dll", R"(msvcp100\.dll)"}, - {"msvcp100d.dll", R"(msvcp100d\.dll)"}, - {"msvcp110.dll", R"(msvcp110\.dll)"}, - {"msvcp110_win.dll", R"(msvcp110_win\.dll)"}, - {"msvcp120.dll", R"(msvcp120\.dll)"}, - {"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"}, - {"msvcp60.dll", R"(msvcp60\.dll)"}, - {"msvcp60.dll", R"(msvcp60\.dll)"}, - - {"msvcr100.dll", R"(msvcr100\.dll)"}, - {"msvcr100d.dll", R"(msvcr100d\.dll)"}, - {"msvcr100_clr0400.dll", R"(msvcr100_clr0400\.dll)"}, - {"msvcr110.dll", R"(msvcr110\.dll)"}, - {"msvcr120.dll", R"(msvcr120\.dll)"}, - {"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"}, - {"msvcrt20.dll", R"(msvcrt20\.dll)"}, - {"msvcrt40.dll", R"(msvcrt40\.dll)"}}; - - return V_NO_MSVCRT; - } - - static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs, - const Build::BuildPolicies& policies, - const fs::path& package_dir) - { - if (policies.is_enabled(BuildPolicy::EMPTY_INCLUDE_FOLDER)) - { - return LintStatus::SUCCESS; - } - - const fs::path include_dir = package_dir / "include"; - if (!fs.exists(include_dir) || fs.is_empty(include_dir)) - { - System::println(System::Color::warning, - "The folder /include is empty. This indicates the library was not correctly installed."); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_for_files_in_debug_include_directory(const Files::Filesystem& fs, - const fs::path& package_dir) - { - const fs::path debug_include_dir = package_dir / "debug" / "include"; - - std::vector files_found = fs.get_files_recursive(debug_include_dir); - - Util::unstable_keep_if( - files_found, [&fs](const fs::path& path) { return !fs.is_directory(path) && path.extension() != ".ifc"; }); - - if (!files_found.empty()) - { - System::println(System::Color::warning, - "Include files should not be duplicated into the /debug/include directory. If this cannot " - "be disabled in the project cmake, use\n" - " file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include)"); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_for_files_in_debug_share_directory(const Files::Filesystem& fs, const fs::path& package_dir) - { - const fs::path debug_share = package_dir / "debug" / "share"; - - if (fs.exists(debug_share)) - { - System::println(System::Color::warning, - "/debug/share should not exist. Please reorganize any important files, then use\n" - " file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/share)"); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_folder_lib_cmake(const Files::Filesystem& fs, - const fs::path& package_dir, - const PackageSpec& spec) - { - const fs::path lib_cmake = package_dir / "lib" / "cmake"; - if (fs.exists(lib_cmake)) - { - System::println( - System::Color::warning, - "The /lib/cmake folder should be merged with /debug/lib/cmake and moved to /share/%s/cmake.", - spec.name()); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_for_misplaced_cmake_files(const Files::Filesystem& fs, - const fs::path& package_dir, - const PackageSpec& spec) - { - std::vector dirs = { - package_dir / "cmake", - package_dir / "debug" / "cmake", - package_dir / "lib" / "cmake", - package_dir / "debug" / "lib" / "cmake", - }; - - std::vector misplaced_cmake_files; - for (auto&& dir : dirs) - { - auto files = fs.get_files_recursive(dir); - for (auto&& file : files) - { - if (!fs.is_directory(file) && file.extension() == ".cmake") - misplaced_cmake_files.push_back(std::move(file)); - } - } - - if (!misplaced_cmake_files.empty()) - { - System::println( - System::Color::warning, - "The following cmake files were found outside /share/%s. Please place cmake files in /share/%s.", - spec.name(), - spec.name()); - Files::print_paths(misplaced_cmake_files); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_folder_debug_lib_cmake(const Files::Filesystem& fs, - const fs::path& package_dir, - const PackageSpec& spec) - { - const fs::path lib_cmake_debug = package_dir / "debug" / "lib" / "cmake"; - if (fs.exists(lib_cmake_debug)) - { - System::println(System::Color::warning, - "The /debug/lib/cmake folder should be merged with /lib/cmake into /share/%s", - spec.name()); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_for_dlls_in_lib_dir(const Files::Filesystem& fs, const fs::path& package_dir) - { - std::vector dlls = fs.get_files_recursive(package_dir / "lib"); - Util::unstable_keep_if(dlls, has_extension_pred(fs, ".dll")); - - if (!dlls.empty()) - { - System::println(System::Color::warning, - "\nThe following dlls were found in /lib or /debug/lib. Please move them to /bin or " - "/debug/bin, respectively."); - Files::print_paths(dlls); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_for_copyright_file(const Files::Filesystem& fs, - const PackageSpec& spec, - const VcpkgPaths& paths) - { - const fs::path packages_dir = paths.packages / spec.dir(); - const fs::path copyright_file = packages_dir / "share" / spec.name() / "copyright"; - if (fs.exists(copyright_file)) - { - return LintStatus::SUCCESS; - } - const fs::path current_buildtrees_dir = paths.buildtrees / spec.name(); - const fs::path current_buildtrees_dir_src = current_buildtrees_dir / "src"; - - std::vector potential_copyright_files; - // We only search in the root of each unpacked source archive to reduce false positives - auto src_dirs = fs.get_files_non_recursive(current_buildtrees_dir_src); - for (auto&& src_dir : src_dirs) - { - if (!fs.is_directory(src_dir)) continue; - - for (auto&& src_file : fs.get_files_non_recursive(src_dir)) - { - const std::string filename = src_file.filename().string(); - - if (filename == "LICENSE" || filename == "LICENSE.txt" || filename == "COPYING") - { - potential_copyright_files.push_back(src_file); - } - } - } - - System::println(System::Color::warning, - "The software license must be available at ${CURRENT_PACKAGES_DIR}/share/%s/copyright", - spec.name()); - if (potential_copyright_files.size() == - 1) // if there is only one candidate, provide the cmake lines needed to place it in the proper location - { - const fs::path found_file = potential_copyright_files[0]; - const fs::path relative_path = found_file.string().erase( - 0, current_buildtrees_dir.string().size() + 1); // The +1 is needed to remove the "/" - System::println( - "\n file(COPY ${CURRENT_BUILDTREES_DIR}/%s DESTINATION ${CURRENT_PACKAGES_DIR}/share/%s)\n" - " file(RENAME ${CURRENT_PACKAGES_DIR}/share/%s/%s ${CURRENT_PACKAGES_DIR}/share/%s/copyright)", - relative_path.generic_string(), - spec.name(), - spec.name(), - found_file.filename().generic_string(), - spec.name()); - } - else if (potential_copyright_files.size() > 1) - { - System::println(System::Color::warning, "The following files are potential copyright files:"); - Files::print_paths(potential_copyright_files); - } - return LintStatus::ERROR_DETECTED; - } - - static LintStatus check_for_exes(const Files::Filesystem& fs, const fs::path& package_dir) - { - std::vector exes = fs.get_files_recursive(package_dir / "bin"); - Util::unstable_keep_if(exes, has_extension_pred(fs, ".exe")); - - if (!exes.empty()) - { - System::println( - System::Color::warning, - "The following EXEs were found in /bin or /debug/bin. EXEs are not valid distribution targets."); - Files::print_paths(exes); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_exports_of_dlls(const std::vector& dlls, const fs::path& dumpbin_exe) - { - std::vector dlls_with_no_exports; - for (const fs::path& dll : dlls) - { - const std::wstring cmd_line = - Strings::wformat(LR"("%s" /exports "%s")", dumpbin_exe.native(), dll.native()); - System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, - ec_data.exit_code == 0, - "Running command:\n %s\n failed", - Strings::to_utf8(cmd_line)); - - if (ec_data.output.find("ordinal hint RVA name") == std::string::npos) - { - dlls_with_no_exports.push_back(dll); - } - } - - if (!dlls_with_no_exports.empty()) - { - System::println(System::Color::warning, "The following DLLs have no exports:"); - Files::print_paths(dlls_with_no_exports); - System::println(System::Color::warning, "DLLs without any exports are likely a bug in the build script."); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_uwp_bit_of_dlls(const std::string& expected_system_name, - const std::vector& dlls, - const fs::path dumpbin_exe) - { - if (expected_system_name != "WindowsStore") - { - return LintStatus::SUCCESS; - } - - std::vector dlls_with_improper_uwp_bit; - for (const fs::path& dll : dlls) - { - const std::wstring cmd_line = - Strings::wformat(LR"("%s" /headers "%s")", dumpbin_exe.native(), dll.native()); - System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, - ec_data.exit_code == 0, - "Running command:\n %s\n failed", - Strings::to_utf8(cmd_line)); - - if (ec_data.output.find("App Container") == std::string::npos) - { - dlls_with_improper_uwp_bit.push_back(dll); - } - } - - if (!dlls_with_improper_uwp_bit.empty()) - { - System::println(System::Color::warning, "The following DLLs do not have the App Container bit set:"); - Files::print_paths(dlls_with_improper_uwp_bit); - System::println(System::Color::warning, "This bit is required for Windows Store apps."); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - struct FileAndArch - { - fs::path file; - std::string actual_arch; - }; - - static std::string get_actual_architecture(const MachineType& machine_type) - { - switch (machine_type) - { - case MachineType::AMD64: - case MachineType::IA64: return "x64"; - case MachineType::I386: return "x86"; - case MachineType::ARM: - case MachineType::ARMNT: return "arm"; - default: return "Machine Type Code = " + std::to_string(static_cast(machine_type)); - } - } - - static void print_invalid_architecture_files(const std::string& expected_architecture, - std::vector binaries_with_invalid_architecture) - { - System::println(System::Color::warning, "The following files were built for an incorrect architecture:"); - System::println(); - for (const FileAndArch& b : binaries_with_invalid_architecture) - { - System::println(" %s", b.file.generic_string()); - System::println("Expected %s, but was: %s", expected_architecture, b.actual_arch); - System::println(); - } - } - - static LintStatus check_dll_architecture(const std::string& expected_architecture, - const std::vector& files) - { - std::vector binaries_with_invalid_architecture; - - for (const fs::path& file : files) - { - Checks::check_exit(VCPKG_LINE_INFO, - file.extension() == ".dll", - "The file extension was not .dll: %s", - file.generic_string()); - const CoffFileReader::DllInfo info = CoffFileReader::read_dll(file); - const std::string actual_architecture = get_actual_architecture(info.machine_type); - - if (expected_architecture != actual_architecture) - { - binaries_with_invalid_architecture.push_back({file, actual_architecture}); - } - } - - if (!binaries_with_invalid_architecture.empty()) - { - print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_lib_architecture(const std::string& expected_architecture, - const std::vector& files) - { - std::vector binaries_with_invalid_architecture; - - for (const fs::path& file : files) - { - Checks::check_exit(VCPKG_LINE_INFO, - file.extension() == ".lib", - "The file extension was not .lib: %s", - file.generic_string()); - CoffFileReader::LibInfo info = CoffFileReader::read_lib(file); - - // This is zero for folly's debug library - // TODO: Why? - if (info.machine_types.size() == 0) return LintStatus::SUCCESS; - - Checks::check_exit(VCPKG_LINE_INFO, - info.machine_types.size() == 1, - "Found more than 1 architecture in file %s", - file.generic_string()); - - const std::string actual_architecture = get_actual_architecture(info.machine_types.at(0)); - if (expected_architecture != actual_architecture) - { - binaries_with_invalid_architecture.push_back({file, actual_architecture}); - } - } - - if (!binaries_with_invalid_architecture.empty()) - { - print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_no_dlls_present(const std::vector& dlls) - { - if (dlls.empty()) - { - return LintStatus::SUCCESS; - } - - System::println(System::Color::warning, - "DLLs should not be present in a static build, but the following DLLs were found:"); - Files::print_paths(dlls); - return LintStatus::ERROR_DETECTED; - } - - static LintStatus check_matching_debug_and_release_binaries(const std::vector& debug_binaries, - const std::vector& release_binaries) - { - const size_t debug_count = debug_binaries.size(); - const size_t release_count = release_binaries.size(); - if (debug_count == release_count) - { - return LintStatus::SUCCESS; - } - - System::println(System::Color::warning, - "Mismatching number of debug and release binaries. Found %d for debug but %d for release.", - debug_count, - release_count); - System::println("Debug binaries"); - Files::print_paths(debug_binaries); - - System::println("Release binaries"); - Files::print_paths(release_binaries); - - if (debug_count == 0) - { - System::println(System::Color::warning, "Debug binaries were not found"); - } - if (release_count == 0) - { - System::println(System::Color::warning, "Release binaries were not found"); - } - - System::println(); - - return LintStatus::ERROR_DETECTED; - } - - static LintStatus check_lib_files_are_available_if_dlls_are_available(const Build::BuildPolicies& policies, - const size_t lib_count, - const size_t dll_count, - const fs::path& lib_dir) - { - if (policies.is_enabled(BuildPolicy::DLLS_WITHOUT_LIBS)) return LintStatus::SUCCESS; - - if (lib_count == 0 && dll_count != 0) - { - System::println(System::Color::warning, "Import libs were not present in %s", lib_dir.u8string()); - System::println(System::Color::warning, - "If this is intended, add the following line in the portfile:\n" - " SET(%s enabled)", - to_cmake_variable(BuildPolicy::DLLS_WITHOUT_LIBS)); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_bin_folders_are_not_present_in_static_build(const Files::Filesystem& fs, - const fs::path& package_dir) - { - const fs::path bin = package_dir / "bin"; - const fs::path debug_bin = package_dir / "debug" / "bin"; - - if (!fs.exists(bin) && !fs.exists(debug_bin)) - { - return LintStatus::SUCCESS; - } - - if (fs.exists(bin)) - { - System::println(System::Color::warning, - R"(There should be no bin\ directory in a static build, but %s is present.)", - bin.u8string()); - } - - if (fs.exists(debug_bin)) - { - System::println(System::Color::warning, - R"(There should be no debug\bin\ directory in a static build, but %s is present.)", - debug_bin.u8string()); - } - - System::println( - System::Color::warning, - R"(If the creation of bin\ and/or debug\bin\ cannot be disabled, use this in the portfile to remove them)" - "\n" - "\n" - R"###( if(VCPKG_LIBRARY_LINKAGE STREQUAL static))###" - "\n" - R"###( file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/bin ${CURRENT_PACKAGES_DIR}/debug/bin))###" - "\n" - R"###( endif())###" - "\n"); - - return LintStatus::ERROR_DETECTED; - } - - static LintStatus check_no_empty_folders(const Files::Filesystem& fs, const fs::path& dir) - { - std::vector empty_directories = fs.get_files_recursive(dir); - - Util::unstable_keep_if(empty_directories, [&fs](const fs::path& current) { - return fs.is_directory(current) && fs.is_empty(current); - }); - - if (!empty_directories.empty()) - { - System::println(System::Color::warning, "There should be no empty directories in %s", dir.generic_string()); - System::println("The following empty directories were found: "); - Files::print_paths(empty_directories); - System::println( - System::Color::warning, - "If a directory should be populated but is not, this might indicate an error in the portfile.\n" - "If the directories are not needed and their creation cannot be disabled, use something like this in " - "the portfile to remove them:\n" - "\n" - R"###( file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/a/dir ${CURRENT_PACKAGES_DIR}/some/other/dir))###" - "\n" - "\n"); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - struct BuildTypeAndFile - { - fs::path file; - BuildType build_type; - }; - - static LintStatus check_crt_linkage_of_libs(const BuildType& expected_build_type, - const std::vector& libs, - const fs::path dumpbin_exe) - { - std::vector bad_build_types(BuildTypeC::VALUES.cbegin(), BuildTypeC::VALUES.cend()); - bad_build_types.erase(std::remove(bad_build_types.begin(), bad_build_types.end(), expected_build_type), - bad_build_types.end()); - - std::vector libs_with_invalid_crt; - - for (const fs::path& lib : libs) - { - const std::wstring cmd_line = - Strings::wformat(LR"("%s" /directives "%s")", dumpbin_exe.native(), lib.native()); - System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, - ec_data.exit_code == 0, - "Running command:\n %s\n failed", - Strings::to_utf8(cmd_line)); - - for (const BuildType& bad_build_type : bad_build_types) - { - if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), bad_build_type.crt_regex())) - { - libs_with_invalid_crt.push_back({lib, bad_build_type}); - break; - } - } - } - - if (!libs_with_invalid_crt.empty()) - { - System::println(System::Color::warning, - "Expected %s crt linkage, but the following libs had invalid crt linkage:", - expected_build_type.to_string()); - System::println(); - for (const BuildTypeAndFile btf : libs_with_invalid_crt) - { - System::println(" %s: %s", btf.file.generic_string(), btf.build_type.to_string()); - } - System::println(); - - System::println(System::Color::warning, - "To inspect the lib files, use:\n dumpbin.exe /directives mylibfile.lib"); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - struct OutdatedDynamicCrtAndFile - { - fs::path file; - OutdatedDynamicCrt outdated_crt; - - OutdatedDynamicCrtAndFile() = delete; - }; - - static LintStatus check_outdated_crt_linkage_of_dlls(const std::vector& dlls, - const fs::path dumpbin_exe, - const BuildInfo& build_info) - { - if (build_info.policies.is_enabled(BuildPolicy::ALLOW_OBSOLETE_MSVCRT)) return LintStatus::SUCCESS; - - std::vector dlls_with_outdated_crt; - - for (const fs::path& dll : dlls) - { - const std::wstring cmd_line = - Strings::wformat(LR"("%s" /dependents "%s")", dumpbin_exe.native(), dll.native()); - System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, - ec_data.exit_code == 0, - "Running command:\n %s\n failed", - Strings::to_utf8(cmd_line)); - - for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts("v141")) - { - if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), outdated_crt.regex)) - { - dlls_with_outdated_crt.push_back({dll, outdated_crt}); - break; - } - } - } - - if (!dlls_with_outdated_crt.empty()) - { - System::println(System::Color::warning, "Detected outdated dynamic CRT in the following files:"); - System::println(); - for (const OutdatedDynamicCrtAndFile btf : dlls_with_outdated_crt) - { - System::println(" %s: %s", btf.file.generic_string(), btf.outdated_crt.name); - } - System::println(); - - System::println(System::Color::warning, - "To inspect the dll files, use:\n dumpbin.exe /dependents mydllfile.dll"); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static LintStatus check_no_files_in_dir(const Files::Filesystem& fs, const fs::path& dir) - { - std::vector misplaced_files = fs.get_files_non_recursive(dir); - Util::unstable_keep_if(misplaced_files, [&fs](const fs::path& path) { - const std::string filename = path.filename().generic_string(); - if (Strings::case_insensitive_ascii_compare(filename.c_str(), "CONTROL") == 0 || - Strings::case_insensitive_ascii_compare(filename.c_str(), "BUILD_INFO") == 0) - return false; - return !fs.is_directory(path); - }); - - if (!misplaced_files.empty()) - { - System::println(System::Color::warning, "The following files are placed in\n%s: ", dir.u8string()); - Files::print_paths(misplaced_files); - System::println(System::Color::warning, "Files cannot be present in those directories.\n"); - return LintStatus::ERROR_DETECTED; - } - - return LintStatus::SUCCESS; - } - - static void operator+=(size_t& left, const LintStatus& right) { left += static_cast(right); } - - static size_t perform_all_checks_and_return_error_count(const PackageSpec& spec, - const VcpkgPaths& paths, - const PreBuildInfo& pre_build_info, - const BuildInfo& build_info) - { - const auto& fs = paths.get_filesystem(); - - // for dumpbin - const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); - const fs::path package_dir = paths.package_dir(spec); - - size_t error_count = 0; - - if (build_info.policies.is_enabled(BuildPolicy::EMPTY_PACKAGE)) - { - return error_count; - } - - error_count += check_for_files_in_include_directory(fs, build_info.policies, package_dir); - error_count += check_for_files_in_debug_include_directory(fs, package_dir); - error_count += check_for_files_in_debug_share_directory(fs, package_dir); - error_count += check_folder_lib_cmake(fs, package_dir, spec); - error_count += check_for_misplaced_cmake_files(fs, package_dir, spec); - error_count += check_folder_debug_lib_cmake(fs, package_dir, spec); - error_count += check_for_dlls_in_lib_dir(fs, package_dir); - error_count += check_for_dlls_in_lib_dir(fs, package_dir / "debug"); - error_count += check_for_copyright_file(fs, spec, paths); - error_count += check_for_exes(fs, package_dir); - error_count += check_for_exes(fs, package_dir / "debug"); - - const fs::path debug_lib_dir = package_dir / "debug" / "lib"; - const fs::path release_lib_dir = package_dir / "lib"; - const fs::path debug_bin_dir = package_dir / "debug" / "bin"; - const fs::path release_bin_dir = package_dir / "bin"; - - std::vector debug_libs = fs.get_files_recursive(debug_lib_dir); - Util::unstable_keep_if(debug_libs, has_extension_pred(fs, ".lib")); - std::vector release_libs = fs.get_files_recursive(release_lib_dir); - Util::unstable_keep_if(release_libs, has_extension_pred(fs, ".lib")); - - error_count += check_matching_debug_and_release_binaries(debug_libs, release_libs); - - { - std::vector libs; - libs.insert(libs.cend(), debug_libs.cbegin(), debug_libs.cend()); - libs.insert(libs.cend(), release_libs.cbegin(), release_libs.cend()); - - error_count += check_lib_architecture(pre_build_info.target_architecture, libs); - } - - std::vector debug_dlls = fs.get_files_recursive(debug_bin_dir); - Util::unstable_keep_if(debug_dlls, has_extension_pred(fs, ".dll")); - std::vector release_dlls = fs.get_files_recursive(release_bin_dir); - Util::unstable_keep_if(release_dlls, has_extension_pred(fs, ".dll")); - - switch (build_info.library_linkage) - { - case Build::LinkageType::DYNAMIC: - { - error_count += check_matching_debug_and_release_binaries(debug_dlls, release_dlls); - - error_count += check_lib_files_are_available_if_dlls_are_available( - build_info.policies, debug_libs.size(), debug_dlls.size(), debug_lib_dir); - error_count += check_lib_files_are_available_if_dlls_are_available( - build_info.policies, release_libs.size(), release_dlls.size(), release_lib_dir); - - std::vector dlls; - dlls.insert(dlls.cend(), debug_dlls.cbegin(), debug_dlls.cend()); - dlls.insert(dlls.cend(), release_dlls.cbegin(), release_dlls.cend()); - - error_count += check_exports_of_dlls(dlls, toolset.dumpbin); - error_count += check_uwp_bit_of_dlls(pre_build_info.cmake_system_name, dlls, toolset.dumpbin); - error_count += check_dll_architecture(pre_build_info.target_architecture, dlls); - - error_count += check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info); - break; - } - case Build::LinkageType::STATIC: - { - auto dlls = release_dlls; - dlls.insert(dlls.end(), debug_dlls.begin(), debug_dlls.end()); - error_count += check_no_dlls_present(dlls); - - error_count += check_bin_folders_are_not_present_in_static_build(fs, package_dir); - - if (!build_info.policies.is_enabled(BuildPolicy::ONLY_RELEASE_CRT)) - { - error_count += - check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::DEBUG, build_info.crt_linkage), - debug_libs, - toolset.dumpbin); - } - error_count += - check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::RELEASE, build_info.crt_linkage), - release_libs, - toolset.dumpbin); - break; - } - default: Checks::unreachable(VCPKG_LINE_INFO); - } - - error_count += check_no_empty_folders(fs, package_dir); - error_count += check_no_files_in_dir(fs, package_dir); - error_count += check_no_files_in_dir(fs, package_dir / "debug"); - - return error_count; - } - - size_t perform_all_checks(const PackageSpec& spec, - const VcpkgPaths& paths, - const PreBuildInfo& pre_build_info, - const BuildInfo& build_info) - { - System::println("-- Performing post-build validation"); - const size_t error_count = perform_all_checks_and_return_error_count(spec, paths, pre_build_info, build_info); - - if (error_count != 0) - { - const fs::path portfile = paths.ports / spec.name() / "portfile.cmake"; - System::println(System::Color::error, - "Found %u error(s). Please correct the portfile:\n %s", - error_count, - portfile.string()); - } - - System::println("-- Performing post-build validation done"); - - return error_count; - } -} diff --git a/toolsrc/src/PostBuildLint_BuildType.cpp b/toolsrc/src/PostBuildLint_BuildType.cpp deleted file mode 100644 index 649f0ccca..000000000 --- a/toolsrc/src/PostBuildLint_BuildType.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "pch.h" - -#include "PostBuildLint_BuildType.h" -#include "vcpkg_Checks.h" - -namespace vcpkg::PostBuildLint -{ - BuildType BuildType::value_of(const ConfigurationType& config, const Build::LinkageType& linkage) - { - if (config == ConfigurationType::DEBUG && linkage == Build::LinkageType::STATIC) - { - return BuildTypeC::DEBUG_STATIC; - } - - if (config == ConfigurationType::DEBUG && linkage == Build::LinkageType::DYNAMIC) - { - return BuildTypeC::DEBUG_DYNAMIC; - } - - if (config == ConfigurationType::RELEASE && linkage == Build::LinkageType::STATIC) - { - return BuildTypeC::RELEASE_STATIC; - } - - if (config == ConfigurationType::RELEASE && linkage == Build::LinkageType::DYNAMIC) - { - return BuildTypeC::RELEASE_DYNAMIC; - } - - Checks::unreachable(VCPKG_LINE_INFO); - } - - const ConfigurationType& BuildType::config() const { return this->m_config; } - - const Build::LinkageType& BuildType::linkage() const { return this->m_linkage; } - - const std::regex& BuildType::crt_regex() const - { - static const std::regex REGEX_DEBUG_STATIC(R"(/DEFAULTLIB:LIBCMTD)", std::regex_constants::icase); - static const std::regex REGEX_DEBUG_DYNAMIC(R"(/DEFAULTLIB:MSVCRTD)", std::regex_constants::icase); - static const std::regex REGEX_RELEASE_STATIC(R"(/DEFAULTLIB:LIBCMT[^D])", std::regex_constants::icase); - static const std::regex REGEX_RELEASE_DYNAMIC(R"(/DEFAULTLIB:MSVCRT[^D])", std::regex_constants::icase); - - switch (backing_enum) - { - case BuildTypeC::DEBUG_STATIC: return REGEX_DEBUG_STATIC; - case BuildTypeC::DEBUG_DYNAMIC: return REGEX_DEBUG_DYNAMIC; - case BuildTypeC::RELEASE_STATIC: return REGEX_RELEASE_STATIC; - case BuildTypeC::RELEASE_DYNAMIC: return REGEX_RELEASE_DYNAMIC; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - - const std::string& BuildType::to_string() const - { - static const std::string NAME_DEBUG_STATIC("Debug,Static"); - static const std::string NAME_DEBUG_DYNAMIC("Debug,Dynamic"); - static const std::string NAME_RELEASE_STATIC("Release,Static"); - static const std::string NAME_RELEASE_DYNAMIC("Release,Dynamic"); - - switch (backing_enum) - { - case BuildTypeC::DEBUG_STATIC: return NAME_DEBUG_STATIC; - case BuildTypeC::DEBUG_DYNAMIC: return NAME_DEBUG_DYNAMIC; - case BuildTypeC::RELEASE_STATIC: return NAME_RELEASE_STATIC; - case BuildTypeC::RELEASE_DYNAMIC: return NAME_RELEASE_DYNAMIC; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } -} diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp deleted file mode 100644 index 0f1a38d19..000000000 --- a/toolsrc/src/SourceParagraph.cpp +++ /dev/null @@ -1,262 +0,0 @@ -#include "pch.h" - -#include "PackageSpec.h" -#include "SourceParagraph.h" -#include "Triplet.h" -#include "vcpkg_Checks.h" -#include "vcpkg_Maps.h" -#include "vcpkg_System.h" -#include "vcpkg_Util.h" -#include "vcpkg_expected.h" - -namespace vcpkg -{ - using namespace vcpkg::Parse; - - namespace Fields - { - static const std::string BUILD_DEPENDS = "Build-Depends"; - static const std::string DEFAULTFEATURES = "Default-Features"; - static const std::string DESCRIPTION = "Description"; - static const std::string FEATURE = "Feature"; - static const std::string MAINTAINER = "Maintainer"; - static const std::string SOURCE = "Source"; - static const std::string SUPPORTS = "Supports"; - static const std::string VERSION = "Version"; - } - - static Span get_list_of_valid_fields() - { - static const std::string valid_fields[] = { - Fields::SOURCE, - Fields::VERSION, - Fields::DESCRIPTION, - Fields::MAINTAINER, - Fields::BUILD_DEPENDS, - }; - - return valid_fields; - } - - void print_error_message(Span> error_info_list) - { - Checks::check_exit(VCPKG_LINE_INFO, error_info_list.size() > 0); - - for (auto&& error_info : error_info_list) - { - Checks::check_exit(VCPKG_LINE_INFO, error_info != nullptr); - if (error_info->error) - { - System::println( - System::Color::error, "Error: while loading %s: %s", error_info->name, error_info->error.message()); - } - } - - bool have_remaining_fields = false; - for (auto&& error_info : error_info_list) - { - if (!error_info->extra_fields.empty()) - { - System::println(System::Color::error, - "Error: There are invalid fields in the control file of %s", - error_info->name); - System::println("The following fields were not expected:\n\n %s\n", - Strings::join("\n ", error_info->extra_fields)); - have_remaining_fields = true; - } - } - - if (have_remaining_fields) - { - System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", - Strings::join("\n ", get_list_of_valid_fields())); - System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); - } - - for (auto&& error_info : error_info_list) - { - if (!error_info->missing_fields.empty()) - { - System::println(System::Color::error, - "Error: There are missing fields in the control file of %s", - error_info->name); - System::println("The following fields were missing:\n\n %s\n", - Strings::join("\n ", error_info->missing_fields)); - } - } - } - - static ParseExpected parse_source_paragraph(RawParagraph&& fields) - { - ParagraphParser parser(std::move(fields)); - - auto spgh = std::make_unique(); - - parser.required_field(Fields::SOURCE, spgh->name); - parser.required_field(Fields::VERSION, spgh->version); - - spgh->description = parser.optional_field(Fields::DESCRIPTION); - spgh->maintainer = parser.optional_field(Fields::MAINTAINER); - spgh->depends = expand_qualified_dependencies(parse_comma_list(parser.optional_field(Fields::BUILD_DEPENDS))); - spgh->supports = parse_comma_list(parser.optional_field(Fields::SUPPORTS)); - spgh->default_features = parse_comma_list(parser.optional_field(Fields::DEFAULTFEATURES)); - - auto err = parser.error_info(spgh->name); - if (err) - return std::move(err); - else - return std::move(spgh); - } - - static ParseExpected parse_feature_paragraph(RawParagraph&& fields) - { - ParagraphParser parser(std::move(fields)); - - auto fpgh = std::make_unique(); - - parser.required_field(Fields::FEATURE, fpgh->name); - parser.required_field(Fields::DESCRIPTION, fpgh->description); - - fpgh->depends = expand_qualified_dependencies(parse_comma_list(parser.optional_field(Fields::BUILD_DEPENDS))); - - auto err = parser.error_info(fpgh->name); - if (err) - return std::move(err); - else - return std::move(fpgh); - } - - ParseExpected SourceControlFile::parse_control_file( - std::vector>&& control_paragraphs) - { - if (control_paragraphs.size() == 0) - { - return std::make_unique(); - } - - auto control_file = std::make_unique(); - - auto maybe_source = parse_source_paragraph(std::move(control_paragraphs.front())); - if (const auto source = maybe_source.get()) - control_file->core_paragraph = std::move(*source); - else - return std::move(maybe_source).error(); - - control_paragraphs.erase(control_paragraphs.begin()); - - for (auto&& feature_pgh : control_paragraphs) - { - auto maybe_feature = parse_feature_paragraph(std::move(feature_pgh)); - if (const auto feature = maybe_feature.get()) - control_file->feature_paragraphs.emplace_back(std::move(*feature)); - else - return std::move(maybe_feature).error(); - } - - return std::move(control_file); - } - - Dependency Dependency::parse_dependency(std::string name, std::string qualifier) - { - Dependency dep; - dep.qualifier = qualifier; - if (auto maybe_features = Features::from_string(name)) - dep.depend = *maybe_features.get(); - else - Checks::exit_with_message( - VCPKG_LINE_INFO, "error while parsing dependency: %s: %s", to_string(maybe_features.error()), name); - return dep; - } - - std::string Dependency::name() const - { - if (this->depend.features.empty()) return this->depend.name; - - const std::string features = Strings::join(",", this->depend.features); - return Strings::format("%s[%s]", this->depend.name, features); - } - - std::vector vcpkg::expand_qualified_dependencies(const std::vector& depends) - { - return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency { - auto pos = depend_string.find(' '); - if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, Strings::EMPTY); - // expect of the form "\w+ \[\w+\]" - Dependency dep; - - dep.depend.name = depend_string.substr(0, pos); - if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')') - { - // Error, but for now just slurp the entire string. - return Dependency::parse_dependency(depend_string, Strings::EMPTY); - } - dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3); - return dep; - }); - } - - std::vector filter_dependencies(const std::vector& deps, const Triplet& t) - { - std::vector ret; - for (auto&& dep : deps) - { - if (dep.qualifier.empty() || t.canonical_name().find(dep.qualifier) != std::string::npos) - { - ret.emplace_back(dep.name()); - } - } - return ret; - } - - std::vector filter_dependencies_to_specs(const std::vector& deps, const Triplet& t) - { - return FeatureSpec::from_strings_and_triplet(filter_dependencies(deps, t), t); - } - - std::string to_string(const Dependency& dep) { return dep.name(); } - - ExpectedT> Supports::parse(const std::vector& strs) - { - Supports ret; - std::vector unrecognized; - - for (auto&& str : strs) - { - if (str == "x64") - ret.architectures.push_back(Architecture::X64); - else if (str == "x86") - ret.architectures.push_back(Architecture::X86); - else if (str == "arm") - ret.architectures.push_back(Architecture::ARM); - else if (str == "windows") - ret.platforms.push_back(Platform::WINDOWS); - else if (str == "uwp") - ret.platforms.push_back(Platform::UWP); - else if (str == "v140") - ret.toolsets.push_back(ToolsetVersion::V140); - else if (str == "v141") - ret.toolsets.push_back(ToolsetVersion::V141); - else if (str == "crt-static") - ret.crt_linkages.push_back(Linkage::STATIC); - else if (str == "crt-dynamic") - ret.crt_linkages.push_back(Linkage::DYNAMIC); - else - unrecognized.push_back(str); - } - - if (unrecognized.empty()) - return std::move(ret); - else - return std::move(unrecognized); - } - - bool Supports::is_supported(Architecture arch, Platform plat, Linkage crt, ToolsetVersion tools) - { - const auto is_in_or_empty = [](auto v, auto&& c) -> bool { return c.empty() || c.end() != Util::find(c, v); }; - if (!is_in_or_empty(arch, architectures)) return false; - if (!is_in_or_empty(plat, platforms)) return false; - if (!is_in_or_empty(crt, crt_linkages)) return false; - if (!is_in_or_empty(tools, toolsets)) return false; - return true; - } -} diff --git a/toolsrc/src/StatusParagraph.cpp b/toolsrc/src/StatusParagraph.cpp deleted file mode 100644 index f8ae293c2..000000000 --- a/toolsrc/src/StatusParagraph.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "pch.h" - -#include "StatusParagraph.h" - -using namespace vcpkg::Parse; - -namespace vcpkg -{ - namespace BinaryParagraphRequiredField - { - static const std::string STATUS = "Status"; - } - - StatusParagraph::StatusParagraph() : want(Want::ERROR_STATE), state(InstallState::ERROR_STATE) {} - - void serialize(const StatusParagraph& pgh, std::string& out_str) - { - serialize(pgh.package, out_str); - out_str.append("Status: ") - .append(to_string(pgh.want)) - .append(" ok ") - .append(to_string(pgh.state)) - .push_back('\n'); - } - - StatusParagraph::StatusParagraph(std::unordered_map&& fields) - { - auto status_it = fields.find(BinaryParagraphRequiredField::STATUS); - Checks::check_exit(VCPKG_LINE_INFO, status_it != fields.end(), "Expected 'Status' field in status paragraph"); - std::string status_field = std::move(status_it->second); - fields.erase(status_it); - - this->package = BinaryParagraph(std::move(fields)); - - auto b = status_field.begin(); - const auto mark = b; - const auto e = status_field.end(); - - // Todo: improve error handling - while (b != e && *b != ' ') - ++b; - - want = [](const std::string& text) { - if (text == "unknown") return Want::UNKNOWN; - if (text == "install") return Want::INSTALL; - if (text == "hold") return Want::HOLD; - if (text == "deinstall") return Want::DEINSTALL; - if (text == "purge") return Want::PURGE; - return Want::ERROR_STATE; - }(std::string(mark, b)); - - if (std::distance(b, e) < 4) return; - b += 4; - - state = [](const std::string& text) { - if (text == "not-installed") return InstallState::NOT_INSTALLED; - if (text == "installed") return InstallState::INSTALLED; - if (text == "half-installed") return InstallState::HALF_INSTALLED; - return InstallState::ERROR_STATE; - }(std::string(b, e)); - } - - std::string to_string(InstallState f) - { - switch (f) - { - case InstallState::HALF_INSTALLED: return "half-installed"; - case InstallState::INSTALLED: return "installed"; - case InstallState::NOT_INSTALLED: return "not-installed"; - default: return "error"; - } - } - - std::string to_string(Want f) - { - switch (f) - { - case Want::DEINSTALL: return "deinstall"; - case Want::HOLD: return "hold"; - case Want::INSTALL: return "install"; - case Want::PURGE: return "purge"; - case Want::UNKNOWN: return "unknown"; - default: return "error"; - } - } -} diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp deleted file mode 100644 index aaba95eb9..000000000 --- a/toolsrc/src/StatusParagraphs.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "pch.h" - -#include "StatusParagraphs.h" -#include "vcpkg_Checks.h" -#include - -namespace vcpkg -{ - StatusParagraphs::StatusParagraphs() = default; - - StatusParagraphs::StatusParagraphs(std::vector>&& ps) - : paragraphs(std::move(ps)){}; - - StatusParagraphs::const_iterator StatusParagraphs::find(const std::string& name, const Triplet& triplet) const - { - return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { - const PackageSpec& spec = pgh->package.spec; - return spec.name() == name && spec.triplet() == triplet; - }); - } - - StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, const Triplet& triplet) - { - return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { - const PackageSpec& spec = pgh->package.spec; - return spec.name() == name && spec.triplet() == triplet; - }); - } - - std::vector*> StatusParagraphs::find_all(const std::string& name, - const Triplet& triplet) - { - std::vector*> spghs; - for (auto&& p : *this) - { - if (p->package.spec.name() == name && p->package.spec.triplet() == triplet) - { - spghs.emplace_back(&p); - } - } - return spghs; - } - - StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, - const Triplet& triplet, - const std::string& feature) - { - return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { - const PackageSpec& spec = pgh->package.spec; - return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature; - }); - } - - StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name, - const Triplet& triplet) const - { - const const_iterator it = find(name, triplet); - if (it != end() && (*it)->want == Want::INSTALL && (*it)->state == InstallState::INSTALLED) - { - return it; - } - - return end(); - } - - StatusParagraphs::iterator StatusParagraphs::insert(std::unique_ptr pgh) - { - Checks::check_exit(VCPKG_LINE_INFO, pgh != nullptr, "Inserted null paragraph"); - const PackageSpec& spec = pgh->package.spec; - const auto ptr = find(spec.name(), spec.triplet(), pgh->package.feature); - if (ptr == end()) - { - paragraphs.push_back(std::move(pgh)); - return paragraphs.rbegin(); - } - - // consume data from provided pgh. - **ptr = std::move(*pgh); - return ptr; - } - - void serialize(const StatusParagraphs& pghs, std::string& out_str) - { - for (auto& pgh : pghs.paragraphs) - { - serialize(*pgh, out_str); - out_str.push_back('\n'); - } - } -} diff --git a/toolsrc/src/VcpkgCmdArguments.cpp b/toolsrc/src/VcpkgCmdArguments.cpp deleted file mode 100644 index cb261930e..000000000 --- a/toolsrc/src/VcpkgCmdArguments.cpp +++ /dev/null @@ -1,283 +0,0 @@ -#include "pch.h" - -#include "VcpkgCmdArguments.h" -#include "metrics.h" -#include "vcpkg_Commands.h" -#include "vcpkg_GlobalState.h" -#include "vcpkg_System.h" - -namespace vcpkg -{ - static void parse_value(const std::string* arg_begin, - const std::string* arg_end, - const std::string& option_name, - std::unique_ptr& option_field) - { - if (arg_begin == arg_end) - { - System::println(System::Color::error, "Error: expected value after %s", option_name); - Metrics::g_metrics.lock()->track_property("error", "error option name"); - Commands::Help::print_usage(); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - if (option_field != nullptr) - { - System::println(System::Color::error, "Error: %s specified multiple times", option_name); - Metrics::g_metrics.lock()->track_property("error", "error option specified multiple times"); - Commands::Help::print_usage(); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - option_field = std::make_unique(*arg_begin); - } - - static void parse_switch(bool new_setting, const std::string& option_name, Optional& option_field) - { - if (option_field && option_field != new_setting) - { - System::println(System::Color::error, "Error: conflicting values specified for --%s", option_name); - Metrics::g_metrics.lock()->track_property("error", "error conflicting switches"); - Commands::Help::print_usage(); - Checks::exit_fail(VCPKG_LINE_INFO); - } - option_field = new_setting; - } - - VcpkgCmdArguments VcpkgCmdArguments::create_from_command_line(const int argc, const wchar_t* const* const argv) - { - std::vector v; - for (int i = 1; i < argc; ++i) - { - v.push_back(Strings::to_utf8(argv[i])); - } - - return VcpkgCmdArguments::create_from_arg_sequence(v.data(), v.data() + v.size()); - } - - VcpkgCmdArguments VcpkgCmdArguments::create_from_arg_sequence(const std::string* arg_begin, - const std::string* arg_end) - { - VcpkgCmdArguments args; - - for (; arg_begin != arg_end; ++arg_begin) - { - std::string arg = *arg_begin; - - if (arg.empty()) - { - continue; - } - - if (arg[0] == '-' && arg[1] != '-') - { - Metrics::g_metrics.lock()->track_property("error", "error short options are not supported"); - Checks::exit_with_message(VCPKG_LINE_INFO, "Error: short options are not supported: %s", arg); - } - - if (arg[0] == '-' && arg[1] == '-') - { - // make argument case insensitive - auto& f = std::use_facet>(std::locale()); - f.tolower(&arg[0], &arg[0] + arg.size()); - // command switch - if (arg == "--vcpkg-root") - { - ++arg_begin; - parse_value(arg_begin, arg_end, "--vcpkg-root", args.vcpkg_root_dir); - continue; - } - if (arg == "--triplet") - { - ++arg_begin; - parse_value(arg_begin, arg_end, "--triplet", args.triplet); - continue; - } - if (arg == "--debug") - { - parse_switch(true, "debug", args.debug); - continue; - } - if (arg == "--sendmetrics") - { - parse_switch(true, "sendmetrics", args.sendmetrics); - continue; - } - if (arg == "--printmetrics") - { - parse_switch(true, "printmetrics", args.printmetrics); - continue; - } - if (arg == "--no-sendmetrics") - { - parse_switch(false, "sendmetrics", args.sendmetrics); - continue; - } - if (arg == "--no-printmetrics") - { - parse_switch(false, "printmetrics", args.printmetrics); - continue; - } - if (arg == "--featurepackages") - { - GlobalState::feature_packages = true; - continue; - } - - const auto eq_pos = arg.find('='); - if (eq_pos != std::string::npos) - { - args.optional_command_arguments.emplace(arg.substr(0, eq_pos), arg.substr(eq_pos + 1)); - } - else - { - args.optional_command_arguments.emplace(arg, nullopt); - } - continue; - } - - if (args.command.empty()) - { - args.command = arg; - } - else - { - args.command_arguments.push_back(arg); - } - } - - return args; - } - - ParsedArguments VcpkgCmdArguments::check_and_get_optional_command_arguments( - const std::vector& valid_switches, const std::vector& valid_settings) const - { - bool failed = false; - ParsedArguments output; - - auto options_copy = this->optional_command_arguments; - for (const std::string& option : valid_switches) - { - const auto it = options_copy.find(option); - if (it != options_copy.end()) - { - if (it->second.has_value()) - { - // Having a string value indicates it was passed like '--a=xyz' - System::println(System::Color::error, "The option '%s' does not accept an argument.", option); - failed = true; - } - else - { - output.switches.insert(option); - options_copy.erase(it); - } - } - } - - for (const std::string& option : valid_settings) - { - const auto it = options_copy.find(option); - if (it != options_copy.end()) - { - if (!it->second.has_value()) - { - // Not having a string value indicates it was passed like '--a' - System::println(System::Color::error, "The option '%s' must be passed an argument.", option); - failed = true; - } - else - { - output.settings.emplace(option, it->second.value_or_exit(VCPKG_LINE_INFO)); - options_copy.erase(it); - } - } - } - - if (!options_copy.empty()) - { - System::println(System::Color::error, "Unknown option(s) for command '%s':", this->command); - for (auto&& option : options_copy) - { - System::println(" %s", option.first); - } - System::println("\nValid options are:", this->command); - for (auto&& option : valid_switches) - { - System::println(" %s", option); - } - for (auto&& option : valid_settings) - { - System::println(" %s=...", option); - } - System::println(" --triplet "); - System::println(" --vcpkg-root "); - - Checks::exit_fail(VCPKG_LINE_INFO); - } - if (failed) Checks::exit_fail(VCPKG_LINE_INFO); - - return output; - } - - void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count) const - { - return check_max_arg_count(expected_arg_count, Strings::EMPTY); - } - - void VcpkgCmdArguments::check_min_arg_count(const size_t expected_arg_count) const - { - return check_min_arg_count(expected_arg_count, Strings::EMPTY); - } - - void VcpkgCmdArguments::check_exact_arg_count(const size_t expected_arg_count) const - { - return check_exact_arg_count(expected_arg_count, Strings::EMPTY); - } - - void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count, const std::string& example_text) const - { - const size_t actual_arg_count = command_arguments.size(); - if (actual_arg_count > expected_arg_count) - { - System::println(System::Color::error, - "Error: `%s` requires at most %u arguments, but %u were provided", - this->command, - expected_arg_count, - actual_arg_count); - System::print(example_text); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - - void VcpkgCmdArguments::check_min_arg_count(const size_t expected_arg_count, const std::string& example_text) const - { - const size_t actual_arg_count = command_arguments.size(); - if (actual_arg_count < expected_arg_count) - { - System::println(System::Color::error, - "Error: `%s` requires at least %u arguments, but %u were provided", - this->command, - expected_arg_count, - actual_arg_count); - System::print(example_text); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - - void VcpkgCmdArguments::check_exact_arg_count(const size_t expected_arg_count, - const std::string& example_text) const - { - const size_t actual_arg_count = command_arguments.size(); - if (actual_arg_count != expected_arg_count) - { - System::println(System::Color::error, - "Error: `%s` requires %u arguments, but %u were provided", - this->command, - expected_arg_count, - actual_arg_count); - System::print(example_text); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } -} diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp deleted file mode 100644 index d14002e47..000000000 --- a/toolsrc/src/VcpkgPaths.cpp +++ /dev/null @@ -1,519 +0,0 @@ -#include "pch.h" - -#include "PackageSpec.h" -#include "VcpkgPaths.h" -#include "metrics.h" -#include "vcpkg_Files.h" -#include "vcpkg_System.h" -#include "vcpkg_Util.h" -#include "vcpkg_expected.h" - -namespace vcpkg -{ - static constexpr CWStringView V_120 = L"v120"; - static constexpr CWStringView V_140 = L"v140"; - static constexpr CWStringView V_141 = L"v141"; - - static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd, - const std::array& expected_version) - { - static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###"); - - const auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s)", version_cmd)); - if (rc.exit_code != 0) - { - return false; - } - - std::match_results match; - const auto found = std::regex_search(rc.output, match, RE); - if (!found) - { - return false; - } - - const int d1 = atoi(match[1].str().c_str()); - const int d2 = atoi(match[2].str().c_str()); - const int d3 = atoi(match[3].str().c_str()); - if (d1 > expected_version[0] || (d1 == expected_version[0] && d2 > expected_version[1]) || - (d1 == expected_version[0] && d2 == expected_version[1] && d3 >= expected_version[2])) - { - // satisfactory version found - return true; - } - - return false; - } - - static Optional find_if_has_equal_or_greater_version(const std::vector& candidate_paths, - const std::wstring& version_check_arguments, - const std::array& expected_version) - { - auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { - const std::wstring cmd = Strings::wformat(LR"("%s" %s)", p.native(), version_check_arguments); - return exists_and_has_equal_or_greater_version(cmd, expected_version); - }); - - if (it != candidate_paths.cend()) - { - return std::move(*it); - } - - return nullopt; - } - - static fs::path fetch_dependency(const fs::path& scripts_folder, - const std::wstring& tool_name, - const fs::path& expected_downloaded_path, - const std::array& version) - { - const std::string tool_name_utf8 = Strings::to_utf8(tool_name); - const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); - System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", - tool_name_utf8, - version_as_string, - tool_name_utf8, - version_as_string); - const fs::path script = scripts_folder / "fetchDependency.ps1"; - const auto install_cmd = - System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name)); - const System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd); - if (rc.exit_code) - { - System::println(System::Color::error, - "Launching powershell failed or was denied when trying to fetch %s version %s.\n" - "(No sufficient installed version was found)", - tool_name_utf8, - version_as_string); - { - auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_property("error", "powershell install failed"); - locked_metrics->track_property("dependency", tool_name); - } - Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); - } - - const fs::path actual_downloaded_path = Strings::trimmed(rc.output); - std::error_code ec; - const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - eq && !ec, - "Expected dependency downloaded path to be %s, but was %s", - expected_downloaded_path.u8string(), - actual_downloaded_path.u8string()); - return actual_downloaded_path; - } - - static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) - { - static constexpr std::array EXPECTED_VERSION = {3, 9, 3}; - static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; - - const fs::path downloaded_copy = downloads_folder / "cmake-3.9.3-win32-x86" / "bin" / "cmake.exe"; - const std::vector from_path = Files::find_from_PATH(L"cmake"); - - std::vector candidate_paths; - candidate_paths.push_back(downloaded_copy); - candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - candidate_paths.push_back(System::get_program_files_platform_bitness() / "CMake" / "bin" / "cmake.exe"); - candidate_paths.push_back(System::get_program_files_32_bit() / "CMake" / "bin"); - - const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); - if (const auto p = path.get()) - { - return *p; - } - - return fetch_dependency(scripts_folder, L"cmake", downloaded_copy, EXPECTED_VERSION); - } - - fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) - { - static constexpr std::array EXPECTED_VERSION = {4, 3, 0}; - static const std::wstring VERSION_CHECK_ARGUMENTS = Strings::WEMPTY; - - const fs::path downloaded_copy = downloads_folder / "nuget-4.3.0" / "nuget.exe"; - const std::vector from_path = Files::find_from_PATH(L"nuget"); - - std::vector candidate_paths; - candidate_paths.push_back(downloaded_copy); - candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - - auto path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); - if (const auto p = path.get()) - { - return *p; - } - - return fetch_dependency(scripts_folder, L"nuget", downloaded_copy, EXPECTED_VERSION); - } - - fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) - { - static constexpr std::array EXPECTED_VERSION = {2, 14, 1}; - static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; - - const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.1-32-bit" / "cmd" / "git.exe"; - const std::vector from_path = Files::find_from_PATH(L"git"); - - std::vector candidate_paths; - candidate_paths.push_back(downloaded_copy); - candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - candidate_paths.push_back(System::get_program_files_platform_bitness() / "git" / "cmd" / "git.exe"); - candidate_paths.push_back(System::get_program_files_32_bit() / "git" / "cmd" / "git.exe"); - - const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); - if (const auto p = path.get()) - { - return *p; - } - - return fetch_dependency(scripts_folder, L"git", downloaded_copy, EXPECTED_VERSION); - } - - static fs::path get_ifw_installerbase_path(const fs::path& downloads_folder, const fs::path& scripts_folder) - { - static constexpr std::array EXPECTED_VERSION = {3, 1, 81}; - static const std::wstring VERSION_CHECK_ARGUMENTS = L"--framework-version"; - - const fs::path downloaded_copy = - downloads_folder / "QtInstallerFramework-win-x86" / "bin" / "installerbase.exe"; - - std::vector candidate_paths; - candidate_paths.push_back(downloaded_copy); - // TODO: Uncomment later - // const std::vector from_path = Files::find_from_PATH(L"installerbase"); - // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / - // "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe"); - // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / - // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); - - const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); - if (const auto p = path.get()) - { - return *p; - } - - return fetch_dependency(scripts_folder, L"installerbase", downloaded_copy, EXPECTED_VERSION); - } - - Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir) - { - std::error_code ec; - const fs::path canonical_vcpkg_root_dir = fs::stdfs::canonical(vcpkg_root_dir, ec); - if (ec) - { - return ec; - } - - VcpkgPaths paths; - paths.root = canonical_vcpkg_root_dir; - - if (paths.root.empty()) - { - Metrics::g_metrics.lock()->track_property("error", "Invalid vcpkg root directory"); - Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid vcpkg root directory: %s", paths.root.string()); - } - - paths.packages = paths.root / "packages"; - paths.buildtrees = paths.root / "buildtrees"; - paths.downloads = paths.root / "downloads"; - paths.ports = paths.root / "ports"; - paths.installed = paths.root / "installed"; - paths.triplets = paths.root / "triplets"; - paths.scripts = paths.root / "scripts"; - - paths.buildsystems = paths.scripts / "buildsystems"; - paths.buildsystems_msbuild_targets = paths.buildsystems / "msbuild" / "vcpkg.targets"; - - paths.vcpkg_dir = paths.installed / "vcpkg"; - paths.vcpkg_dir_status_file = paths.vcpkg_dir / "status"; - paths.vcpkg_dir_info = paths.vcpkg_dir / "info"; - paths.vcpkg_dir_updates = paths.vcpkg_dir / "updates"; - - paths.ports_cmake = paths.scripts / "ports.cmake"; - - return paths; - } - - fs::path VcpkgPaths::package_dir(const PackageSpec& spec) const { return this->packages / spec.dir(); } - - fs::path VcpkgPaths::port_dir(const PackageSpec& spec) const { return this->ports / spec.name(); } - fs::path VcpkgPaths::port_dir(const std::string& name) const { return this->ports / name; } - - fs::path VcpkgPaths::build_info_file_path(const PackageSpec& spec) const - { - return this->package_dir(spec) / "BUILD_INFO"; - } - - fs::path VcpkgPaths::listfile_path(const BinaryParagraph& pgh) const - { - return this->vcpkg_dir_info / (pgh.fullstem() + ".list"); - } - - bool VcpkgPaths::is_valid_triplet(const Triplet& t) const - { - for (auto&& path : get_filesystem().get_files_non_recursive(this->triplets)) - { - const std::string triplet_file_name = path.stem().generic_u8string(); - if (t.canonical_name() == triplet_file_name) // TODO: fuzzy compare - { - // t.value = triplet_file_name; // NOTE: uncomment when implementing fuzzy compare - return true; - } - } - return false; - } - - const fs::path& VcpkgPaths::get_cmake_exe() const - { - return this->cmake_exe.get_lazy([this]() { return get_cmake_path(this->downloads, this->scripts); }); - } - - const fs::path& VcpkgPaths::get_git_exe() const - { - return this->git_exe.get_lazy([this]() { return get_git_path(this->downloads, this->scripts); }); - } - - const fs::path& VcpkgPaths::get_nuget_exe() const - { - return this->nuget_exe.get_lazy([this]() { return get_nuget_path(this->downloads, this->scripts); }); - } - - const fs::path& VcpkgPaths::get_ifw_installerbase_exe() const - { - return this->ifw_installerbase_exe.get_lazy( - [this]() { return get_ifw_installerbase_path(this->downloads, this->scripts); }); - } - - const fs::path& VcpkgPaths::get_ifw_binarycreator_exe() const - { - return this->ifw_binarycreator_exe.get_lazy( - [this]() { return get_ifw_installerbase_exe().parent_path() / "binarycreator.exe"; }); - } - - const fs::path& VcpkgPaths::get_ifw_repogen_exe() const - { - return this->ifw_repogen_exe.get_lazy( - [this]() { return get_ifw_installerbase_exe().parent_path() / "repogen.exe"; }); - } - - struct VisualStudioInstance - { - fs::path root_path; - std::string version; - std::string release_type; - std::string preference_weight; // Mostly unused, just for verification that order is as intended - - std::string major_version() const { return version.substr(0, 2); } - }; - - static std::vector get_visual_studio_instances(const VcpkgPaths& paths) - { - const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; - const std::wstring cmd = System::create_powershell_script_cmd(script); - const System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); - Checks::check_exit( - VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect Visual Studio instances"); - - const std::vector instances_as_strings = Strings::split(ec_data.output, "\n"); - std::vector output; - for (const std::string& instance_as_string : instances_as_strings) - { - const std::vector split = Strings::split(instance_as_string, "::"); - output.push_back({split.at(3), split.at(2), split.at(1), split.at(0)}); - } - - return output; - } - - static std::vector find_toolset_instances(const VcpkgPaths& paths) - { - using CPU = System::CPUArchitecture; - - const auto& fs = paths.get_filesystem(); - - // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. - std::vector paths_examined; - - std::vector found_toolsets; - - const std::vector vs_instances = get_visual_studio_instances(paths); - const bool v140_is_available = Util::find_if(vs_instances, [&](const VisualStudioInstance& vs_instance) { - return vs_instance.major_version() == "14"; - }) != vs_instances.cend(); - - for (const VisualStudioInstance& vs_instance : vs_instances) - { - const std::string major_version = vs_instance.major_version(); - if (major_version == "15") - { - const fs::path vc_dir = vs_instance.root_path / "VC"; - - // Skip any instances that do not have vcvarsall. - const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build"; - const fs::path vcvarsall_bat = vcvarsall_dir / "vcvarsall.bat"; - paths_examined.push_back(vcvarsall_bat); - if (!fs.exists(vcvarsall_bat)) continue; - - // Get all supported architectures - std::vector supported_architectures; - if (fs.exists(vcvarsall_dir / "vcvars32.bat")) - supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvars64.bat")) - supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) - supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) - supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) - supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) - supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); - - // Locate the "best" MSVC toolchain version - const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; - std::vector msvc_subdirectories = fs.get_files_non_recursive(msvc_path); - Util::unstable_keep_if(msvc_subdirectories, - [&fs](const fs::path& path) { return fs.is_directory(path); }); - - // Sort them so that latest comes first - std::sort( - msvc_subdirectories.begin(), - msvc_subdirectories.end(), - [](const fs::path& left, const fs::path& right) { return left.filename() > right.filename(); }); - - for (const fs::path& subdir : msvc_subdirectories) - { - const fs::path dumpbin_path = subdir / "bin" / "HostX86" / "x86" / "dumpbin.exe"; - paths_examined.push_back(dumpbin_path); - if (fs.exists(dumpbin_path)) - { - found_toolsets.push_back(Toolset{ - vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}); - - if (v140_is_available) - { - found_toolsets.push_back(Toolset{vs_instance.root_path, - dumpbin_path, - vcvarsall_bat, - {L"-vcvars_ver=14.0"}, - V_140, - supported_architectures}); - } - - break; - } - } - - continue; - } - - if (major_version == "14") - { - const fs::path vcvarsall_bat = vs_instance.root_path / "VC" / "vcvarsall.bat"; - - paths_examined.push_back(vcvarsall_bat); - if (fs.exists(vcvarsall_bat)) - { - const fs::path vs2015_dumpbin_exe = vs_instance.root_path / "VC" / "bin" / "dumpbin.exe"; - paths_examined.push_back(vs2015_dumpbin_exe); - - const fs::path vs2015_bin_dir = vcvarsall_bat.parent_path() / "bin"; - std::vector supported_architectures; - if (fs.exists(vs2015_bin_dir / "vcvars32.bat")) - supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); - if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat")) - supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); - if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) - supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); - if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) - supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); - if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) - supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); - if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) - supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); - - if (fs.exists(vs2015_dumpbin_exe)) - { - found_toolsets.push_back({vs_instance.root_path, - vs2015_dumpbin_exe, - vcvarsall_bat, - {}, - V_140, - supported_architectures}); - } - } - } - } - - if (found_toolsets.empty()) - { - System::println(System::Color::error, "Could not locate a complete toolset."); - System::println("The following paths were examined:"); - for (const fs::path& path : paths_examined) - { - System::println(" %s", path.u8string()); - } - Checks::exit_fail(VCPKG_LINE_INFO); - } - - return found_toolsets; - } - - const Toolset& VcpkgPaths::get_toolset(const Optional& toolset_version, - const Optional& visual_studio_path) const - { - // Invariant: toolsets are non-empty and sorted with newest at back() - const std::vector& vs_toolsets = - this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); - - std::vector candidates = Util::element_pointers(vs_toolsets); - const auto tsv = toolset_version.get(); - const auto vsp = visual_studio_path.get(); - - if (tsv && vsp) - { - const std::wstring w_toolset_version = Strings::to_utf16(*tsv); - const fs::path vs_root_path = *vsp; - Util::stable_keep_if(candidates, [&](const Toolset* t) { - return w_toolset_version == t->version && vs_root_path == t->visual_studio_root_path; - }); - Checks::check_exit(VCPKG_LINE_INFO, - !candidates.empty(), - "Could not find Visual Studio instace at %s with %s toolset.", - vs_root_path.generic_string(), - *tsv); - - Checks::check_exit(VCPKG_LINE_INFO, candidates.size() == 1); - return *candidates.back(); - } - - if (tsv) - { - const std::wstring w_toolset_version = Strings::to_utf16(*tsv); - Util::stable_keep_if(candidates, [&](const Toolset* t) { return w_toolset_version == t->version; }); - Checks::check_exit( - VCPKG_LINE_INFO, !candidates.empty(), "Could not find Visual Studio instace with %s toolset.", *tsv); - } - - if (vsp) - { - const fs::path vs_root_path = *vsp; - Util::stable_keep_if(candidates, - [&](const Toolset* t) { return vs_root_path == t->visual_studio_root_path; }); - Checks::check_exit(VCPKG_LINE_INFO, - !candidates.empty(), - "Could not find Visual Studio instace at %s.", - vs_root_path.generic_string()); - } - - return *candidates.front(); - } - - Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); } -} diff --git a/toolsrc/src/VersionT.cpp b/toolsrc/src/VersionT.cpp deleted file mode 100644 index 738d2ce88..000000000 --- a/toolsrc/src/VersionT.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "pch.h" - -#include "VersionT.h" -#include "vcpkg_Strings.h" - -namespace vcpkg -{ - VersionT::VersionT() : value("0.0.0") {} - VersionT::VersionT(const std::string& value) : value(value) {} - std::string VersionT::to_string() const { return value; } - bool operator==(const VersionT& left, const VersionT& right) { return left.value == right.value; } - bool operator!=(const VersionT& left, const VersionT& right) { return left.value != right.value; } - std::string to_printf_arg(const VersionT& version) { return version.value; } - - VersionDiff::VersionDiff() : left(), right() {} - VersionDiff::VersionDiff(const VersionT& left, const VersionT& right) : left(left), right(right) {} - - std::string VersionDiff::to_string() const { return Strings::format("%s -> %s", left.value, right.value); } -} diff --git a/toolsrc/src/coff_file_reader.cpp b/toolsrc/src/coff_file_reader.cpp deleted file mode 100644 index bb3a6cefd..000000000 --- a/toolsrc/src/coff_file_reader.cpp +++ /dev/null @@ -1,308 +0,0 @@ -#include "pch.h" - -#include "coff_file_reader.h" -#include "vcpkg_Checks.h" - -using namespace std; - -namespace vcpkg::CoffFileReader -{ - template - static T reinterpret_bytes(const char* data) - { - return (*reinterpret_cast(&data[0])); - } - - template - static T read_value_from_stream(fstream& fs) - { - T data; - fs.read(reinterpret_cast(&data), sizeof data); - return data; - } - - template - static T peek_value_from_stream(fstream& fs) - { - const fpos_t original_pos = fs.tellg().seekpos(); - T data; - fs.read(reinterpret_cast(&data), sizeof data); - fs.seekg(original_pos); - return data; - } - - static void verify_equal_strings( - const LineInfo& line_info, const char* expected, const char* actual, int size, const char* label) - { - Checks::check_exit(line_info, - memcmp(expected, actual, size) == 0, - "Incorrect string (%s) found. Expected: (%s) but found (%s)", - label, - expected, - actual); - } - - static void read_and_verify_PE_signature(fstream& fs) - { - static const size_t OFFSET_TO_PE_SIGNATURE_OFFSET = 0x3c; - - static const char* PE_SIGNATURE = "PE\0\0"; - static const size_t PE_SIGNATURE_SIZE = 4; - - fs.seekg(OFFSET_TO_PE_SIGNATURE_OFFSET, ios_base::beg); - const int32_t offset_to_PE_signature = read_value_from_stream(fs); - - fs.seekg(offset_to_PE_signature); - char signature[PE_SIGNATURE_SIZE]; - fs.read(signature, PE_SIGNATURE_SIZE); - verify_equal_strings(VCPKG_LINE_INFO, PE_SIGNATURE, signature, PE_SIGNATURE_SIZE, "PE_SIGNATURE"); - fs.seekg(offset_to_PE_signature + PE_SIGNATURE_SIZE, ios_base::beg); - } - - static fpos_t align_to_size(const uint64_t unaligned, const uint64_t alignment_size) - { - fpos_t aligned = unaligned - 1; - aligned /= alignment_size; - aligned += 1; - aligned *= alignment_size; - return aligned; - } - - struct CoffFileHeader - { - static const size_t HEADER_SIZE = 20; - - static CoffFileHeader read(fstream& fs) - { - CoffFileHeader ret; - ret.data.resize(HEADER_SIZE); - fs.read(&ret.data[0], HEADER_SIZE); - return ret; - } - - MachineType machine_type() const - { - static const size_t MACHINE_TYPE_OFFSET = 0; - static const size_t MACHINE_TYPE_SIZE = 2; - - std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE); - const uint16_t machine = reinterpret_bytes(machine_field_as_string.c_str()); - return to_machine_type(machine); - } - - private: - std::string data; - }; - - struct ArchiveMemberHeader - { - static const size_t HEADER_SIZE = 60; - - static ArchiveMemberHeader read(fstream& fs) - { - static const size_t HEADER_END_OFFSET = 58; - static const char* HEADER_END = "`\n"; - static const size_t HEADER_END_SIZE = 2; - - ArchiveMemberHeader ret; - ret.data.resize(HEADER_SIZE); - fs.read(&ret.data[0], HEADER_SIZE); - - if (ret.data[0] != '\0') // Due to freeglut. github issue #223 - { - const std::string header_end = ret.data.substr(HEADER_END_OFFSET, HEADER_END_SIZE); - verify_equal_strings( - VCPKG_LINE_INFO, HEADER_END, header_end.c_str(), HEADER_END_SIZE, "LIB HEADER_END"); - } - - return ret; - } - - std::string name() const - { - static const size_t HEADER_NAME_OFFSET = 0; - static const size_t HEADER_NAME_SIZE = 16; - return data.substr(HEADER_NAME_OFFSET, HEADER_NAME_SIZE); - } - - uint64_t member_size() const - { - static const size_t ALIGNMENT_SIZE = 2; - - static const size_t HEADER_SIZE_OFFSET = 48; - static const size_t HEADER_SIZE_FIELD_SIZE = 10; - const std::string as_string = data.substr(HEADER_SIZE_OFFSET, HEADER_SIZE_FIELD_SIZE); - // This is in ASCII decimal representation - const uint64_t value = std::strtoull(as_string.c_str(), nullptr, 10); - - const uint64_t aligned = align_to_size(value, ALIGNMENT_SIZE); - return aligned; - } - - std::string data; - }; - - struct OffsetsArray - { - static OffsetsArray read(fstream& fs, const uint32_t offset_count) - { - static const size_t OFFSET_WIDTH = 4; - - std::string raw_offsets; - const size_t raw_offset_size = offset_count * OFFSET_WIDTH; - raw_offsets.resize(raw_offset_size); - fs.read(&raw_offsets[0], raw_offset_size); - - OffsetsArray ret; - for (uint32_t i = 0; i < offset_count; ++i) - { - const std::string value_as_string = raw_offsets.substr(OFFSET_WIDTH * i, OFFSET_WIDTH * (i + 1)); - const uint32_t value = reinterpret_bytes(value_as_string.c_str()); - - // Ignore offsets that point to offset 0. See vcpkg github #223 #288 #292 - if (value != 0) - { - ret.data.push_back(value); - } - } - - // Sort the offsets, because it is possible for them to be unsorted. See vcpkg github #292 - std::sort(ret.data.begin(), ret.data.end()); - return ret; - } - - std::vector data; - }; - - struct ImportHeader - { - static const size_t HEADER_SIZE = 20; - - static ImportHeader read(fstream& fs) - { - static const size_t SIG1_OFFSET = 0; - static const uint16_t SIG1 = static_cast(MachineType::UNKNOWN); - static const size_t SIG1_SIZE = 2; - - static const size_t SIG2_OFFSET = 2; - static const uint16_t SIG2 = 0xFFFF; - static const size_t SIG2_SIZE = 2; - - ImportHeader ret; - ret.data.resize(HEADER_SIZE); - fs.read(&ret.data[0], HEADER_SIZE); - - const std::string sig1_as_string = ret.data.substr(SIG1_OFFSET, SIG1_SIZE); - const uint16_t sig1 = reinterpret_bytes(sig1_as_string.c_str()); - Checks::check_exit(VCPKG_LINE_INFO, sig1 == SIG1, "Sig1 was incorrect. Expected %s but got %s", SIG1, sig1); - - const std::string sig2_as_string = ret.data.substr(SIG2_OFFSET, SIG2_SIZE); - const uint16_t sig2 = reinterpret_bytes(sig2_as_string.c_str()); - Checks::check_exit(VCPKG_LINE_INFO, sig2 == SIG2, "Sig2 was incorrect. Expected %s but got %s", SIG2, sig2); - - return ret; - } - - MachineType machine_type() const - { - static const size_t MACHINE_TYPE_OFFSET = 6; - static const size_t MACHINE_TYPE_SIZE = 2; - - std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE); - const uint16_t machine = reinterpret_bytes(machine_field_as_string.c_str()); - return to_machine_type(machine); - } - - private: - std::string data; - }; - - static void read_and_verify_archive_file_signature(fstream& fs) - { - static const char* FILE_START = "!\n"; - static const size_t FILE_START_SIZE = 8; - - fs.seekg(fs.beg); - - char file_start[FILE_START_SIZE]; - fs.read(file_start, FILE_START_SIZE); - verify_equal_strings(VCPKG_LINE_INFO, FILE_START, file_start, FILE_START_SIZE, "LIB FILE_START"); - } - - DllInfo read_dll(const fs::path& path) - { - std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate); - Checks::check_exit(VCPKG_LINE_INFO, fs.is_open(), "Could not open file %s for reading", path.generic_string()); - - read_and_verify_PE_signature(fs); - CoffFileHeader header = CoffFileHeader::read(fs); - const MachineType machine = header.machine_type(); - return {machine}; - } - - struct Marker - { - void set_to_offset(const fpos_t position) { this->m_absolute_position = position; } - - void set_to_current_pos(fstream& fs) { this->m_absolute_position = fs.tellg().seekpos(); } - - void seek_to_marker(fstream& fs) const { fs.seekg(this->m_absolute_position, ios_base::beg); } - - void advance_by(const uint64_t offset) { this->m_absolute_position += offset; } - - private: - fpos_t m_absolute_position = 0; - }; - - LibInfo read_lib(const fs::path& path) - { - std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate); - Checks::check_exit(VCPKG_LINE_INFO, fs.is_open(), "Could not open file %s for reading", path.generic_string()); - - read_and_verify_archive_file_signature(fs); - - Marker marker; - marker.set_to_current_pos(fs); - - // First Linker Member - const ArchiveMemberHeader first_linker_member_header = ArchiveMemberHeader::read(fs); - Checks::check_exit(VCPKG_LINE_INFO, - first_linker_member_header.name().substr(0, 2) == "/ ", - "Could not find proper first linker member"); - marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + first_linker_member_header.member_size()); - marker.seek_to_marker(fs); - - const ArchiveMemberHeader second_linker_member_header = ArchiveMemberHeader::read(fs); - Checks::check_exit(VCPKG_LINE_INFO, - second_linker_member_header.name().substr(0, 2) == "/ ", - "Could not find proper second linker member"); - // The first 4 bytes contains the number of archive members - const uint32_t archive_member_count = read_value_from_stream(fs); - const OffsetsArray offsets = OffsetsArray::read(fs, archive_member_count); - marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + second_linker_member_header.member_size()); - marker.seek_to_marker(fs); - - const bool hasLongnameMemberHeader = peek_value_from_stream(fs) == 0x2F2F; - if (hasLongnameMemberHeader) - { - const ArchiveMemberHeader longnames_member_header = ArchiveMemberHeader::read(fs); - marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + longnames_member_header.member_size()); - marker.seek_to_marker(fs); - } - - std::set machine_types; - // Next we have the obj and pseudo-object files - for (const uint32_t offset : offsets.data) - { - marker.set_to_offset(offset + ArchiveMemberHeader::HEADER_SIZE); // Skip the header, no need to read it. - marker.seek_to_marker(fs); - const uint16_t first_two_bytes = peek_value_from_stream(fs); - const bool isImportHeader = to_machine_type(first_two_bytes) == MachineType::UNKNOWN; - const MachineType machine = - isImportHeader ? ImportHeader::read(fs).machine_type() : CoffFileHeader::read(fs).machine_type(); - machine_types.insert(machine); - } - - return {std::vector(machine_types.cbegin(), machine_types.cend())}; - } -} diff --git a/toolsrc/src/commands_autocomplete.cpp b/toolsrc/src/commands_autocomplete.cpp deleted file mode 100644 index 3963f904b..000000000 --- a/toolsrc/src/commands_autocomplete.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "SortedVector.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Maps.h" -#include "vcpkg_System.h" -#include "vcpkglib.h" - -namespace vcpkg::Commands::Autocomplete -{ - std::vector autocomplete_install( - const std::vector>& source_paragraphs, const std::string& start_with) - { - std::vector results; - const auto& istartswith = Strings::case_insensitive_ascii_starts_with; - - for (const auto& source_control_file : source_paragraphs) - { - auto&& sp = *source_control_file->core_paragraph; - - if (istartswith(sp.name, start_with)) - { - results.push_back(sp.name); - } - } - return results; - } - - std::vector autocomplete_remove(std::vector installed_packages, - const std::string& start_with) - { - std::vector results; - const auto& istartswith = Strings::case_insensitive_ascii_starts_with; - - for (const auto& installed_package : installed_packages) - { - auto sp = installed_package->package.displayname(); - - if (istartswith(sp, start_with)) - { - results.push_back(sp); - } - } - return results; - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - static const std::string EXAMPLE = - Strings::format("The argument should be a command line to autocomplete.\n%s", - Commands::Help::create_example_string("autocomplete install z")); - - args.check_min_arg_count(1, EXAMPLE); - args.check_max_arg_count(2, EXAMPLE); - args.check_and_get_optional_command_arguments({}); - - const std::string requested_command = args.command_arguments.at(0); - const std::string start_with = - args.command_arguments.size() > 1 ? args.command_arguments.at(1) : Strings::EMPTY; - std::vector results; - if (requested_command == "install") - { - auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); - auto& source_paragraphs = sources_and_errors.paragraphs; - - results = autocomplete_install(source_paragraphs, start_with); - } - else if (requested_command == "remove") - { - const StatusParagraphs status_db = database_load_check(paths); - std::vector installed_packages = get_installed_ports(status_db); - results = autocomplete_remove(installed_packages, start_with); - } - - System::println(Strings::join(" ", results)); - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_available_commands.cpp b/toolsrc/src/commands_available_commands.cpp deleted file mode 100644 index d3280e6d7..000000000 --- a/toolsrc/src/commands_available_commands.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Commands.h" - -namespace vcpkg::Commands -{ - const std::vector>& get_available_commands_type_a() - { - static std::vector> t = { - {"install", &Install::perform_and_exit}, - {"ci", &CI::perform_and_exit}, - {"remove", &Remove::perform_and_exit}, - {"build", &BuildCommand::perform_and_exit}, - {"env", &Env::perform_and_exit}, - {"build-external", &BuildExternal::perform_and_exit}, - {"export", &Export::perform_and_exit}, - }; - return t; - } - - const std::vector>& get_available_commands_type_b() - { - static std::vector> t = { - {"/?", &Help::perform_and_exit}, - {"help", &Help::perform_and_exit}, - {"search", &Search::perform_and_exit}, - {"list", &List::perform_and_exit}, - {"integrate", &Integrate::perform_and_exit}, - {"owns", &Owns::perform_and_exit}, - {"update", &Update::perform_and_exit}, - {"depend-info", &DependInfo::perform_and_exit}, - {"edit", &Edit::perform_and_exit}, - {"create", &Create::perform_and_exit}, - {"import", &Import::perform_and_exit}, - {"cache", &Cache::perform_and_exit}, - {"portsdiff", &PortsDiff::perform_and_exit}, - {"autocomplete", &Autocomplete::perform_and_exit}}; - return t; - } - - const std::vector>& get_available_commands_type_c() - { - static std::vector> t = { - {"version", &Version::perform_and_exit}, - {"contact", &Contact::perform_and_exit}, - {"hash", &Hash::perform_and_exit}, - }; - return t; - } -} diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp deleted file mode 100644 index a69958058..000000000 --- a/toolsrc/src/commands_build.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "PostBuildLint.h" -#include "StatusParagraphs.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Dependencies.h" -#include "vcpkg_Enums.h" -#include "vcpkg_Input.h" -#include "vcpkg_System.h" -#include "vcpkglib.h" - -using vcpkg::Build::BuildResult; -using vcpkg::Parse::ParseControlErrorInfo; -using vcpkg::Parse::ParseExpected; - -namespace vcpkg::Commands::BuildCommand -{ - using Dependencies::InstallPlanAction; - using Dependencies::InstallPlanType; - - static const std::string OPTION_CHECKS_ONLY = "--checks-only"; - - void perform_and_exit(const FullPackageSpec& full_spec, - const fs::path& port_dir, - const std::unordered_set& options, - const VcpkgPaths& paths) - { - const PackageSpec& spec = full_spec.package_spec; - if (options.find(OPTION_CHECKS_ONLY) != options.end()) - { - const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet()); - const auto build_info = Build::read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); - const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); - Checks::check_exit(VCPKG_LINE_INFO, error_count == 0); - Checks::exit_success(VCPKG_LINE_INFO); - } - - const ParseExpected source_control_file = - Paragraphs::try_load_port(paths.get_filesystem(), port_dir); - - if (!source_control_file.has_value()) - { - print_error_message(source_control_file.error()); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - for (const std::string& str : full_spec.features) - { - System::println("%s \n", str); - } - const auto& scf = source_control_file.value_or_exit(VCPKG_LINE_INFO); - Checks::check_exit(VCPKG_LINE_INFO, - spec.name() == scf->core_paragraph->name, - "The Name: field inside the CONTROL does not match the port directory: '%s' != '%s'", - scf->core_paragraph->name, - spec.name()); - - const StatusParagraphs status_db = database_load_check(paths); - const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; - - const Build::BuildPackageConfig build_config{ - *scf->core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options}; - - const auto result = Build::build_package(paths, build_config, status_db); - if (result.code == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES) - { - System::println(System::Color::error, - "The build command requires all dependencies to be already installed."); - System::println("The following dependencies are missing:"); - System::println(); - for (const auto& p : result.unmet_dependencies) - { - System::println(" %s", p); - } - System::println(); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - if (result.code != BuildResult::SUCCEEDED) - { - System::println(System::Color::error, Build::create_error_message(result.code, spec)); - System::println(Build::create_user_troubleshooting_message(spec)); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - Checks::exit_success(VCPKG_LINE_INFO); - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) - { - static const std::string EXAMPLE = Commands::Help::create_example_string("build zlib:x64-windows"); - // Build only takes a single package and all dependencies must already be installed - args.check_exact_arg_count(1, EXAMPLE); - const std::string command_argument = args.command_arguments.at(0); - const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, EXAMPLE); - Input::check_triplet(spec.package_spec.triplet(), paths); - const std::unordered_set options = - args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}); - perform_and_exit(spec, paths.port_dir(spec.package_spec), options, paths); - } -} diff --git a/toolsrc/src/commands_build_external.cpp b/toolsrc/src/commands_build_external.cpp deleted file mode 100644 index 7e85f2250..000000000 --- a/toolsrc/src/commands_build_external.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Commands.h" -#include "vcpkg_Input.h" - -namespace vcpkg::Commands::BuildExternal -{ - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) - { - static const std::string EXAMPLE = - Commands::Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)"); - args.check_exact_arg_count(2, EXAMPLE); - const FullPackageSpec spec = - Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, EXAMPLE); - Input::check_triplet(spec.package_spec.triplet(), paths); - const std::unordered_set options = args.check_and_get_optional_command_arguments({}); - - const fs::path port_dir = args.command_arguments.at(1); - BuildCommand::perform_and_exit(spec, port_dir, options, paths); - } -} diff --git a/toolsrc/src/commands_cache.cpp b/toolsrc/src/commands_cache.cpp deleted file mode 100644 index 5b65b197f..000000000 --- a/toolsrc/src/commands_cache.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "pch.h" - -#include "BinaryParagraph.h" -#include "Paragraphs.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Files.h" -#include "vcpkg_System.h" - -namespace vcpkg::Commands::Cache -{ - static std::vector read_all_binary_paragraphs(const VcpkgPaths& paths) - { - std::vector output; - for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.packages)) - { - const Expected> pghs = - Paragraphs::get_single_paragraph(paths.get_filesystem(), path / "CONTROL"); - if (const auto p = pghs.get()) - { - const BinaryParagraph binary_paragraph = BinaryParagraph(*p); - output.push_back(binary_paragraph); - } - } - - return output; - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - static const std::string EXAMPLE = Strings::format( - "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s", - Commands::Help::create_example_string("cache png")); - args.check_max_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}); - - const std::vector binary_paragraphs = read_all_binary_paragraphs(paths); - if (binary_paragraphs.empty()) - { - System::println("No packages are cached."); - Checks::exit_success(VCPKG_LINE_INFO); - } - - if (args.command_arguments.size() == 0) - { - for (const BinaryParagraph& binary_paragraph : binary_paragraphs) - { - const std::string displayname = binary_paragraph.displayname(); - System::println(displayname); - } - } - else - { - // At this point there is 1 argument - for (const BinaryParagraph& binary_paragraph : binary_paragraphs) - { - const std::string displayname = binary_paragraph.displayname(); - if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end()) - { - continue; - } - - System::println(displayname); - } - } - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp deleted file mode 100644 index 75ff65556..000000000 --- a/toolsrc/src/commands_ci.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "vcpkg_Build.h" -#include "vcpkg_Chrono.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Dependencies.h" -#include "vcpkg_Files.h" -#include "vcpkg_Input.h" -#include "vcpkg_System.h" -#include "vcpkg_Util.h" -#include "vcpkglib.h" - -namespace vcpkg::Commands::CI -{ - using Build::BuildResult; - using Dependencies::InstallPlanAction; - using Dependencies::InstallPlanType; - - static std::vector load_all_package_specs(Files::Filesystem& fs, - const fs::path& ports_directory, - const Triplet& triplet) - { - auto ports = Paragraphs::load_all_ports(fs, ports_directory); - return Util::fmap(ports, [&](auto&& control_file) -> PackageSpec { - return PackageSpec::from_name_and_triplet(control_file->core_paragraph->name, triplet) - .value_or_exit(VCPKG_LINE_INFO); - }); - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) - { - static const std::string EXAMPLE = Commands::Help::create_example_string("ci x64-windows"); - args.check_max_arg_count(1, EXAMPLE); - const Triplet triplet = args.command_arguments.size() == 1 - ? Triplet::from_canonical_name(args.command_arguments.at(0)) - : default_triplet; - Input::check_triplet(triplet, paths); - args.check_and_get_optional_command_arguments({}); - const std::vector specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet); - - StatusParagraphs status_db = database_load_check(paths); - const auto& paths_port_file = Dependencies::PathsPortFile(paths); - std::vector install_plan = - Dependencies::create_install_plan(paths_port_file, specs, status_db); - Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); - - const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; - - const std::vector action_plan = - Util::fmap(install_plan, [](InstallPlanAction& install_action) { - return Dependencies::AnyAction(std::move(install_action)); - }); - - Install::perform_and_exit( - action_plan, install_plan_options, Install::KeepGoing::YES, Install::PrintSummary::YES, paths, status_db); - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_contact.cpp b/toolsrc/src/commands_contact.cpp deleted file mode 100644 index 8374350ee..000000000 --- a/toolsrc/src/commands_contact.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Commands.h" -#include "vcpkg_System.h" - -namespace vcpkg::Commands::Contact -{ - const std::string& email() - { - static const std::string S_EMAIL = R"(vcpkg@microsoft.com)"; - return S_EMAIL; - } - - void perform_and_exit(const VcpkgCmdArguments& args) - { - args.check_exact_arg_count(0); - args.check_and_get_optional_command_arguments({}); - - System::println("Send an email to %s with any feedback.", email()); - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_create.cpp b/toolsrc/src/commands_create.cpp deleted file mode 100644 index 6898f7399..000000000 --- a/toolsrc/src/commands_create.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Commands.h" -#include "vcpkg_Files.h" -#include "vcpkg_System.h" -#include "vcpkglib.h" - -namespace vcpkg::Commands::Create -{ - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - static const std::string EXAMPLE = Commands::Help::create_example_string( - R"###(create zlib2 http://zlib.net/zlib1211.zip "zlib1211-2.zip")###"); - args.check_max_arg_count(3, EXAMPLE); - args.check_min_arg_count(2, EXAMPLE); - args.check_and_get_optional_command_arguments({}); - const std::string port_name = args.command_arguments.at(0); - const std::string url = args.command_arguments.at(1); - - const fs::path& cmake_exe = paths.get_cmake_exe(); - - std::vector cmake_args{{L"CMD", L"CREATE"}, {L"PORT", port_name}, {L"URL", url}}; - - if (args.command_arguments.size() >= 3) - { - const std::string& zip_file_name = args.command_arguments.at(2); - Checks::check_exit(VCPKG_LINE_INFO, - !Files::has_invalid_chars_for_filesystem(zip_file_name), - R"(Filename cannot contain invalid chars %s, but was %s)", - Files::FILESYSTEM_INVALID_CHARACTERS, - zip_file_name); - cmake_args.push_back({L"FILENAME", zip_file_name}); - } - - const std::wstring cmd_launch_cmake = make_cmake_cmd(cmake_exe, paths.ports_cmake, cmake_args); - Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute_clean(cmd_launch_cmake)); - } -} diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp deleted file mode 100644 index 17cd9c881..000000000 --- a/toolsrc/src/commands_depends.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Strings.h" -#include "vcpkg_System.h" -#include "vcpkg_Util.h" - -namespace vcpkg::Commands::DependInfo -{ - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - static const std::string EXAMPLE = Commands::Help::create_example_string(R"###(depend-info [pat])###"); - args.check_max_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}); - - std::vector> source_control_files = - Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - - if (args.command_arguments.size() == 1) - { - const std::string filter = args.command_arguments.at(0); - - Util::erase_remove_if(source_control_files, - [&](const std::unique_ptr& source_control_file) { - - const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; - - if (Strings::case_insensitive_ascii_contains(source_paragraph.name, filter)) - { - return false; - } - - for (const Dependency& dependency : source_paragraph.depends) - { - if (Strings::case_insensitive_ascii_contains(dependency.name(), filter)) - { - return false; - } - } - - return true; - }); - } - - for (auto&& source_control_file : source_control_files) - { - const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; - const auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name(); }); - System::println("%s: %s", source_paragraph.name, s); - } - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp deleted file mode 100644 index 823c87534..000000000 --- a/toolsrc/src/commands_edit.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Commands.h" -#include "vcpkg_Input.h" -#include "vcpkg_System.h" - -namespace vcpkg::Commands::Edit -{ - static std::vector find_from_registry() - { - static const std::array REGKEYS = { - LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", - LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1)", - LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", - }; - - std::vector output; - for (auto&& keypath : REGKEYS) - { - const Optional code_installpath = - System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation"); - if (const auto c = code_installpath.get()) - { - const fs::path install_path = fs::path(*c); - output.push_back(install_path / "Code - Insiders.exe"); - output.push_back(install_path / "Code.exe"); - } - } - return output; - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - static const std::string OPTION_BUILDTREES = "--buildtrees"; - - static const fs::path VS_CODE_INSIDERS = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe"; - static const fs::path VS_CODE = fs::path{"Microsoft VS Code"} / "Code.exe"; - - auto& fs = paths.get_filesystem(); - - static const std::string EXAMPLE = Commands::Help::create_example_string("edit zlib"); - args.check_exact_arg_count(1, EXAMPLE); - const std::unordered_set options = - args.check_and_get_optional_command_arguments({OPTION_BUILDTREES}); - const std::string port_name = args.command_arguments.at(0); - - const fs::path portpath = paths.ports / port_name; - Checks::check_exit(VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name); - - std::vector candidate_paths; - const std::vector from_path = Files::find_from_PATH(L"EDITOR"); - candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE_INSIDERS); - candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE_INSIDERS); - candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE); - candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE); - - const std::vector from_registry = find_from_registry(); - candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend()); - - auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { return fs.exists(p); }); - if (it == candidate_paths.cend()) - { - System::println(System::Color::error, - "Error: Visual Studio Code was not found and the environment variable EDITOR is not set."); - System::println("The following paths were examined:"); - Files::print_paths(candidate_paths); - System::println("You can also set the environmental variable EDITOR to your editor of choice."); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - const fs::path env_editor = *it; - if (options.find(OPTION_BUILDTREES) != options.cend()) - { - const auto buildtrees_current_dir = paths.buildtrees / port_name; - - const std::wstring cmd_line = - Strings::wformat(LR"("%s" "%s" -n)", env_editor, buildtrees_current_dir.native()); - Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); - } - - const std::wstring cmd_line = Strings::wformat( - LR"("%s" "%s" "%s" -n)", env_editor, portpath.native(), (portpath / "portfile.cmake").native()); - Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); - } -} diff --git a/toolsrc/src/commands_env.cpp b/toolsrc/src/commands_env.cpp deleted file mode 100644 index 6dad3e882..000000000 --- a/toolsrc/src/commands_env.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Build.h" -#include "vcpkg_Commands.h" -#include "vcpkg_System.h" - -namespace vcpkg::Commands::Env -{ - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) - { - static const std::string EXAMPLE = Commands::Help::create_example_string(R"(env --Triplet x64-windows)"); - args.check_exact_arg_count(0, EXAMPLE); - args.check_and_get_optional_command_arguments({}); - - const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); - const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); - System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, toolset) + L" && cmd"); - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp deleted file mode 100644 index 20838f5a5..000000000 --- a/toolsrc/src/commands_export.cpp +++ /dev/null @@ -1,526 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Commands_Export_IFW.h" -#include "vcpkg_Dependencies.h" -#include "vcpkg_Input.h" -#include "vcpkg_System.h" -#include "vcpkg_Util.h" -#include "vcpkglib.h" -#include - -namespace vcpkg::Commands::Export -{ - using Dependencies::ExportPlanAction; - using Dependencies::ExportPlanType; - using Dependencies::RequestType; - using Install::InstallDir; - - static std::string create_nuspec_file_contents(const std::string& raw_exported_dir, - const std::string& targets_redirect_path, - const std::string& nuget_id, - const std::string& nupkg_version) - { - static constexpr auto CONTENT_TEMPLATE = R"( - - - @NUGET_ID@ - @VERSION@ - vcpkg - - Vcpkg NuGet export - - - - - - - - - -)"; - - std::string nuspec_file_content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id); - nuspec_file_content = std::regex_replace(nuspec_file_content, std::regex("@VERSION@"), nupkg_version); - nuspec_file_content = - std::regex_replace(nuspec_file_content, std::regex("@RAW_EXPORTED_DIR@"), raw_exported_dir); - nuspec_file_content = - std::regex_replace(nuspec_file_content, std::regex("@TARGETS_REDIRECT_PATH@"), targets_redirect_path); - return nuspec_file_content; - } - - static std::string create_targets_redirect(const std::string& target_path) noexcept - { - return Strings::format(R"###( - - - -)###", - target_path, - target_path); - } - - static void print_plan(const std::map>& group_by_plan_type) - { - static constexpr std::array ORDER = {ExportPlanType::ALREADY_BUILT, - ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT}; - - for (const ExportPlanType plan_type : ORDER) - { - const auto it = group_by_plan_type.find(plan_type); - if (it == group_by_plan_type.cend()) - { - continue; - } - - std::vector cont = it->second; - std::sort(cont.begin(), cont.end(), &ExportPlanAction::compare_by_name); - const std::string as_string = Strings::join("\n", cont, [](const ExportPlanAction* p) { - return Dependencies::to_output_string(p->request_type, p->spec.to_string()); - }); - - switch (plan_type) - { - case ExportPlanType::ALREADY_BUILT: - System::println("The following packages are already built and will be exported:\n%s", as_string); - continue; - case ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT: - System::println("The following packages need to be built:\n%s", as_string); - continue; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - } - - static std::string create_export_id() - { - const tm date_time = System::get_current_date_time(); - - // Format is: YYYYmmdd-HHMMSS - // 15 characters + 1 null terminating character will be written for a total of 16 chars - char mbstr[16]; - const size_t bytes_written = std::strftime(mbstr, sizeof(mbstr), "%Y%m%d-%H%M%S", &date_time); - Checks::check_exit(VCPKG_LINE_INFO, - bytes_written == 15, - "Expected 15 bytes to be written, but %u were written", - bytes_written); - const std::string date_time_as_string(mbstr); - return ("vcpkg-export-" + date_time_as_string); - } - - static fs::path do_nuget_export(const VcpkgPaths& paths, - const std::string& nuget_id, - const std::string& nuget_version, - const fs::path& raw_exported_dir, - const fs::path& output_dir) - { - Files::Filesystem& fs = paths.get_filesystem(); - const fs::path& nuget_exe = paths.get_nuget_exe(); - - // This file will be placed in "build\native" in the nuget package. Therefore, go up two dirs. - const std::string targets_redirect_content = - create_targets_redirect("../../scripts/buildsystems/msbuild/vcpkg.targets"); - const fs::path targets_redirect = paths.buildsystems / "tmp" / "vcpkg.export.nuget.targets"; - - std::error_code ec; - fs.create_directories(paths.buildsystems / "tmp", ec); - - fs.write_contents(targets_redirect, targets_redirect_content); - - const std::string nuspec_file_content = - create_nuspec_file_contents(raw_exported_dir.string(), targets_redirect.string(), nuget_id, nuget_version); - const fs::path nuspec_file_path = paths.buildsystems / "tmp" / "vcpkg.export.nuspec"; - fs.write_contents(nuspec_file_path, nuspec_file_content); - - // -NoDefaultExcludes is needed for ".vcpkg-root" - const std::wstring cmd_line = - Strings::wformat(LR"("%s" pack -OutputDirectory "%s" "%s" -NoDefaultExcludes > nul)", - nuget_exe.native(), - output_dir.native(), - nuspec_file_path.native()); - - const int exit_code = System::cmd_execute_clean(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: NuGet package creation failed"); - - const fs::path output_path = output_dir / (nuget_id + ".nupkg"); - return output_path; - } - - struct ArchiveFormat final - { - enum class BackingEnum - { - ZIP = 1, - SEVEN_ZIP, - }; - - constexpr ArchiveFormat() = delete; - - constexpr ArchiveFormat(BackingEnum backing_enum, const wchar_t* extension, const wchar_t* cmake_option) - : backing_enum(backing_enum), m_extension(extension), m_cmake_option(cmake_option) - { - } - - constexpr operator BackingEnum() const { return backing_enum; } - constexpr CWStringView extension() const { return this->m_extension; } - constexpr CWStringView cmake_option() const { return this->m_cmake_option; } - - private: - BackingEnum backing_enum; - const wchar_t* m_extension; - const wchar_t* m_cmake_option; - }; - - namespace ArchiveFormatC - { - constexpr const ArchiveFormat ZIP(ArchiveFormat::BackingEnum::ZIP, L"zip", L"zip"); - constexpr const ArchiveFormat SEVEN_ZIP(ArchiveFormat::BackingEnum::SEVEN_ZIP, L"7z", L"7zip"); - } - - static fs::path do_archive_export(const VcpkgPaths& paths, - const fs::path& raw_exported_dir, - const fs::path& output_dir, - const ArchiveFormat& format) - { - const fs::path& cmake_exe = paths.get_cmake_exe(); - - const std::wstring exported_dir_filename = raw_exported_dir.filename().native(); - const std::wstring exported_archive_filename = - Strings::wformat(L"%s.%s", exported_dir_filename, format.extension()); - const fs::path exported_archive_path = (output_dir / exported_archive_filename); - - // -NoDefaultExcludes is needed for ".vcpkg-root" - const std::wstring cmd_line = Strings::wformat(LR"("%s" -E tar "cf" "%s" --format=%s -- "%s")", - cmake_exe.native(), - exported_archive_path.native(), - format.cmake_option(), - raw_exported_dir.native()); - - const int exit_code = System::cmd_execute_clean(cmd_line); - Checks::check_exit( - VCPKG_LINE_INFO, exit_code == 0, "Error: %s creation failed", exported_archive_path.generic_string()); - return exported_archive_path; - } - - static Optional maybe_lookup(std::unordered_map const& m, - std::string const& key) - { - const auto it = m.find(key); - if (it != m.end()) return it->second; - return nullopt; - } - - void export_integration_files(const fs::path& raw_exported_dir_path, const VcpkgPaths& paths) - { - const std::vector integration_files_relative_to_root = { - {".vcpkg-root"}, - {fs::path{"scripts"} / "buildsystems" / "msbuild" / "applocal.ps1"}, - {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"}, - {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"}, - {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"}, - {fs::path{"scripts"} / "getWindowsSDK.ps1"}, - {fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"}, - {fs::path{"scripts"} / "getProgramFiles32bit.ps1"}, - }; - - for (const fs::path& file : integration_files_relative_to_root) - { - const fs::path source = paths.root / file; - fs::path destination = raw_exported_dir_path / file; - Files::Filesystem& fs = paths.get_filesystem(); - std::error_code ec; - fs.create_directories(destination.parent_path(), ec); - Checks::check_exit(VCPKG_LINE_INFO, !ec); - fs.copy_file(source, destination, fs::copy_options::overwrite_existing, ec); - Checks::check_exit(VCPKG_LINE_INFO, !ec); - } - } - - struct ExportArguments - { - bool dry_run; - bool raw; - bool nuget; - bool ifw; - bool zip; - bool seven_zip; - - Optional maybe_nuget_id; - Optional maybe_nuget_version; - - IFW::Options ifw_options; - std::vector specs; - }; - - static ExportArguments handle_export_command_arguments(const VcpkgCmdArguments& args, - const Triplet& default_triplet) - { - ExportArguments ret; - - static const std::string OPTION_DRY_RUN = "--dry-run"; - static const std::string OPTION_RAW = "--raw"; - static const std::string OPTION_NUGET = "--nuget"; - static const std::string OPTION_IFW = "--ifw"; - static const std::string OPTION_ZIP = "--zip"; - static const std::string OPTION_SEVEN_ZIP = "--7zip"; - static const std::string OPTION_NUGET_ID = "--nuget-id"; - static const std::string OPTION_NUGET_VERSION = "--nuget-version"; - static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url"; - static const std::string OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path"; - static const std::string OPTION_IFW_REPOSITORY_DIR_PATH = "--ifw-repository-directory-path"; - static const std::string OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path"; - static const std::string OPTION_IFW_INSTALLER_FILE_PATH = "--ifw-installer-file-path"; - - // input sanitization - static const std::string EXAMPLE = - Commands::Help::create_example_string("export zlib zlib:x64-windows boost --nuget"); - args.check_min_arg_count(1, EXAMPLE); - - ret.specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); - }); - - const auto options = args.check_and_get_optional_command_arguments( - { - OPTION_DRY_RUN, - OPTION_RAW, - OPTION_NUGET, - OPTION_IFW, - OPTION_ZIP, - OPTION_SEVEN_ZIP, - }, - { - OPTION_NUGET_ID, - OPTION_NUGET_VERSION, - OPTION_IFW_REPOSITORY_URL, - OPTION_IFW_PACKAGES_DIR_PATH, - OPTION_IFW_REPOSITORY_DIR_PATH, - OPTION_IFW_CONFIG_FILE_PATH, - OPTION_IFW_INSTALLER_FILE_PATH, - }); - ret.dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); - ret.raw = options.switches.find(OPTION_RAW) != options.switches.cend(); - ret.nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); - ret.ifw = options.switches.find(OPTION_IFW) != options.switches.cend(); - ret.zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); - ret.seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend(); - - if (!ret.raw && !ret.nuget && !ret.ifw && !ret.zip && !ret.seven_zip && !ret.dry_run) - { - System::println(System::Color::error, - "Must provide at least one export type: --raw --nuget --ifw --zip --7zip"); - System::print(EXAMPLE); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - struct OptionPair - { - const std::string& name; - Optional& out_opt; - }; - const auto options_implies = - [&](const std::string& main_opt_name, bool main_opt, Span implying_opts) { - if (main_opt) - { - for (auto&& opt : implying_opts) - opt.out_opt = maybe_lookup(options.settings, opt.name); - } - else - { - for (auto&& opt : implying_opts) - Checks::check_exit(VCPKG_LINE_INFO, - !maybe_lookup(options.settings, opt.name), - "%s is only valid with %s", - opt.name, - main_opt_name); - } - }; - - options_implies(OPTION_NUGET, - ret.nuget, - { - {OPTION_NUGET_ID, ret.maybe_nuget_id}, - {OPTION_NUGET_VERSION, ret.maybe_nuget_version}, - }); - - options_implies(OPTION_IFW, - ret.ifw, - { - {OPTION_IFW_REPOSITORY_URL, ret.ifw_options.maybe_repository_url}, - {OPTION_IFW_PACKAGES_DIR_PATH, ret.ifw_options.maybe_packages_dir_path}, - {OPTION_IFW_REPOSITORY_DIR_PATH, ret.ifw_options.maybe_repository_dir_path}, - {OPTION_IFW_CONFIG_FILE_PATH, ret.ifw_options.maybe_config_file_path}, - {OPTION_IFW_INSTALLER_FILE_PATH, ret.ifw_options.maybe_installer_file_path}, - }); - return ret; - } - - static void print_next_step_info(const fs::path& prefix) - { - const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; - const CMakeVariable cmake_variable = CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); - System::println("\n" - "To use the exported libraries in CMake projects use:" - "\n" - " %s" - "\n", - Strings::to_utf8(cmake_variable.s)); - }; - - static void handle_raw_based_export(Span export_plan, - const ExportArguments& opts, - const std::string& export_id, - const VcpkgPaths& paths) - { - Files::Filesystem& fs = paths.get_filesystem(); - const fs::path export_to_path = paths.root; - const fs::path raw_exported_dir_path = export_to_path / export_id; - std::error_code ec; - fs.remove_all(raw_exported_dir_path, ec); - fs.create_directory(raw_exported_dir_path, ec); - - // execute the plan - for (const ExportPlanAction& action : export_plan) - { - if (action.plan_type != ExportPlanType::ALREADY_BUILT) - { - Checks::unreachable(VCPKG_LINE_INFO); - } - - const std::string display_name = action.spec.to_string(); - System::println("Exporting package %s... ", display_name); - - const BinaryParagraph& binary_paragraph = - action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; - - const InstallDir dirs = InstallDir::from_destination_root( - raw_exported_dir_path / "installed", - action.spec.triplet().to_string(), - raw_exported_dir_path / "installed" / "vcpkg" / "info" / (binary_paragraph.fullstem() + ".list")); - - Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); - System::println(System::Color::success, "Exporting package %s... done", display_name); - } - - // Copy files needed for integration - export_integration_files(raw_exported_dir_path, paths); - - if (opts.raw) - { - System::println( - System::Color::success, R"(Files exported at: "%s")", raw_exported_dir_path.generic_string()); - print_next_step_info(export_to_path); - } - - if (opts.nuget) - { - System::println("Creating nuget package... "); - - const std::string nuget_id = opts.maybe_nuget_id.value_or(raw_exported_dir_path.filename().string()); - const std::string nuget_version = opts.maybe_nuget_version.value_or("1.0.0"); - const fs::path output_path = - do_nuget_export(paths, nuget_id, nuget_version, raw_exported_dir_path, export_to_path); - System::println(System::Color::success, "Creating nuget package... done"); - System::println(System::Color::success, "NuGet package exported at: %s", output_path.generic_string()); - - System::println(R"( -With a project open, go to Tools->NuGet Package Manager->Package Manager Console and paste: - Install-Package %s -Source "%s" -)" - "\n", - nuget_id, - output_path.parent_path().u8string()); - } - - if (opts.zip) - { - System::println("Creating zip archive... "); - const fs::path output_path = - do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::ZIP); - System::println(System::Color::success, "Creating zip archive... done"); - System::println(System::Color::success, "Zip archive exported at: %s", output_path.generic_string()); - print_next_step_info("[...]"); - } - - if (opts.seven_zip) - { - System::println("Creating 7zip archive... "); - const fs::path output_path = - do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::SEVEN_ZIP); - System::println(System::Color::success, "Creating 7zip archive... done"); - System::println(System::Color::success, "7zip archive exported at: %s", output_path.generic_string()); - print_next_step_info("[...]"); - } - - if (!opts.raw) - { - fs.remove_all(raw_exported_dir_path, ec); - } - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) - { - const auto opts = handle_export_command_arguments(args, default_triplet); - for (auto&& spec : opts.specs) - Input::check_triplet(spec.triplet(), paths); - - // create the plan - const StatusParagraphs status_db = database_load_check(paths); - std::vector export_plan = Dependencies::create_export_plan(paths, opts.specs, status_db); - Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty"); - - std::map> group_by_plan_type; - Util::group_by(export_plan, &group_by_plan_type, [](const ExportPlanAction& p) { return p.plan_type; }); - print_plan(group_by_plan_type); - - const bool has_non_user_requested_packages = - Util::find_if(export_plan, [](const ExportPlanAction& package) -> bool { - return package.request_type != RequestType::USER_REQUESTED; - }) != export_plan.cend(); - - if (has_non_user_requested_packages) - { - System::println(System::Color::warning, - "Additional packages (*) need to be exported to complete this operation."); - } - - const auto it = group_by_plan_type.find(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT); - if (it != group_by_plan_type.cend() && !it->second.empty()) - { - System::println(System::Color::error, "There are packages that have not been built."); - - // No need to show all of them, just the user-requested ones. Dependency resolution will handle the rest. - std::vector unbuilt = it->second; - Util::erase_remove_if( - unbuilt, [](const ExportPlanAction* a) { return a->request_type != RequestType::USER_REQUESTED; }); - - const auto s = Strings::join(" ", unbuilt, [](const ExportPlanAction* a) { return a->spec.to_string(); }); - System::println("To build them, run:\n" - " vcpkg install %s", - s); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - if (opts.dry_run) - { - Checks::exit_success(VCPKG_LINE_INFO); - } - - std::string export_id = create_export_id(); - - if (opts.raw || opts.nuget || opts.zip || opts.seven_zip) - { - handle_raw_based_export(export_plan, opts, export_id, paths); - } - - if (opts.ifw) - { - IFW::do_export(export_plan, export_id, opts.ifw_options, paths); - - print_next_step_info("@RootDir@/src/vcpkg"); - } - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp deleted file mode 100644 index 191dbb763..000000000 --- a/toolsrc/src/commands_export_ifw.cpp +++ /dev/null @@ -1,481 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Commands.h" -#include "vcpkg_Commands_Export.h" -#include "vcpkg_Commands_Export_IFW.h" - -namespace vcpkg::Commands::Export::IFW -{ - using Dependencies::ExportPlanAction; - using Dependencies::ExportPlanType; - using Install::InstallDir; - - static std::string create_release_date() - { - const tm date_time = System::get_current_date_time(); - - // Format is: YYYY-mm-dd - // 10 characters + 1 null terminating character will be written for a total of 11 chars - char mbstr[11]; - const size_t bytes_written = std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%d", &date_time); - Checks::check_exit(VCPKG_LINE_INFO, - bytes_written == 10, - "Expected 10 bytes to be written, but %u were written", - bytes_written); - const std::string date_time_as_string(mbstr); - return date_time_as_string; - } - - fs::path get_packages_dir_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) - { - return ifw_options.maybe_packages_dir_path.has_value() - ? fs::path(ifw_options.maybe_packages_dir_path.value_or_exit(VCPKG_LINE_INFO)) - : paths.root / (export_id + "-ifw-packages"); - } - - fs::path get_repository_dir_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) - { - return ifw_options.maybe_repository_dir_path.has_value() - ? fs::path(ifw_options.maybe_repository_dir_path.value_or_exit(VCPKG_LINE_INFO)) - : paths.root / (export_id + "-ifw-repository"); - } - - fs::path get_config_file_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) - { - return ifw_options.maybe_config_file_path.has_value() - ? fs::path(ifw_options.maybe_config_file_path.value_or_exit(VCPKG_LINE_INFO)) - : paths.root / (export_id + "-ifw-configuration.xml"); - } - - fs::path get_installer_file_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) - { - return ifw_options.maybe_installer_file_path.has_value() - ? fs::path(ifw_options.maybe_installer_file_path.value_or_exit(VCPKG_LINE_INFO)) - : paths.root / (export_id + "-ifw-installer.exe"); - } - - fs::path export_real_package(const fs::path& ifw_packages_dir_path, - const ExportPlanAction& action, - Files::Filesystem& fs) - { - std::error_code ec; - - const BinaryParagraph& binary_paragraph = - action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; - - // Prepare meta dir - const fs::path package_xml_file_path = - ifw_packages_dir_path / - Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "meta" / - "package.xml"; - const fs::path package_xml_dir_path = package_xml_file_path.parent_path(); - fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create directory for package file %s", - package_xml_file_path.generic_string()); - - auto deps = Strings::join( - ",", binary_paragraph.depends, [](const std::string& dep) { return "packages." + dep + ":"; }); - - if (!deps.empty()) deps = "\n " + deps + ""; - - fs.write_contents(package_xml_file_path, - Strings::format( - R"###( - - %s - %s - %s - packages.%s:,triplets.%s:%s - true - -)###", - action.spec.to_string(), - binary_paragraph.version, - create_release_date(), - action.spec.name(), - action.spec.triplet().canonical_name(), - deps)); - - // Return dir path for export package data - return ifw_packages_dir_path / - Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "data" / - "installed"; - } - - void export_unique_packages(const fs::path& raw_exported_dir_path, - std::map unique_packages, - Files::Filesystem& fs) - { - std::error_code ec; - - // packages - - fs::path package_xml_file_path = raw_exported_dir_path / "packages" / "meta" / "package.xml"; - fs::path package_xml_dir_path = package_xml_file_path.parent_path(); - fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create directory for package file %s", - package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, - Strings::format( - R"###( - - Packages - 1.0.0 - %s - -)###", - create_release_date())); - - for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) - { - const ExportPlanAction& action = *(package->second); - const BinaryParagraph& binary_paragraph = - action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; - - package_xml_file_path = - raw_exported_dir_path / Strings::format("packages.%s", package->first) / "meta" / "package.xml"; - package_xml_dir_path = package_xml_file_path.parent_path(); - fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create directory for package file %s", - package_xml_file_path.generic_string()); - - fs.write_contents(package_xml_file_path, - Strings::format( - R"###( - - %s - %s - %s - %s - -)###", - action.spec.name(), - binary_paragraph.description, - binary_paragraph.version, - create_release_date())); - } - } - - void export_unique_triplets(const fs::path& raw_exported_dir_path, - std::set unique_triplets, - Files::Filesystem& fs) - { - std::error_code ec; - - // triplets - - fs::path package_xml_file_path = raw_exported_dir_path / "triplets" / "meta" / "package.xml"; - fs::path package_xml_dir_path = package_xml_file_path.parent_path(); - fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create directory for package file %s", - package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, - Strings::format( - R"###( - - Triplets - 1.0.0 - %s - -)###", - create_release_date())); - - for (const std::string& triplet : unique_triplets) - { - package_xml_file_path = - raw_exported_dir_path / Strings::format("triplets.%s", triplet) / "meta" / "package.xml"; - package_xml_dir_path = package_xml_file_path.parent_path(); - fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create directory for package file %s", - package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, - Strings::format( - R"###( - - %s - 1.0.0 - %s - -)###", - triplet, - create_release_date())); - } - } - - void export_integration(const fs::path& raw_exported_dir_path, Files::Filesystem& fs) - { - std::error_code ec; - - // integration - fs::path package_xml_file_path = raw_exported_dir_path / "integration" / "meta" / "package.xml"; - fs::path package_xml_dir_path = package_xml_file_path.parent_path(); - fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create directory for package file %s", - package_xml_file_path.generic_string()); - - fs.write_contents(package_xml_file_path, - Strings::format( - R"###( - - Integration - 1.0.0 - %s - -)###", - create_release_date())); - } - - void export_config(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) - { - std::error_code ec; - Files::Filesystem& fs = paths.get_filesystem(); - - const fs::path config_xml_file_path = get_config_file_path(export_id, ifw_options, paths); - - fs::path config_xml_dir_path = config_xml_file_path.parent_path(); - fs.create_directories(config_xml_dir_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create directory for configuration file %s", - config_xml_file_path.generic_string()); - - std::string formatted_repo_url; - std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); - if (!ifw_repo_url.empty()) - { - formatted_repo_url = Strings::format(R"###( - - - %s - - )###", - ifw_repo_url); - } - - fs.write_contents(config_xml_file_path, - Strings::format( - R"###( - - vcpkg - 1.0.0 - vcpkg - @RootDir@/src/vcpkg%s - -)###", - formatted_repo_url)); - } - - void export_maintenance_tool(const fs::path& ifw_packages_dir_path, const VcpkgPaths& paths) - { - System::println("Exporting maintenance tool... "); - - std::error_code ec; - Files::Filesystem& fs = paths.get_filesystem(); - - const fs::path& installerbase_exe = paths.get_ifw_installerbase_exe(); - fs::path tempmaintenancetool = ifw_packages_dir_path / "maintenance" / "data" / "tempmaintenancetool.exe"; - fs.create_directories(tempmaintenancetool.parent_path(), ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create directory for package file %s", - tempmaintenancetool.generic_string()); - fs.copy_file(installerbase_exe, tempmaintenancetool, fs::copy_options::overwrite_existing, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not write package file %s", tempmaintenancetool.generic_string()); - - fs::path package_xml_file_path = ifw_packages_dir_path / "maintenance" / "meta" / "package.xml"; - fs::path package_xml_dir_path = package_xml_file_path.parent_path(); - fs.create_directories(package_xml_dir_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not create directory for package file %s", - package_xml_file_path.generic_string()); - fs.write_contents(package_xml_file_path, - Strings::format( - R"###( - - Maintenance Tool - Maintenance Tool - 1.0.0 - %s - - true - true - true - -)###", - create_release_date())); - const fs::path script_source = paths.root / "scripts" / "ifw" / "maintenance.qs"; - const fs::path script_destination = ifw_packages_dir_path / "maintenance" / "meta" / "maintenance.qs"; - fs.copy_file(script_source, script_destination, fs::copy_options::overwrite_existing, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not write package file %s", script_destination.generic_string()); - - System::println("Exporting maintenance tool... done"); - } - - void do_repository(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) - { - const fs::path& repogen_exe = paths.get_ifw_repogen_exe(); - const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); - const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); - - System::println("Generating repository %s...", repository_dir.generic_string()); - - std::error_code ec; - Files::Filesystem& fs = paths.get_filesystem(); - - fs.remove_all(repository_dir, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not remove outdated repository directory %s", repository_dir.generic_string()); - - const std::wstring cmd_line = Strings::wformat(LR"("%s" --packages "%s" "%s" > nul)", - repogen_exe.native(), - packages_dir.native(), - repository_dir.native()); - - const int exit_code = System::cmd_execute_clean(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW repository generating failed"); - - System::println(System::Color::success, "Generating repository %s... done.", repository_dir.generic_string()); - } - - void do_installer(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) - { - const fs::path& binarycreator_exe = paths.get_ifw_binarycreator_exe(); - const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); - const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); - const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); - const fs::path installer_file = get_installer_file_path(export_id, ifw_options, paths); - - System::println("Generating installer %s...", installer_file.generic_string()); - - std::wstring cmd_line; - - std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); - if (!ifw_repo_url.empty()) - { - cmd_line = Strings::wformat(LR"("%s" --online-only --config "%s" --repository "%s" "%s" > nul)", - binarycreator_exe.native(), - config_file.native(), - repository_dir.native(), - installer_file.native()); - } - else - { - cmd_line = Strings::wformat(LR"("%s" --config "%s" --packages "%s" "%s" > nul)", - binarycreator_exe.native(), - config_file.native(), - packages_dir.native(), - installer_file.native()); - } - - const int exit_code = System::cmd_execute_clean(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW installer generating failed"); - - System::println(System::Color::success, "Generating installer %s... done.", installer_file.generic_string()); - } - - void do_export(const std::vector& export_plan, - const std::string& export_id, - const Options& ifw_options, - const VcpkgPaths& paths) - { - std::error_code ec; - Files::Filesystem& fs = paths.get_filesystem(); - - // Prepare packages directory - const fs::path ifw_packages_dir_path = get_packages_dir_path(export_id, ifw_options, paths); - - fs.remove_all(ifw_packages_dir_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !ec, - "Could not remove outdated packages directory %s", - ifw_packages_dir_path.generic_string()); - - fs.create_directory(ifw_packages_dir_path, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not create packages directory %s", ifw_packages_dir_path.generic_string()); - - // Export maintenance tool - export_maintenance_tool(ifw_packages_dir_path, paths); - - System::println("Exporting packages %s... ", ifw_packages_dir_path.generic_string()); - - // execute the plan - std::map unique_packages; - std::set unique_triplets; - for (const ExportPlanAction& action : export_plan) - { - if (action.plan_type != ExportPlanType::ALREADY_BUILT) - { - Checks::unreachable(VCPKG_LINE_INFO); - } - - const std::string display_name = action.spec.to_string(); - System::println("Exporting package %s... ", display_name); - - const BinaryParagraph& binary_paragraph = - action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; - - unique_packages[action.spec.name()] = &action; - unique_triplets.insert(action.spec.triplet().canonical_name()); - - // Export real package and return data dir for installation - fs::path ifw_package_dir_path = export_real_package(ifw_packages_dir_path, action, fs); - - // Copy package data - const InstallDir dirs = InstallDir::from_destination_root(ifw_package_dir_path, - action.spec.triplet().to_string(), - ifw_package_dir_path / "vcpkg" / "info" / - (binary_paragraph.fullstem() + ".list")); - - Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); - System::println("Exporting package %s... done", display_name); - } - - System::println("Exporting packages %s... done", ifw_packages_dir_path.generic_string()); - - const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); - - System::println("Generating configuration %s...", config_file.generic_string()); - - // Unique packages - export_unique_packages(ifw_packages_dir_path, unique_packages, fs); - - // Unique triplets - export_unique_triplets(ifw_packages_dir_path, unique_triplets, fs); - - // Copy files needed for integration - export_integration_files(ifw_packages_dir_path / "integration" / "data", paths); - // Integration - export_integration(ifw_packages_dir_path, fs); - - // Configuration - export_config(export_id, ifw_options, paths); - - System::println("Generating configuration %s... done.", config_file.generic_string()); - - // Do repository (optional) - std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); - if (!ifw_repo_url.empty()) - { - do_repository(export_id, ifw_options, paths); - } - - // Do installer - do_installer(export_id, ifw_options, paths); - } -} diff --git a/toolsrc/src/commands_hash.cpp b/toolsrc/src/commands_hash.cpp deleted file mode 100644 index b3211b9f8..000000000 --- a/toolsrc/src/commands_hash.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Commands.h" -#include "vcpkg_System.h" -#include "vcpkg_Util.h" - -namespace vcpkg::Commands::Hash -{ - static void do_file_hash(fs::path const& path, std::wstring const& hash_type) - { - const auto cmd_line = Strings::wformat(LR"(CertUtil.exe -hashfile "%s" %s)", path.c_str(), hash_type); - const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit( - VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::to_utf8(cmd_line)); - - std::string const& output = ec_data.output; - - const auto start = output.find_first_of("\r\n"); - Checks::check_exit(VCPKG_LINE_INFO, - start != std::string::npos, - "Unexpected output format from command: %s", - Strings::to_utf8(cmd_line)); - - const auto end = output.find_first_of("\r\n", start + 1); - Checks::check_exit(VCPKG_LINE_INFO, - end != std::string::npos, - "Unexpected output format from command: %s", - Strings::to_utf8(cmd_line)); - - auto hash = output.substr(start, end - start); - Util::erase_remove_if(hash, isspace); - System::println(hash); - } - - void perform_and_exit(const VcpkgCmdArguments& args) - { - static const std::string EXAMPLE = - Strings::format("The argument should be a file path\n%s", - Commands::Help::create_example_string("hash boost_1_62_0.tar.bz2")); - args.check_min_arg_count(1, EXAMPLE); - args.check_max_arg_count(2, EXAMPLE); - args.check_and_get_optional_command_arguments({}); - - if (args.command_arguments.size() == 1) - { - do_file_hash(args.command_arguments[0], L"SHA512"); - } - if (args.command_arguments.size() == 2) - { - do_file_hash(args.command_arguments[0], Strings::to_utf16(args.command_arguments[1])); - } - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_help.cpp b/toolsrc/src/commands_help.cpp deleted file mode 100644 index a12f9003d..000000000 --- a/toolsrc/src/commands_help.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Commands.h" -#include "vcpkg_System.h" - -namespace vcpkg::Commands::Help -{ - void help_topics() - { - System::println("Available help topics:\n" - " triplet\n" - " integrate\n" - " export"); - } - - void help_topic_valid_triplet(const VcpkgPaths& paths) - { - System::println("Available architecture triplets:"); - for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.triplets)) - { - System::println(" %s", path.stem().filename().string()); - } - } - - void help_topic_export() - { - System::println("Summary:\n" - " vcpkg export [options] ...\n" - "\n" - "Options:\n" - " --7zip Export to a 7zip (.7z) file\n" - " --dry-run Do not actually export\n" - " --nuget Export a NuGet package\n" - " --nuget-id= Specify the id for the exported NuGet package\n" - " --nuget-version= Specify the version for the exported NuGet package\n" - " --raw Export to an uncompressed directory\n" - " --zip Export to a zip file"); - } - - void print_usage() - { - System::println( - "Commands:\n" - " vcpkg search [pat] Search for packages available to be built\n" - " vcpkg install ... Install a package\n" - " vcpkg remove ... Uninstall a package\n" - " vcpkg remove --outdated Uninstall all out-of-date packages\n" - " vcpkg list List installed packages\n" - " vcpkg update Display list of packages for updating\n" - " vcpkg hash [alg] Hash a file by specific algorithm, default SHA512\n" - " vcpkg help topics Display the list of help topics\n" - " vcpkg help Display help for a specific topic\n" - "\n" - "%s" // Integration help - "\n" - " vcpkg export ... [opt]... Exports a package\n" - " vcpkg edit Open up a port for editing (uses %%EDITOR%%, default 'code')\n" - " vcpkg import Import a pre-built library\n" - " vcpkg create \n" - " [archivename] Create a new package\n" - " vcpkg owns Search for files in installed packages\n" - " vcpkg cache List cached compiled packages\n" - " vcpkg version Display version information\n" - " vcpkg contact Display contact information to send feedback\n" - "\n" - //"internal commands:\n" - //" --check-build-deps \n" - //" --create-binary-control \n" - //"\n" - "Options:\n" - " --triplet Specify the target architecture triplet.\n" - " (default: %%VCPKG_DEFAULT_TRIPLET%%, see 'vcpkg help triplet')\n" - "\n" - " --vcpkg-root Specify the vcpkg root directory\n" - " (default: %%VCPKG_ROOT%%)\n" - "\n" - "For more help (including examples) see the accompanying README.md.", - Integrate::INTEGRATE_COMMAND_HELPSTRING); - } - - std::string create_example_string(const std::string& command_and_arguments) - { - std::string cs = Strings::format("Example:\n" - " vcpkg %s\n", - command_and_arguments); - return cs; - } - - void print_example(const std::string& command_and_arguments) - { - System::println(create_example_string(command_and_arguments)); - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - args.check_max_arg_count(1); - args.check_and_get_optional_command_arguments({}); - - if (args.command_arguments.empty()) - { - print_usage(); - Checks::exit_success(VCPKG_LINE_INFO); - } - const auto& topic = args.command_arguments[0]; - if (topic == "triplet" || topic == "triplets" || topic == "triple") - { - help_topic_valid_triplet(paths); - } - else if (topic == "export") - { - help_topic_export(); - } - else if (topic == "integrate") - { - System::print("Commands:\n" - "%s", - Integrate::INTEGRATE_COMMAND_HELPSTRING); - } - else if (topic == "topics") - { - help_topics(); - } - else - { - System::println(System::Color::error, "Error: unknown topic %s", topic); - help_topics(); - Checks::exit_fail(VCPKG_LINE_INFO); - } - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp deleted file mode 100644 index 412a03d7f..000000000 --- a/toolsrc/src/commands_import.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "StatusParagraph.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Files.h" - -namespace vcpkg::Commands::Import -{ - struct Binaries - { - std::vector dlls; - std::vector libs; - }; - - static void check_is_directory(const LineInfo& line_info, const Files::Filesystem& fs, const fs::path& dirpath) - { - Checks::check_exit(line_info, fs.is_directory(dirpath), "The path %s is not a directory", dirpath.string()); - } - - static Binaries find_binaries_in_dir(const Files::Filesystem& fs, const fs::path& path) - { - auto files = fs.get_files_recursive(path); - - check_is_directory(VCPKG_LINE_INFO, fs, path); - - Binaries binaries; - for (auto&& file : files) - { - if (fs.is_directory(file)) continue; - const auto ext = file.extension(); - if (ext == ".dll") - binaries.dlls.push_back(std::move(file)); - else if (ext == ".lib") - binaries.libs.push_back(std::move(file)); - } - return binaries; - } - - static void copy_files_into_directory(Files::Filesystem& fs, - const std::vector& files, - const fs::path& destination_folder) - { - std::error_code ec; - fs.create_directory(destination_folder, ec); - - for (auto const& src_path : files) - { - const fs::path dest_path = destination_folder / src_path.filename(); - fs.copy(src_path, dest_path, fs::copy_options::overwrite_existing); - } - } - - static void place_library_files_in(Files::Filesystem& fs, - const fs::path& include_directory, - const fs::path& project_directory, - const fs::path& destination_path) - { - check_is_directory(VCPKG_LINE_INFO, fs, include_directory); - check_is_directory(VCPKG_LINE_INFO, fs, project_directory); - check_is_directory(VCPKG_LINE_INFO, fs, destination_path); - const Binaries debug_binaries = find_binaries_in_dir(fs, project_directory / "Debug"); - const Binaries release_binaries = find_binaries_in_dir(fs, project_directory / "Release"); - - const fs::path destination_include_directory = destination_path / "include"; - fs.copy(include_directory, - destination_include_directory, - fs::copy_options::recursive | fs::copy_options::overwrite_existing); - - copy_files_into_directory(fs, release_binaries.dlls, destination_path / "bin"); - copy_files_into_directory(fs, release_binaries.libs, destination_path / "lib"); - - std::error_code ec; - fs.create_directory(destination_path / "debug", ec); - copy_files_into_directory(fs, debug_binaries.dlls, destination_path / "debug" / "bin"); - copy_files_into_directory(fs, debug_binaries.libs, destination_path / "debug" / "lib"); - } - - static void do_import(const VcpkgPaths& paths, - const fs::path& include_directory, - const fs::path& project_directory, - const BinaryParagraph& control_file_data) - { - auto& fs = paths.get_filesystem(); - const fs::path library_destination_path = paths.package_dir(control_file_data.spec); - std::error_code ec; - fs.create_directory(library_destination_path, ec); - place_library_files_in(paths.get_filesystem(), include_directory, project_directory, library_destination_path); - - const fs::path control_file_path = library_destination_path / "CONTROL"; - fs.write_contents(control_file_path, Strings::serialize(control_file_data)); - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - static const std::string EXAMPLE = Commands::Help::create_example_string( - R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)"); - args.check_exact_arg_count(3, EXAMPLE); - args.check_and_get_optional_command_arguments({}); - - const fs::path control_file_path(args.command_arguments[0]); - const fs::path include_directory(args.command_arguments[1]); - const fs::path project_directory(args.command_arguments[2]); - - const Expected> pghs = - Paragraphs::get_single_paragraph(paths.get_filesystem(), control_file_path); - Checks::check_exit(VCPKG_LINE_INFO, - pghs.get() != nullptr, - "Invalid control file %s for package", - control_file_path.generic_string()); - - StatusParagraph spgh; - spgh.package = BinaryParagraph(*pghs.get()); - auto& control_file_data = spgh.package; - - do_import(paths, include_directory, project_directory, control_file_data); - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp deleted file mode 100644 index d815332fe..000000000 --- a/toolsrc/src/commands_install.cpp +++ /dev/null @@ -1,613 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "metrics.h" -#include "vcpkg_Build.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Dependencies.h" -#include "vcpkg_Files.h" -#include "vcpkg_GlobalState.h" -#include "vcpkg_Input.h" -#include "vcpkg_System.h" -#include "vcpkg_Util.h" -#include "vcpkglib.h" - -namespace vcpkg::Commands::Install -{ - using namespace Dependencies; - - InstallDir InstallDir::from_destination_root(const fs::path& destination_root, - const std::string& destination_subdirectory, - const fs::path& listfile) - { - InstallDir dirs; - dirs.m_destination = destination_root / destination_subdirectory; - dirs.m_destination_subdirectory = destination_subdirectory; - dirs.m_listfile = listfile; - return dirs; - } - - const fs::path& InstallDir::destination() const { return this->m_destination; } - - const std::string& InstallDir::destination_subdirectory() const { return this->m_destination_subdirectory; } - - const fs::path& InstallDir::listfile() const { return this->m_listfile; } - - void install_files_and_write_listfile(Files::Filesystem& fs, - const fs::path& source_dir, - const InstallDir& destination_dir) - { - std::vector output; - std::error_code ec; - - const size_t prefix_length = source_dir.native().size(); - const fs::path& destination = destination_dir.destination(); - const std::string& destination_subdirectory = destination_dir.destination_subdirectory(); - const fs::path& listfile = destination_dir.listfile(); - - Checks::check_exit( - VCPKG_LINE_INFO, fs.exists(source_dir), "Source directory %s does not exist", source_dir.generic_string()); - fs.create_directories(destination, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not create destination directory %s", destination.generic_string()); - const fs::path listfile_parent = listfile.parent_path(); - fs.create_directories(listfile_parent, ec); - Checks::check_exit( - VCPKG_LINE_INFO, !ec, "Could not create directory for listfile %s", listfile.generic_string()); - - output.push_back(Strings::format(R"(%s/)", destination_subdirectory)); - auto files = fs.get_files_recursive(source_dir); - for (auto&& file : files) - { - const auto status = fs.status(file, ec); - if (ec) - { - System::println(System::Color::error, "failed: %s: %s", file.u8string(), ec.message()); - continue; - } - - const std::string filename = file.filename().generic_string(); - if (fs::is_regular_file(status) && - (Strings::case_insensitive_ascii_compare(filename.c_str(), "CONTROL") == 0 || - Strings::case_insensitive_ascii_compare(filename.c_str(), "BUILD_INFO") == 0)) - { - // Do not copy the control file - continue; - } - - const std::string suffix = file.generic_u8string().substr(prefix_length + 1); - const fs::path target = destination / suffix; - - if (fs::is_directory(status)) - { - fs.create_directory(target, ec); - if (ec) - { - System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); - } - - // Trailing backslash for directories - output.push_back(Strings::format(R"(%s/%s/)", destination_subdirectory, suffix)); - continue; - } - - if (fs::is_regular_file(status)) - { - if (fs.exists(target)) - { - System::println(System::Color::warning, - "File %s was already present and will be overwritten", - target.u8string(), - ec.message()); - } - fs.copy_file(file, target, fs::copy_options::overwrite_existing, ec); - if (ec) - { - System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); - } - output.push_back(Strings::format(R"(%s/%s)", destination_subdirectory, suffix)); - continue; - } - - if (!fs::status_known(status)) - { - System::println(System::Color::error, "failed: %s: unknown status", file.u8string()); - continue; - } - - System::println(System::Color::error, "failed: %s: cannot handle file type", file.u8string()); - } - - std::sort(output.begin(), output.end()); - - fs.write_lines(listfile, output); - } - - static void remove_first_n_chars(std::vector* strings, const size_t n) - { - for (std::string& s : *strings) - { - s.erase(0, n); - } - }; - - static std::vector extract_files_in_triplet( - const std::vector& pgh_and_files, const Triplet& triplet) - { - std::vector output; - for (const StatusParagraphAndAssociatedFiles& t : pgh_and_files) - { - if (t.pgh.package.spec.triplet() != triplet) - { - continue; - } - - output.insert(output.end(), t.files.begin(), t.files.end()); - } - - std::sort(output.begin(), output.end()); - return output; - } - - static SortedVector build_list_of_package_files(const Files::Filesystem& fs, - const fs::path& package_dir) - { - const std::vector package_file_paths = fs.get_files_recursive(package_dir); - const size_t package_remove_char_count = package_dir.generic_string().size() + 1; // +1 for the slash - auto package_files = Util::fmap(package_file_paths, [package_remove_char_count](const fs::path& path) { - std::string as_string = path.generic_string(); - as_string.erase(0, package_remove_char_count); - return std::move(as_string); - }); - - return SortedVector(std::move(package_files)); - } - - static SortedVector build_list_of_installed_files( - const std::vector& pgh_and_files, const Triplet& triplet) - { - std::vector installed_files = extract_files_in_triplet(pgh_and_files, triplet); - const size_t installed_remove_char_count = triplet.canonical_name().size() + 1; // +1 for the slash - remove_first_n_chars(&installed_files, installed_remove_char_count); - - return SortedVector(std::move(installed_files)); - } - - InstallResult install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db) - { - const fs::path package_dir = paths.package_dir(bcf.core_paragraph.spec); - const Triplet& triplet = bcf.core_paragraph.spec.triplet(); - const std::vector pgh_and_files = get_installed_files(paths, *status_db); - - const SortedVector package_files = - build_list_of_package_files(paths.get_filesystem(), package_dir); - const SortedVector installed_files = build_list_of_installed_files(pgh_and_files, triplet); - - std::vector intersection; - std::set_intersection(package_files.begin(), - package_files.end(), - installed_files.begin(), - installed_files.end(), - std::back_inserter(intersection)); - - if (!intersection.empty()) - { - const fs::path triplet_install_path = paths.installed / triplet.canonical_name(); - System::println(System::Color::error, - "The following files are already installed in %s and are in conflict with %s", - triplet_install_path.generic_string(), - bcf.core_paragraph.spec); - System::print("\n "); - System::println(Strings::join("\n ", intersection)); - System::println(); - return InstallResult::FILE_CONFLICTS; - } - - StatusParagraph source_paragraph; - source_paragraph.package = bcf.core_paragraph; - source_paragraph.want = Want::INSTALL; - source_paragraph.state = InstallState::HALF_INSTALLED; - - write_update(paths, source_paragraph); - status_db->insert(std::make_unique(source_paragraph)); - - std::vector features_spghs; - for (auto&& feature : bcf.features) - { - features_spghs.emplace_back(); - - StatusParagraph& feature_paragraph = features_spghs.back(); - feature_paragraph.package = feature; - feature_paragraph.want = Want::INSTALL; - feature_paragraph.state = InstallState::HALF_INSTALLED; - - write_update(paths, feature_paragraph); - status_db->insert(std::make_unique(feature_paragraph)); - } - - const InstallDir install_dir = InstallDir::from_destination_root( - paths.installed, triplet.to_string(), paths.listfile_path(bcf.core_paragraph)); - - install_files_and_write_listfile(paths.get_filesystem(), package_dir, install_dir); - - source_paragraph.state = InstallState::INSTALLED; - write_update(paths, source_paragraph); - status_db->insert(std::make_unique(source_paragraph)); - - for (auto&& feature_paragraph : features_spghs) - { - feature_paragraph.state = InstallState::INSTALLED; - write_update(paths, feature_paragraph); - status_db->insert(std::make_unique(feature_paragraph)); - } - - return InstallResult::SUCCESS; - } - - using Build::BuildResult; - - BuildResult perform_install_plan_action(const VcpkgPaths& paths, - const InstallPlanAction& action, - const Build::BuildPackageOptions& build_package_options, - StatusParagraphs& status_db) - { - const InstallPlanType& plan_type = action.plan_type; - const std::string display_name = action.spec.to_string(); - const std::string display_name_with_features = - GlobalState::feature_packages ? action.displayname() : display_name; - - const bool is_user_requested = action.request_type == RequestType::USER_REQUESTED; - const bool use_head_version = to_bool(build_package_options.use_head_version); - - if (plan_type == InstallPlanType::ALREADY_INSTALLED) - { - if (use_head_version && is_user_requested) - System::println( - System::Color::warning, "Package %s is already installed -- not building from HEAD", display_name); - else - System::println(System::Color::success, "Package %s is already installed", display_name); - return BuildResult::SUCCEEDED; - } - - if (plan_type == InstallPlanType::BUILD_AND_INSTALL) - { - if (use_head_version) - System::println("Building package %s from HEAD... ", display_name_with_features); - else - System::println("Building package %s... ", display_name_with_features); - - const auto result = [&]() -> Build::ExtendedBuildResult { - if (GlobalState::feature_packages) - { - const Build::BuildPackageConfig build_config{ - *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), - action.spec.triplet(), - paths.port_dir(action.spec), - build_package_options, - action.feature_list}; - return Build::build_package(paths, build_config, status_db); - } - else - { - const Build::BuildPackageConfig build_config{ - action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO), - action.spec.triplet(), - paths.port_dir(action.spec), - build_package_options}; - return Build::build_package(paths, build_config, status_db); - } - }(); - - if (result.code != Build::BuildResult::SUCCEEDED) - { - System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); - return result.code; - } - - System::println("Building package %s... done", display_name_with_features); - - const BinaryControlFile bcf = - Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); - System::println("Installing package %s... ", display_name_with_features); - const auto install_result = install_package(paths, bcf, &status_db); - switch (install_result) - { - case InstallResult::SUCCESS: - System::println(System::Color::success, "Installing package %s... done", display_name); - return BuildResult::SUCCEEDED; - case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - - if (plan_type == InstallPlanType::INSTALL) - { - if (use_head_version && is_user_requested) - { - System::println( - System::Color::warning, "Package %s is already built -- not building from HEAD", display_name); - } - System::println("Installing package %s... ", display_name); - const auto install_result = install_package( - paths, action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO), &status_db); - switch (install_result) - { - case InstallResult::SUCCESS: - System::println(System::Color::success, "Installing package %s... done", display_name); - return BuildResult::SUCCEEDED; - case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - - Checks::unreachable(VCPKG_LINE_INFO); - } - - static void print_plan(const std::vector& action_plan, bool is_recursive) - { - std::vector remove_plans; - std::vector rebuilt_plans; - std::vector only_install_plans; - std::vector new_plans; - std::vector already_installed_plans; - - const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { - if (auto iplan = package.install_plan.get()) - return iplan->request_type != RequestType::USER_REQUESTED; - else - return false; - }) != action_plan.cend(); - - for (auto&& action : action_plan) - { - if (auto install_action = action.install_plan.get()) - { - // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at - // all. - auto it = Util::find_if( - remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); - if (it != remove_plans.end()) - { - rebuilt_plans.emplace_back(install_action); - } - else - { - switch (install_action->plan_type) - { - case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break; - case InstallPlanType::ALREADY_INSTALLED: - if (install_action->request_type == RequestType::USER_REQUESTED) - already_installed_plans.emplace_back(install_action); - break; - case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - } - else if (auto remove_action = action.remove_plan.get()) - { - remove_plans.emplace_back(remove_action); - } - } - - std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name); - std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name); - - if (already_installed_plans.size() > 0) - { - const std::string already_string = - Strings::join("\n", already_installed_plans, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); - System::println("The following packages are already installed:\n%s", already_string); - } - - if (rebuilt_plans.size() > 0) - { - const std::string rebuilt_string = Strings::join("\n", rebuilt_plans, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); - System::println("The following packages will be rebuilt:\n%s", rebuilt_string); - } - - if (new_plans.size() > 0) - { - const std::string new_string = Strings::join("\n", new_plans, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); - System::println("The following packages will be built and installed:\n%s", new_string); - } - - if (only_install_plans.size() > 0) - { - const std::string only_install_string = - Strings::join("\n", only_install_plans, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); - System::println("The following packages will be directly installed:\n%s", only_install_string); - } - - if (has_non_user_requested_packages) - System::println("Additional packages (*) will be installed to complete this operation."); - - if (remove_plans.size() > 0 && !is_recursive) - { - System::println(System::Color::warning, - "If you are sure you want to rebuild the above packages, run the command with the " - "--recurse option"); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - - void perform_and_exit(const std::vector& action_plan, - const Build::BuildPackageOptions& install_plan_options, - const KeepGoing keep_going, - const PrintSummary print_summary, - const VcpkgPaths& paths, - StatusParagraphs& status_db) - { - std::vector results; - std::vector timing; - const ElapsedTime timer = ElapsedTime::create_started(); - size_t counter = 0; - const size_t package_count = action_plan.size(); - - for (const auto& action : action_plan) - { - const ElapsedTime build_timer = ElapsedTime::create_started(); - counter++; - - const std::string display_name = action.spec().to_string(); - System::println("Starting package %d/%d: %s", counter, package_count, display_name); - - timing.push_back("0"); - results.push_back(BuildResult::NULLVALUE); - - if (const auto install_action = action.install_plan.get()) - { - const BuildResult result = - perform_install_plan_action(paths, *install_action, install_plan_options, status_db); - if (result != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO) - { - System::println(Build::create_user_troubleshooting_message(install_action->spec)); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - results.back() = result; - } - else if (const auto remove_action = action.remove_plan.get()) - { - Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages); - Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db); - } - else - { - Checks::unreachable(VCPKG_LINE_INFO); - } - - timing.back() = build_timer.to_string(); - System::println("Elapsed time for package %s: %s", display_name, build_timer.to_string()); - } - - System::println("Total time taken: %s", timer.to_string()); - - if (print_summary == PrintSummary::YES) - { - for (size_t i = 0; i < results.size(); i++) - { - System::println("%s: %s: %s", action_plan[i].spec(), Build::to_string(results[i]), timing[i]); - } - - std::map summary; - for (const BuildResult& v : Build::BUILD_RESULT_VALUES) - { - summary[v] = 0; - } - - for (const BuildResult& r : results) - { - summary[r]++; - } - - System::println("\n\nSUMMARY"); - for (const std::pair& entry : summary) - { - System::println(" %s: %d", Build::to_string(entry.first), entry.second); - } - } - - Checks::exit_success(VCPKG_LINE_INFO); - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) - { - static const std::string OPTION_DRY_RUN = "--dry-run"; - static const std::string OPTION_USE_HEAD_VERSION = "--head"; - static const std::string OPTION_NO_DOWNLOADS = "--no-downloads"; - static const std::string OPTION_RECURSE = "--recurse"; - static const std::string OPTION_KEEP_GOING = "--keep-going"; - - // input sanitization - static const std::string EXAMPLE = - Commands::Help::create_example_string("install zlib zlib:x64-windows curl boost"); - args.check_min_arg_count(1, EXAMPLE); - - const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_full_package_spec(arg, default_triplet, EXAMPLE); - }); - - for (auto&& spec : specs) - { - Input::check_triplet(spec.package_spec.triplet(), paths); - if (!spec.features.empty() && !GlobalState::feature_packages) - { - Checks::exit_with_message( - VCPKG_LINE_INFO, "Feature packages are experimentally available under the --featurepackages flag."); - } - } - - const std::unordered_set options = args.check_and_get_optional_command_arguments( - {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE, OPTION_KEEP_GOING}); - const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend(); - const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend(); - const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); - const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); - const KeepGoing keep_going = to_keep_going(options.find(OPTION_KEEP_GOING) != options.cend()); - - // create the plan - StatusParagraphs status_db = database_load_check(paths); - - const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), - Build::to_allow_downloads(!no_downloads)}; - - std::vector action_plan; - - if (GlobalState::feature_packages) - { - std::unordered_map scf_map; - auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - for (auto&& port : all_ports) - { - scf_map[port->core_paragraph->name] = std::move(*port); - } - action_plan = create_feature_install_plan(scf_map, FullPackageSpec::to_feature_specs(specs), status_db); - } - else - { - Dependencies::PathsPortFile paths_port_file(paths); - auto install_plan = Dependencies::create_install_plan( - paths_port_file, Util::fmap(specs, [](auto&& spec) { return spec.package_spec; }), status_db); - - action_plan = Util::fmap( - install_plan, [](InstallPlanAction& install_action) { return AnyAction(std::move(install_action)); }); - } - - // install plan will be empty if it is already installed - need to change this at status paragraph part - Checks::check_exit(VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty"); - - // log the plan - const std::string specs_string = Strings::join(",", action_plan, [](const AnyAction& action) { - if (auto iaction = action.install_plan.get()) - return iaction->spec.to_string(); - else if (auto raction = action.remove_plan.get()) - return "R$" + raction->spec.to_string(); - Checks::unreachable(VCPKG_LINE_INFO); - }); - - Metrics::g_metrics.lock()->track_property("installplan", specs_string); - - print_plan(action_plan, is_recursive); - - if (dry_run) - { - Checks::exit_success(VCPKG_LINE_INFO); - } - - perform_and_exit(action_plan, install_plan_options, keep_going, PrintSummary::NO, paths, status_db); - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_integrate.cpp b/toolsrc/src/commands_integrate.cpp deleted file mode 100644 index fd2f11294..000000000 --- a/toolsrc/src/commands_integrate.cpp +++ /dev/null @@ -1,342 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Checks.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Files.h" -#include "vcpkg_System.h" -#include "vcpkg_Util.h" - -namespace vcpkg::Commands::Integrate -{ - static const std::array OLD_SYSTEM_TARGET_FILES = { - System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", - System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"}; - static const fs::path SYSTEM_WIDE_TARGETS_FILE = - System::get_program_files_32_bit() / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; - - static std::string create_appdata_targets_shortcut(const std::string& target_path) noexcept - { - return Strings::format(R"###( - - - -)###", - target_path, - target_path); - } - - static std::string create_system_targets_shortcut() noexcept - { - return R"###( - - - - $(LOCALAPPDATA)\vcpkg\vcpkg.user - - - -)###"; - } - - static std::string create_nuget_targets_file_contents(const fs::path& msbuild_vcpkg_targets_file) noexcept - { - const std::string as_string = msbuild_vcpkg_targets_file.string(); - - return Strings::format(R"###( - - - - - - -)###", - as_string, - as_string); - } - - static std::string create_nuget_props_file_contents() noexcept - { - return R"###( - - - true - - -)###"; - } - - static std::string get_nuget_id(const fs::path& vcpkg_root_dir) - { - std::string dir_id = vcpkg_root_dir.generic_string(); - std::replace(dir_id.begin(), dir_id.end(), '/', '.'); - dir_id.erase(1, 1); // Erasing the ":" - - // NuGet id cannot have invalid characters. We will only use alphanumeric and dot. - Util::erase_remove_if(dir_id, [](char c) { return !isalnum(c) && (c != '.'); }); - - const std::string nuget_id = "vcpkg." + dir_id; - return nuget_id; - } - - static std::string create_nuspec_file_contents(const fs::path& vcpkg_root_dir, - const std::string& nuget_id, - const std::string& nupkg_version) - { - static constexpr auto CONTENT_TEMPLATE = R"( - - - @NUGET_ID@ - @VERSION@ - vcpkg - - This package imports all libraries currently installed in @VCPKG_DIR@. This package does not contain any libraries and instead refers to the folder directly (like a symlink). - - - - - - - -)"; - - std::string content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id); - content = std::regex_replace(content, std::regex("@VCPKG_DIR@"), vcpkg_root_dir.string()); - content = std::regex_replace(content, std::regex("@VERSION@"), nupkg_version); - return content; - } - - enum class ElevationPromptChoice - { - YES, - NO - }; - - static ElevationPromptChoice elevated_cmd_execute(const std::string& param) - { - SHELLEXECUTEINFOW sh_ex_info = {0}; - sh_ex_info.cbSize = sizeof(sh_ex_info); - sh_ex_info.fMask = SEE_MASK_NOCLOSEPROCESS; - sh_ex_info.hwnd = nullptr; - sh_ex_info.lpVerb = L"runas"; - sh_ex_info.lpFile = L"cmd"; // Application to start - - auto wparam = Strings::to_utf16(param); - sh_ex_info.lpParameters = wparam.c_str(); // Additional parameters - sh_ex_info.lpDirectory = nullptr; - sh_ex_info.nShow = SW_HIDE; - sh_ex_info.hInstApp = nullptr; - - if (!ShellExecuteExW(&sh_ex_info)) - { - return ElevationPromptChoice::NO; - } - if (sh_ex_info.hProcess == nullptr) - { - return ElevationPromptChoice::NO; - } - WaitForSingleObject(sh_ex_info.hProcess, INFINITE); - CloseHandle(sh_ex_info.hProcess); - return ElevationPromptChoice::YES; - } - - static fs::path get_appdata_targets_path() - { - static const fs::path LOCAL_APP_DATA = - fs::path(System::get_environment_variable(L"LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO)); - return LOCAL_APP_DATA / "vcpkg" / "vcpkg.user.targets"; - } - - static void integrate_install(const VcpkgPaths& paths) - { - auto& fs = paths.get_filesystem(); - - // TODO: This block of code should eventually be removed - for (auto&& old_system_wide_targets_file : OLD_SYSTEM_TARGET_FILES) - { - if (fs.exists(old_system_wide_targets_file)) - { - const std::string param = - Strings::format(R"(/c DEL "%s" /Q > nul)", old_system_wide_targets_file.string()); - const ElevationPromptChoice user_choice = elevated_cmd_execute(param); - switch (user_choice) - { - case ElevationPromptChoice::YES: break; - case ElevationPromptChoice::NO: - System::println(System::Color::warning, "Warning: Previous integration file was not removed"); - Checks::exit_fail(VCPKG_LINE_INFO); - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - } - - std::error_code ec; - const fs::path tmp_dir = paths.buildsystems / "tmp"; - fs.create_directory(paths.buildsystems, ec); - fs.create_directory(tmp_dir, ec); - - bool should_install_system = true; - const Expected system_wide_file_contents = fs.read_contents(SYSTEM_WIDE_TARGETS_FILE); - static const std::regex RE(R"###()###"); - if (const auto contents_data = system_wide_file_contents.get()) - { - std::match_results match; - const auto found = std::regex_search(*contents_data, match, RE); - if (found) - { - const int ver = atoi(match[1].str().c_str()); - if (ver >= 1) should_install_system = false; - } - } - - if (should_install_system) - { - const fs::path sys_src_path = tmp_dir / "vcpkg.system.targets"; - fs.write_contents(sys_src_path, create_system_targets_shortcut()); - - const std::string param = Strings::format(R"(/c mkdir "%s" & copy "%s" "%s" /Y > nul)", - SYSTEM_WIDE_TARGETS_FILE.parent_path().string(), - sys_src_path.string(), - SYSTEM_WIDE_TARGETS_FILE.string()); - const ElevationPromptChoice user_choice = elevated_cmd_execute(param); - switch (user_choice) - { - case ElevationPromptChoice::YES: break; - case ElevationPromptChoice::NO: - System::println(System::Color::warning, "Warning: integration was not applied"); - Checks::exit_fail(VCPKG_LINE_INFO); - default: Checks::unreachable(VCPKG_LINE_INFO); - } - - Checks::check_exit(VCPKG_LINE_INFO, - fs.exists(SYSTEM_WIDE_TARGETS_FILE), - "Error: failed to copy targets file to %s", - SYSTEM_WIDE_TARGETS_FILE.string()); - } - - const fs::path appdata_src_path = tmp_dir / "vcpkg.user.targets"; - fs.write_contents(appdata_src_path, - create_appdata_targets_shortcut(paths.buildsystems_msbuild_targets.string())); - auto appdata_dst_path = get_appdata_targets_path(); - - const auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec); - - if (!rc || ec) - { - System::println(System::Color::error, - "Error: Failed to copy file: %s -> %s", - appdata_src_path.string(), - appdata_dst_path.string()); - Checks::exit_fail(VCPKG_LINE_INFO); - } - System::println(System::Color::success, "Applied user-wide integration for this vcpkg root."); - const fs::path cmake_toolchain = paths.buildsystems / "vcpkg.cmake"; - System::println("\n" - "All MSBuild C++ projects can now #include any installed libraries.\n" - "Linking will be handled automatically.\n" - "Installing new libraries will make them instantly available.\n" - "\n" - "CMake projects should use -DCMAKE_TOOLCHAIN_FILE=%s", - cmake_toolchain.generic_string()); - - Checks::exit_success(VCPKG_LINE_INFO); - } - - static void integrate_remove(Files::Filesystem& fs) - { - const fs::path path = get_appdata_targets_path(); - - std::error_code ec; - const bool was_deleted = fs.remove(path, ec); - - Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %d", ec.message()); - - if (was_deleted) - { - System::println(System::Color::success, "User-wide integration was removed"); - } - else - { - System::println(System::Color::success, "User-wide integration is not installed"); - } - - Checks::exit_success(VCPKG_LINE_INFO); - } - - static void integrate_project(const VcpkgPaths& paths) - { - auto& fs = paths.get_filesystem(); - - const fs::path& nuget_exe = paths.get_nuget_exe(); - - const fs::path& buildsystems_dir = paths.buildsystems; - const fs::path tmp_dir = buildsystems_dir / "tmp"; - std::error_code ec; - fs.create_directory(buildsystems_dir, ec); - fs.create_directory(tmp_dir, ec); - - const fs::path targets_file_path = tmp_dir / "vcpkg.nuget.targets"; - const fs::path props_file_path = tmp_dir / "vcpkg.nuget.props"; - const fs::path nuspec_file_path = tmp_dir / "vcpkg.nuget.nuspec"; - const std::string nuget_id = get_nuget_id(paths.root); - const std::string nupkg_version = "1.0.0"; - - fs.write_contents(targets_file_path, create_nuget_targets_file_contents(paths.buildsystems_msbuild_targets)); - fs.write_contents(props_file_path, create_nuget_props_file_contents()); - fs.write_contents(nuspec_file_path, create_nuspec_file_contents(paths.root, nuget_id, nupkg_version)); - - // Using all forward slashes for the command line - const std::wstring cmd_line = Strings::wformat(LR"("%s" pack -OutputDirectory "%s" "%s" > nul)", - nuget_exe.native(), - buildsystems_dir.native(), - nuspec_file_path.native()); - - const int exit_code = System::cmd_execute_clean(cmd_line); - - const fs::path nuget_package = buildsystems_dir / Strings::format("%s.%s.nupkg", nuget_id, nupkg_version); - Checks::check_exit( - VCPKG_LINE_INFO, exit_code == 0 && fs.exists(nuget_package), "Error: NuGet package creation failed"); - System::println(System::Color::success, "Created nupkg: %s", nuget_package.string()); - - auto source_path = buildsystems_dir.u8string(); - source_path = std::regex_replace(source_path, std::regex("`"), "``"); - - System::println(R"( -With a project open, go to Tools->NuGet Package Manager->Package Manager Console and paste: - Install-Package %s -Source "%s" -)", - nuget_id, - source_path); - - Checks::exit_success(VCPKG_LINE_INFO); - } - - const char* const INTEGRATE_COMMAND_HELPSTRING = - " vcpkg integrate install Make installed packages available user-wide. Requires admin privileges on " - "first use\n" - " vcpkg integrate remove Remove user-wide integration\n" - " vcpkg integrate project Generate a referencing nuget package for individual VS project use\n"; - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - static const std::string EXAMPLE = Strings::format("Commands:\n" - "%s", - INTEGRATE_COMMAND_HELPSTRING); - args.check_exact_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}); - - if (args.command_arguments[0] == "install") - { - return integrate_install(paths); - } - if (args.command_arguments[0] == "remove") - { - return integrate_remove(paths.get_filesystem()); - } - if (args.command_arguments[0] == "project") - { - return integrate_project(paths); - } - - Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown parameter %s for integrate", args.command_arguments[0]); - } -} diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp deleted file mode 100644 index 640885860..000000000 --- a/toolsrc/src/commands_list.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Commands.h" -#include "vcpkg_System.h" -#include "vcpkglib.h" - -namespace vcpkg::Commands::List -{ - static const std::string OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually - - static void do_print(const StatusParagraph& pgh, bool full_desc) - { - if (full_desc) - { - System::println("%-30s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description); - } - else - { - System::println("%-30s %-16s %s", - vcpkg::shorten_text(pgh.package.displayname(), 30), - vcpkg::shorten_text(pgh.package.version, 16), - vcpkg::shorten_text(pgh.package.description, 71)); - } - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - static const std::string EXAMPLE = Strings::format( - "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", - Commands::Help::create_example_string("list png")); - args.check_max_arg_count(1, EXAMPLE); - const std::unordered_set options = - args.check_and_get_optional_command_arguments({OPTION_FULLDESC}); - - const StatusParagraphs status_paragraphs = database_load_check(paths); - std::vector installed_packages = get_installed_ports(status_paragraphs); - - if (installed_packages.empty()) - { - System::println("No packages are installed. Did you mean `search`?"); - Checks::exit_success(VCPKG_LINE_INFO); - } - - std::sort(installed_packages.begin(), - installed_packages.end(), - [](const StatusParagraph* lhs, const StatusParagraph* rhs) -> bool { - return lhs->package.displayname() < rhs->package.displayname(); - }); - - if (args.command_arguments.size() == 0) - { - for (const StatusParagraph* status_paragraph : installed_packages) - { - do_print(*status_paragraph, options.find(OPTION_FULLDESC) != options.cend()); - } - } - else - { - // At this point there is 1 argument - for (const StatusParagraph* status_paragraph : installed_packages) - { - const std::string displayname = status_paragraph->package.displayname(); - if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end()) - { - continue; - } - - do_print(*status_paragraph, options.find(OPTION_FULLDESC) != options.cend()); - } - } - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_owns.cpp b/toolsrc/src/commands_owns.cpp deleted file mode 100644 index 718a0277f..000000000 --- a/toolsrc/src/commands_owns.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Commands.h" -#include "vcpkg_System.h" -#include "vcpkglib.h" - -namespace vcpkg::Commands::Owns -{ - static void search_file(const VcpkgPaths& paths, const std::string& file_substr, const StatusParagraphs& status_db) - { - const std::vector installed_files = get_installed_files(paths, status_db); - for (const StatusParagraphAndAssociatedFiles& pgh_and_file : installed_files) - { - const StatusParagraph& pgh = pgh_and_file.pgh; - - for (const std::string& file : pgh_and_file.files) - { - if (file.find(file_substr) != std::string::npos) - { - System::println("%s: %s", pgh.package.displayname(), file); - } - } - } - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - static const std::string EXAMPLE = Strings::format("The argument should be a pattern to search for. %s", - Commands::Help::create_example_string("owns zlib.dll")); - args.check_exact_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}); - - StatusParagraphs status_db = database_load_check(paths); - search_file(paths, args.command_arguments[0], status_db); - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp deleted file mode 100644 index 2334b2270..000000000 --- a/toolsrc/src/commands_portsdiff.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "SortedVector.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Maps.h" -#include "vcpkg_System.h" - -namespace vcpkg::Commands::PortsDiff -{ - struct UpdatedPort - { - static bool compare_by_name(const UpdatedPort& left, const UpdatedPort& right) - { - return left.port < right.port; - } - - std::string port; - VersionDiff version_diff; - }; - - template - struct SetElementPresence - { - static SetElementPresence create(std::vector left, std::vector right) - { - // TODO: This can be done with one pass instead of three passes - SetElementPresence output; - std::set_difference( - left.cbegin(), left.cend(), right.cbegin(), right.cend(), std::back_inserter(output.only_left)); - std::set_intersection( - left.cbegin(), left.cend(), right.cbegin(), right.cend(), std::back_inserter(output.both)); - std::set_difference( - right.cbegin(), right.cend(), left.cbegin(), left.cend(), std::back_inserter(output.only_right)); - - return output; - } - - std::vector only_left; - std::vector both; - std::vector only_right; - }; - - static std::vector find_updated_ports( - const std::vector& ports, - const std::map& previous_names_and_versions, - const std::map& current_names_and_versions) - { - std::vector output; - for (const std::string& name : ports) - { - const VersionT& previous_version = previous_names_and_versions.at(name); - const VersionT& current_version = current_names_and_versions.at(name); - if (previous_version == current_version) - { - continue; - } - - output.push_back({name, VersionDiff(previous_version, current_version)}); - } - - return output; - } - - static void do_print_name_and_version(const std::vector& ports_to_print, - const std::map& names_and_versions) - { - for (const std::string& name : ports_to_print) - { - const VersionT& version = names_and_versions.at(name); - System::println(" - %-14s %-16s", name, version); - } - } - - static std::map read_ports_from_commit(const VcpkgPaths& paths, - const std::wstring& git_commit_id) - { - std::error_code ec; - auto& fs = paths.get_filesystem(); - const fs::path& git_exe = paths.get_git_exe(); - const fs::path dot_git_dir = paths.root / ".git"; - const std::wstring ports_dir_name_as_string = paths.ports.filename().native(); - const fs::path temp_checkout_path = - paths.root / Strings::wformat(L"%s-%s", ports_dir_name_as_string, git_commit_id); - fs.create_directory(temp_checkout_path, ec); - const std::wstring checkout_this_dir = - Strings::wformat(LR"(.\%s)", ports_dir_name_as_string); // Must be relative to the root of the repository - - const std::wstring cmd = - Strings::wformat(LR"("%s" --git-dir="%s" --work-tree="%s" checkout %s -f -q -- %s %s & "%s" reset >NUL)", - git_exe.native(), - dot_git_dir.native(), - temp_checkout_path.native(), - git_commit_id, - checkout_this_dir, - L".vcpkg-root", - git_exe.native()); - System::cmd_execute_clean(cmd); - const std::map names_and_versions = Paragraphs::load_all_port_names_and_versions( - paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); - fs.remove_all(temp_checkout_path, ec); - return names_and_versions; - } - - static void check_commit_exists(const fs::path& git_exe, const std::wstring& git_commit_id) - { - static const std::string VALID_COMMIT_OUTPUT = "commit\n"; - - const std::wstring cmd = Strings::wformat(LR"("%s" cat-file -t %s)", git_exe.native(), git_commit_id); - const System::ExitCodeAndOutput output = System::cmd_execute_and_capture_output(cmd); - Checks::check_exit(VCPKG_LINE_INFO, - output.output == VALID_COMMIT_OUTPUT, - "Invalid commit id %s", - Strings::to_utf8(git_commit_id)); - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - static const std::string EXAMPLE = - Strings::format("The argument should be a branch/tag/hash to checkout.\n%s", - Commands::Help::create_example_string("portsdiff mybranchname")); - args.check_min_arg_count(1, EXAMPLE); - args.check_max_arg_count(2, EXAMPLE); - args.check_and_get_optional_command_arguments({}); - - const fs::path& git_exe = paths.get_git_exe(); - - const std::wstring git_commit_id_for_previous_snapshot = Strings::to_utf16(args.command_arguments.at(0)); - const std::wstring git_commit_id_for_current_snapshot = - args.command_arguments.size() < 2 ? L"HEAD" : Strings::to_utf16(args.command_arguments.at(1)); - - check_commit_exists(git_exe, git_commit_id_for_current_snapshot); - check_commit_exists(git_exe, git_commit_id_for_previous_snapshot); - - const std::map current_names_and_versions = - read_ports_from_commit(paths, git_commit_id_for_current_snapshot); - const std::map previous_names_and_versions = - read_ports_from_commit(paths, git_commit_id_for_previous_snapshot); - - // Already sorted, so set_difference can work on std::vector too - const std::vector current_ports = Maps::extract_keys(current_names_and_versions); - const std::vector previous_ports = Maps::extract_keys(previous_names_and_versions); - - const SetElementPresence setp = - SetElementPresence::create(current_ports, previous_ports); - - const std::vector& added_ports = setp.only_left; - if (!added_ports.empty()) - { - System::println("\nThe following %d ports were added:", added_ports.size()); - do_print_name_and_version(added_ports, current_names_and_versions); - } - - const std::vector& removed_ports = setp.only_right; - if (!removed_ports.empty()) - { - System::println("\nThe following %d ports were removed:", removed_ports.size()); - do_print_name_and_version(removed_ports, previous_names_and_versions); - } - - const std::vector& common_ports = setp.both; - const std::vector updated_ports = - find_updated_ports(common_ports, previous_names_and_versions, current_names_and_versions); - - if (!updated_ports.empty()) - { - System::println("\nThe following %d ports were updated:", updated_ports.size()); - for (const UpdatedPort& p : updated_ports) - { - System::println(" - %-14s %-16s", p.port, p.version_diff.to_string()); - } - } - - if (added_ports.empty() && removed_ports.empty() && updated_ports.empty()) - { - System::println("There were no changes in the ports between the two commits."); - } - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp deleted file mode 100644 index a9f1b2564..000000000 --- a/toolsrc/src/commands_remove.cpp +++ /dev/null @@ -1,249 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Commands.h" -#include "vcpkg_Dependencies.h" -#include "vcpkg_Input.h" -#include "vcpkg_System.h" -#include "vcpkg_Util.h" -#include "vcpkglib.h" - -namespace vcpkg::Commands::Remove -{ - using Dependencies::RemovePlanAction; - using Dependencies::RemovePlanType; - using Dependencies::RequestType; - using Update::OutdatedPackage; - - void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db) - { - auto& fs = paths.get_filesystem(); - auto spghs = status_db->find_all(spec.name(), spec.triplet()); - const auto core_pkg = **status_db->find(spec.name(), spec.triplet(), Strings::EMPTY); - - for (auto&& spgh : spghs) - { - StatusParagraph& pkg = **spgh; - if (pkg.state != InstallState::INSTALLED) continue; - pkg.want = Want::PURGE; - pkg.state = InstallState::HALF_INSTALLED; - write_update(paths, pkg); - } - - auto maybe_lines = fs.read_lines(paths.listfile_path(core_pkg.package)); - - if (const auto lines = maybe_lines.get()) - { - std::vector dirs_touched; - for (auto&& suffix : *lines) - { - if (!suffix.empty() && suffix.back() == '\r') suffix.pop_back(); - - std::error_code ec; - - auto target = paths.installed / suffix; - - const auto status = fs.status(target, ec); - if (ec) - { - System::println(System::Color::error, "failed: %s", ec.message()); - continue; - } - - if (fs::is_directory(status)) - { - dirs_touched.push_back(target); - } - else if (fs::is_regular_file(status)) - { - fs.remove(target, ec); - if (ec) - { - System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); - } - } - else if (!fs::status_known(status)) - { - System::println(System::Color::warning, "Warning: unknown status: %s", target.u8string()); - } - else - { - System::println(System::Color::warning, "Warning: %s: cannot handle file type", target.u8string()); - } - } - - auto b = dirs_touched.rbegin(); - const auto e = dirs_touched.rend(); - for (; b != e; ++b) - { - if (fs.is_empty(*b)) - { - std::error_code ec; - fs.remove(*b, ec); - if (ec) - { - System::println(System::Color::error, "failed: %s", ec.message()); - } - } - } - - fs.remove(paths.listfile_path(core_pkg.package)); - } - - for (auto&& spgh : spghs) - { - StatusParagraph& pkg = **spgh; - if (pkg.state != InstallState::HALF_INSTALLED) continue; - pkg.state = InstallState::NOT_INSTALLED; - write_update(paths, pkg); - } - } - - static void print_plan(const std::map>& group_by_plan_type) - { - static constexpr std::array ORDER = {RemovePlanType::NOT_INSTALLED, RemovePlanType::REMOVE}; - - for (const RemovePlanType plan_type : ORDER) - { - const auto it = group_by_plan_type.find(plan_type); - if (it == group_by_plan_type.cend()) - { - continue; - } - - std::vector cont = it->second; - std::sort(cont.begin(), cont.end(), &RemovePlanAction::compare_by_name); - const std::string as_string = Strings::join("\n", cont, [](const RemovePlanAction* p) { - return Dependencies::to_output_string(p->request_type, p->spec.to_string()); - }); - - switch (plan_type) - { - case RemovePlanType::NOT_INSTALLED: - System::println("The following packages are not installed, so not removed:\n%s", as_string); - continue; - case RemovePlanType::REMOVE: - System::println("The following packages will be removed:\n%s", as_string); - continue; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - } - - void perform_remove_plan_action(const VcpkgPaths& paths, - const RemovePlanAction& action, - const Purge purge, - StatusParagraphs& status_db) - { - const std::string display_name = action.spec.to_string(); - - switch (action.plan_type) - { - case RemovePlanType::NOT_INSTALLED: - System::println(System::Color::success, "Package %s is not installed", display_name); - break; - case RemovePlanType::REMOVE: - System::println("Removing package %s... ", display_name); - remove_package(paths, action.spec, &status_db); - System::println(System::Color::success, "Removing package %s... done", display_name); - break; - case RemovePlanType::UNKNOWN: - default: Checks::unreachable(VCPKG_LINE_INFO); - } - - if (purge == Purge::YES) - { - System::println("Purging package %s... ", display_name); - Files::Filesystem& fs = paths.get_filesystem(); - std::error_code ec; - fs.remove_all(paths.packages / action.spec.dir(), ec); - System::println(System::Color::success, "Purging package %s... done", display_name); - } - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) - { - static const std::string OPTION_PURGE = "--purge"; - static const std::string OPTION_NO_PURGE = "--no-purge"; - static const std::string OPTION_RECURSE = "--recurse"; - static const std::string OPTION_DRY_RUN = "--dry-run"; - static const std::string OPTION_OUTDATED = "--outdated"; - static const std::string EXAMPLE = - Commands::Help::create_example_string("remove zlib zlib:x64-windows curl boost"); - const std::unordered_set options = args.check_and_get_optional_command_arguments( - {OPTION_PURGE, OPTION_NO_PURGE, OPTION_RECURSE, OPTION_DRY_RUN, OPTION_OUTDATED}); - - StatusParagraphs status_db = database_load_check(paths); - std::vector specs; - if (options.find(OPTION_OUTDATED) != options.cend()) - { - args.check_exact_arg_count(0, EXAMPLE); - specs = Util::fmap(Update::find_outdated_packages(paths, status_db), - [](auto&& outdated) { return outdated.spec; }); - - if (specs.empty()) - { - System::println(System::Color::success, "There are no outdated packages."); - Checks::exit_success(VCPKG_LINE_INFO); - } - } - else - { - args.check_min_arg_count(1, EXAMPLE); - specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); - }); - - for (auto&& spec : specs) - Input::check_triplet(spec.triplet(), paths); - } - - const bool no_purge_was_passed = options.find(OPTION_NO_PURGE) != options.end(); - const bool purge_was_passed = options.find(OPTION_PURGE) != options.end(); - if (purge_was_passed && no_purge_was_passed) - { - System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); - System::print(EXAMPLE); - Checks::exit_fail(VCPKG_LINE_INFO); - } - const Purge purge = to_purge(purge_was_passed || !no_purge_was_passed); - const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); - const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend(); - - const std::vector remove_plan = Dependencies::create_remove_plan(specs, status_db); - Checks::check_exit(VCPKG_LINE_INFO, !remove_plan.empty(), "Remove plan cannot be empty"); - - std::map> group_by_plan_type; - Util::group_by(remove_plan, &group_by_plan_type, [](const RemovePlanAction& p) { return p.plan_type; }); - print_plan(group_by_plan_type); - - const bool has_non_user_requested_packages = - Util::find_if(remove_plan, [](const RemovePlanAction& package) -> bool { - return package.request_type != RequestType::USER_REQUESTED; - }) != remove_plan.cend(); - - if (has_non_user_requested_packages) - { - System::println(System::Color::warning, - "Additional packages (*) need to be removed to complete this operation."); - - if (!is_recursive) - { - System::println(System::Color::warning, - "If you are sure you want to remove them, run the command with the --recurse option"); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - - if (dry_run) - { - Checks::exit_success(VCPKG_LINE_INFO); - } - - for (const RemovePlanAction& action : remove_plan) - { - perform_remove_plan_action(paths, action, purge, status_db); - } - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp deleted file mode 100644 index d35a546c4..000000000 --- a/toolsrc/src/commands_search.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "SourceParagraph.h" -#include "vcpkg_Commands.h" -#include "vcpkg_GlobalState.h" -#include "vcpkg_System.h" -#include "vcpkglib.h" - -namespace vcpkg::Commands::Search -{ - static const std::string OPTION_GRAPH = "--graph"; // TODO: This should find a better home, eventually - static const std::string OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually - - static std::string replace_dashes_with_underscore(const std::string& input) - { - std::string output = input; - std::replace(output.begin(), output.end(), '-', '_'); - return output; - } - - static std::string create_graph_as_string( - const std::vector>& source_control_files) - { - int empty_node_count = 0; - - std::string s; - s.append("digraph G{ rankdir=LR; edge [minlen=3]; overlap=false;"); - - for (const auto& source_control_file : source_control_files) - { - const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; - if (source_paragraph.depends.empty()) - { - empty_node_count++; - continue; - } - - const std::string name = replace_dashes_with_underscore(source_paragraph.name); - s.append(Strings::format("%s;", name)); - for (const Dependency& d : source_paragraph.depends) - { - const std::string dependency_name = replace_dashes_with_underscore(d.name()); - s.append(Strings::format("%s -> %s;", name, dependency_name)); - } - } - - s.append(Strings::format("empty [label=\"%d singletons...\"]; }", empty_node_count)); - return s; - } - static void do_print(const SourceParagraph& source_paragraph, bool full_desc) - { - if (full_desc) - { - System::println( - "%-20s %-16s %s", source_paragraph.name, source_paragraph.version, source_paragraph.description); - } - else - { - System::println("%-20s %-16s %s", - vcpkg::shorten_text(source_paragraph.name, 20), - vcpkg::shorten_text(source_paragraph.version, 16), - vcpkg::shorten_text(source_paragraph.description, 81)); - } - } - - static void do_print(const std::string& name, const FeatureParagraph& feature_paragraph, bool full_desc) - { - if (full_desc) - { - System::println("%-37s %s", name + "[" + feature_paragraph.name + "]", feature_paragraph.description); - } - else - { - System::println("%-37s %s", - vcpkg::shorten_text(name + "[" + feature_paragraph.name + "]", 37), - vcpkg::shorten_text(feature_paragraph.description, 81)); - } - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - static const std::string EXAMPLE = Strings::format( - "The argument should be a substring to search for, or no argument to display all libraries.\n%s", - Commands::Help::create_example_string("search png")); - args.check_max_arg_count(1, EXAMPLE); - const std::unordered_set options = - args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC}); - - auto source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - - if (options.find(OPTION_GRAPH) != options.cend()) - { - const std::string graph_as_string = create_graph_as_string(source_paragraphs); - System::println(graph_as_string); - Checks::exit_success(VCPKG_LINE_INFO); - } - - if (args.command_arguments.empty()) - { - for (const auto& source_control_file : source_paragraphs) - { - do_print(*source_control_file->core_paragraph, options.find(OPTION_FULLDESC) != options.cend()); - for (auto&& feature_paragraph : source_control_file->feature_paragraphs) - { - do_print(source_control_file->core_paragraph->name, - *feature_paragraph, - options.find(OPTION_FULLDESC) != options.cend()); - } - } - } - else - { - const auto& icontains = Strings::case_insensitive_ascii_contains; - - // At this point there is 1 argument - auto&& args_zero = args.command_arguments[0]; - for (const auto& source_control_file : source_paragraphs) - { - auto&& sp = *source_control_file->core_paragraph; - - bool contains_name = icontains(sp.name, args_zero); - if (contains_name || icontains(sp.description, args_zero)) - { - do_print(sp, options.find(OPTION_FULLDESC) != options.cend()); - } - - for (auto&& feature_paragraph : source_control_file->feature_paragraphs) - { - if (contains_name || icontains(feature_paragraph->name, args_zero) || - icontains(feature_paragraph->description, args_zero)) - { - do_print(sp.name, *feature_paragraph, options.find(OPTION_FULLDESC) != options.cend()); - } - } - } - } - - System::println( - "\nIf your library is not listed, please open an issue at and/or consider making a pull request:\n" - " https://github.com/Microsoft/vcpkg/issues"); - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp deleted file mode 100644 index 71ea4b063..000000000 --- a/toolsrc/src/commands_update.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "vcpkg_Commands.h" -#include "vcpkg_System.h" -#include "vcpkglib.h" - -namespace vcpkg::Commands::Update -{ - bool OutdatedPackage::compare_by_name(const OutdatedPackage& left, const OutdatedPackage& right) - { - return left.spec.name() < right.spec.name(); - } - - std::vector find_outdated_packages(const VcpkgPaths& paths, const StatusParagraphs& status_db) - { - const std::map src_names_to_versions = - Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports); - const std::vector installed_packages = get_installed_ports(status_db); - - std::vector output; - for (const StatusParagraph* pgh : installed_packages) - { - const auto it = src_names_to_versions.find(pgh->package.spec.name()); - if (it == src_names_to_versions.end()) - { - // Package was not installed from portfile - continue; - } - if (it->second != pgh->package.version) - { - output.push_back({pgh->package.spec, VersionDiff(pgh->package.version, it->second)}); - } - } - - return output; - } - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) - { - args.check_exact_arg_count(0); - args.check_and_get_optional_command_arguments({}); - System::println("Using local portfile versions. To update the local portfiles, use `git pull`."); - - const StatusParagraphs status_db = database_load_check(paths); - - const auto outdated_packages = - SortedVector(find_outdated_packages(paths, status_db), &OutdatedPackage::compare_by_name); - - if (outdated_packages.empty()) - { - System::println("No packages need updating."); - } - else - { - std::string install_line; - System::println("The following packages differ from their port versions:"); - for (auto&& package : outdated_packages) - { - install_line += package.spec.to_string(); - install_line += " "; - System::println(" %-32s %s", package.spec, package.version_diff.to_string()); - } - System::println("\n" - "To update these packages, run\n" - " .\\vcpkg remove --outdated\n" - " .\\vcpkg install " + - install_line); - } - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/commands_version.cpp b/toolsrc/src/commands_version.cpp deleted file mode 100644 index 5744ea9ef..000000000 --- a/toolsrc/src/commands_version.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "pch.h" - -#include "metrics.h" -#include "vcpkg_Commands.h" -#include "vcpkg_System.h" - -#define STRINGIFY(...) #__VA_ARGS__ -#define MACRO_TO_STRING(X) STRINGIFY(X) - -#define VCPKG_VERSION_AS_STRING MACRO_TO_STRING(VCPKG_VERSION) - -namespace vcpkg::Commands::Version -{ - const std::string& version() - { - static const std::string S_VERSION = -#include "../VERSION.txt" - - +std::string(VCPKG_VERSION_AS_STRING) -#ifndef NDEBUG - + std::string("-debug") -#endif - + std::string(Metrics::get_compiled_metrics_enabled() ? Strings::EMPTY : "-external"); - return S_VERSION; - } - - void warn_if_vcpkg_version_mismatch(const VcpkgPaths& paths) - { - auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt"); - if (const auto version_contents = version_file.get()) - { - int maj1, min1, rev1; - const auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1); - - int maj2, min2, rev2; - const auto num2 = sscanf_s(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2); - - if (num1 == 3 && num2 == 3) - { - if (maj1 != maj2 || min1 != min2 || rev1 != rev2) - { - System::println(System::Color::warning, - "Warning: Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use " - ".\\bootstrap-vcpkg.bat to update.", - maj2, - min2, - rev2, - maj1, - min1, - rev1); - } - } - } - } - - void perform_and_exit(const VcpkgCmdArguments& args) - { - args.check_exact_arg_count(0); - args.check_and_get_optional_command_arguments({}); - - System::println("Vcpkg package management program version %s\n" - "\n" - "See LICENSE.txt for license information.", - version()); - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp deleted file mode 100644 index 8a0050bfc..000000000 --- a/toolsrc/src/metrics.cpp +++ /dev/null @@ -1,395 +0,0 @@ -#include "pch.h" - -#include "filesystem_fs.h" -#include "metrics.h" -#include "vcpkg_Files.h" -#include "vcpkg_Strings.h" -#include "vcpkg_System.h" - -namespace vcpkg::Metrics -{ - Util::LockGuarded g_metrics; - - static std::string get_current_date_time() - { - struct tm newtime; - std::array date; - date.fill(0); - - struct _timeb timebuffer; - - _ftime_s(&timebuffer); - time_t now = timebuffer.time; - const int milli = timebuffer.millitm; - - const errno_t err = gmtime_s(&newtime, &now); - if (err) - { - return Strings::EMPTY; - } - - strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S", &newtime); - return std::string(&date[0]) + "." + std::to_string(milli) + "Z"; - } - - static std::string generate_random_UUID() - { - int part_sizes[] = {8, 4, 4, 4, 12}; - char uuid[37]; - memset(uuid, 0, sizeof(uuid)); - int num; - srand(static_cast(time(nullptr))); - int index = 0; - for (int part = 0; part < 5; part++) - { - if (part > 0) - { - uuid[index] = '-'; - index++; - } - - // Generating UUID format version 4 - // http://en.wikipedia.org/wiki/Universally_unique_identifier - for (int i = 0; i < part_sizes[part]; i++, index++) - { - if (part == 2 && i == 0) - { - num = 4; - } - else if (part == 4 && i == 0) - { - num = (rand() % 4) + 8; - } - else - { - num = rand() % 16; - } - - if (num < 10) - { - uuid[index] = static_cast('0' + num); - } - else - { - uuid[index] = static_cast('a' + (num - 10)); - } - } - } - - return uuid; - } - - static const std::string& get_session_id() - { - static const std::string ID = generate_random_UUID(); - return ID; - } - - static std::string to_json_string(const std::string& str) - { - std::string encoded = "\""; - for (auto&& ch : str) - { - if (ch == '\\') - { - encoded.append("\\\\"); - } - else if (ch == '"') - { - encoded.append("\\\""); - } - else if (ch < 0x20 || ch >= 0x80) - { - // Note: this treats incoming Strings as Latin-1 - static constexpr const char HEX[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - encoded.append("\\u00"); - encoded.push_back(HEX[ch / 16]); - encoded.push_back(HEX[ch % 16]); - } - else - { - encoded.push_back(ch); - } - } - encoded.push_back('"'); - return encoded; - } - - static std::string get_os_version_string() - { - std::wstring path; - path.resize(MAX_PATH); - const auto n = GetSystemDirectoryW(&path[0], static_cast(path.size())); - path.resize(n); - path += L"\\kernel32.dll"; - - const auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr); - if (versz == 0) return Strings::EMPTY; - - std::vector verbuf; - verbuf.resize(versz); - - if (!GetFileVersionInfoW(path.c_str(), 0, static_cast(verbuf.size()), &verbuf[0])) return Strings::EMPTY; - - void* rootblock; - UINT rootblocksize; - if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return Strings::EMPTY; - - auto rootblock_ffi = static_cast(rootblock); - - return Strings::format("%d.%d.%d", - static_cast(HIWORD(rootblock_ffi->dwProductVersionMS)), - static_cast(LOWORD(rootblock_ffi->dwProductVersionMS)), - static_cast(HIWORD(rootblock_ffi->dwProductVersionLS))); - } - - struct MetricMessage - { - std::string user_id = generate_random_UUID(); - std::string user_timestamp; - std::string timestamp = get_current_date_time(); - std::string properties; - std::string measurements; - - void track_property(const std::string& name, const std::string& value) - { - if (properties.size() != 0) properties.push_back(','); - properties.append(to_json_string(name)); - properties.push_back(':'); - properties.append(to_json_string(value)); - } - - void track_metric(const std::string& name, double value) - { - if (measurements.size() != 0) measurements.push_back(','); - measurements.append(to_json_string(name)); - measurements.push_back(':'); - measurements.append(std::to_string(value)); - } - - std::string format_event_data_template() const - { - const std::string& session_id = get_session_id(); - return Strings::format(R"([{ - "ver": 1, - "name": "Microsoft.ApplicationInsights.Event", - "time": "%s", - "sampleRate": 100.000000, - "seq": "0:0", - "iKey": "b4e88960-4393-4dd9-ab8e-97e8fe6d7603", - "flags": 0.000000, - "tags": { - "ai.device.os": "Windows", - "ai.device.osVersion": "%s", - "ai.session.id": "%s", - "ai.user.id": "%s", - "ai.user.accountAcquisitionDate": "%s" - }, - "data": { - "baseType": "EventData", - "baseData": { - "ver": 2, - "name": "commandline_test7", - "properties": { %s }, - "measurements": { %s } - } - } -}])", - timestamp, - get_os_version_string(), - session_id, - user_id, - user_timestamp, - properties, - measurements); - } - }; - - static MetricMessage g_metricmessage; - static bool g_should_send_metrics = -#if defined(NDEBUG) && (DISABLE_METRICS == 0) - true -#else - false -#endif - ; - static bool g_should_print_metrics = false; - - bool get_compiled_metrics_enabled() { return DISABLE_METRICS == 0; } - - std::wstring get_SQM_user() - { - auto hkcu_sqmclient = - System::get_registry_string(HKEY_CURRENT_USER, LR"(Software\Microsoft\SQMClient)", L"UserId"); - return hkcu_sqmclient.value_or(L"{}"); - } - - void Metrics::set_user_information(const std::string& user_id, const std::string& first_use_time) - { - g_metricmessage.user_id = user_id; - g_metricmessage.user_timestamp = first_use_time; - } - - void Metrics::init_user_information(std::string& user_id, std::string& first_use_time) - { - user_id = generate_random_UUID(); - first_use_time = get_current_date_time(); - } - - void Metrics::set_send_metrics(bool should_send_metrics) { g_should_send_metrics = should_send_metrics; } - - void Metrics::set_print_metrics(bool should_print_metrics) { g_should_print_metrics = should_print_metrics; } - - void Metrics::track_metric(const std::string& name, double value) { g_metricmessage.track_metric(name, value); } - - void Metrics::track_property(const std::string& name, const std::wstring& value) - { - // Note: this is not valid UTF-16 -> UTF-8, it just yields a close enough approximation for our purposes. - std::string converted_value; - converted_value.resize(value.size()); - std::transform( - value.begin(), value.end(), converted_value.begin(), [](wchar_t ch) { return static_cast(ch); }); - - g_metricmessage.track_property(name, converted_value); - } - - void Metrics::track_property(const std::string& name, const std::string& value) - { - g_metricmessage.track_property(name, value); - } - - void Metrics::upload(const std::string& payload) - { - HINTERNET connect = nullptr, request = nullptr; - BOOL results = FALSE; - - const HINTERNET session = WinHttpOpen( - L"vcpkg/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); - if (session) connect = WinHttpConnect(session, L"dc.services.visualstudio.com", INTERNET_DEFAULT_HTTPS_PORT, 0); - - if (connect) - request = WinHttpOpenRequest(connect, - L"POST", - L"/v2/track", - nullptr, - WINHTTP_NO_REFERER, - WINHTTP_DEFAULT_ACCEPT_TYPES, - WINHTTP_FLAG_SECURE); - - if (request) - { - if (MAXDWORD <= payload.size()) abort(); - std::wstring hdrs = L"Content-Type: application/json\r\n"; - std::string& p = const_cast(payload); - results = WinHttpSendRequest(request, - hdrs.c_str(), - static_cast(hdrs.size()), - static_cast(&p[0]), - static_cast(payload.size()), - static_cast(payload.size()), - 0); - } - - if (results) - { - results = WinHttpReceiveResponse(request, nullptr); - } - - DWORD http_code = 0, junk = sizeof(DWORD); - - if (results) - { - results = WinHttpQueryHeaders(request, - WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, - nullptr, - &http_code, - &junk, - WINHTTP_NO_HEADER_INDEX); - } - - std::vector response_buffer; - if (results) - { - DWORD available_data = 0, read_data = 0, total_data = 0; - while ((results = WinHttpQueryDataAvailable(request, &available_data)) == TRUE && available_data > 0) - { - response_buffer.resize(response_buffer.size() + available_data); - - results = WinHttpReadData(request, &response_buffer.data()[total_data], available_data, &read_data); - - if (!results) - { - break; - } - - total_data += read_data; - - response_buffer.resize(total_data); - } - } - - if (!results) - { -#ifndef NDEBUG - __debugbreak(); - auto err = GetLastError(); - std::cerr << "[DEBUG] failed to connect to server: " << err << "\n"; -#endif - } - - if (request) WinHttpCloseHandle(request); - if (connect) WinHttpCloseHandle(connect); - if (session) WinHttpCloseHandle(session); - } - - static fs::path get_bindir() - { - wchar_t buf[_MAX_PATH]; - const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); - if (bytes == 0) std::abort(); - return fs::path(buf, buf + bytes); - } - - void Metrics::flush() - { - const std::string payload = g_metricmessage.format_event_data_template(); - if (g_should_print_metrics) std::cerr << payload << "\n"; - if (!g_should_send_metrics) return; - - // upload(payload); - - wchar_t temp_folder[MAX_PATH]; - GetTempPathW(MAX_PATH, temp_folder); - - const fs::path temp_folder_path = temp_folder; - const fs::path temp_folder_path_exe = temp_folder_path / "vcpkgmetricsuploader.exe"; - - auto& fs = Files::get_real_filesystem(); - - if (true) - { - const fs::path exe_path = [&fs]() -> fs::path { - auto vcpkgdir = get_bindir().parent_path(); - auto path = vcpkgdir / "vcpkgmetricsuploader.exe"; - if (fs.exists(path)) return path; - - path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; - if (fs.exists(path)) return path; - - return Strings::WEMPTY; - }(); - - std::error_code ec; - fs.copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec); - if (ec) return; - } - - const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); - fs.write_contents(vcpkg_metrics_txt_path, payload); - - const std::wstring cmd_line = - Strings::wformat(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native()); - System::cmd_execute_clean(cmd_line); - } -} diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp deleted file mode 100644 index 6c9311264..000000000 --- a/toolsrc/src/test_install_plan.cpp +++ /dev/null @@ -1,486 +0,0 @@ -#include "CppUnitTest.h" -#include "vcpkg_Dependencies.h" -#include "vcpkg_Util.h" - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -using namespace vcpkg; - -namespace Microsoft::VisualStudio::CppUnitTestFramework -{ - template<> - inline std::wstring ToString(const vcpkg::Dependencies::InstallPlanType& t) - { - switch (t) - { - case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; - case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; - case Dependencies::InstallPlanType::INSTALL: return L"INSTALL"; - case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; - default: return ToString((int)t); - } - } - - template<> - inline std::wstring ToString(const vcpkg::Dependencies::RequestType& t) - { - switch (t) - { - case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED"; - case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED"; - case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN"; - default: return ToString((int)t); - } - } -} - -namespace UnitTest1 -{ - class InstallPlanTests : public TestClass - { - static std::unique_ptr make_control_file( - const char* name, - const char* depends, - const std::vector>& features = {}) - { - using Pgh = std::unordered_map; - std::vector scf_pghs; - scf_pghs.push_back(Pgh{ - {"Source", name}, - {"Version", "0"}, - {"Build-Depends", depends}, - }); - for (auto&& feature : features) - { - scf_pghs.push_back(Pgh{ - {"Feature", feature.first}, - {"Description", "feature"}, - {"Build-Depends", feature.second}, - }); - } - auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(scf_pghs)); - Assert::IsTrue(m_pgh.has_value()); - return std::move(*m_pgh.get()); - } - - static void features_check(Dependencies::AnyAction* install_action, - std::string pkg_name, - std::vector vec, - const Triplet& triplet = Triplet::X86_WINDOWS) - { - const auto& plan = install_action->install_plan.value_or_exit(VCPKG_LINE_INFO); - const auto& feature_list = plan.feature_list; - - Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); - - Assert::AreEqual(pkg_name.c_str(), - (*plan.any_paragraph.source_control_file.get())->core_paragraph->name.c_str()); - Assert::AreEqual(size_t(vec.size()), feature_list.size()); - - for (auto&& feature_name : vec) - { - if (feature_name == "core" || feature_name == "") - { - Assert::IsTrue(Util::find(feature_list, "core") != feature_list.end() || - Util::find(feature_list, "") != feature_list.end()); - continue; - } - Assert::IsTrue(Util::find(feature_list, feature_name) != feature_list.end()); - } - } - - static void remove_plan_check(Dependencies::AnyAction* remove_action, - std::string pkg_name, - const Triplet& triplet = Triplet::X86_WINDOWS) - { - const auto& plan = remove_action->remove_plan.value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); - Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); - } - - static std::unique_ptr make_status_pgh(const char* name, const char* depends = "") - { - using Pgh = std::unordered_map; - return std::make_unique(Pgh{{"Package", name}, - {"Version", "1"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", depends}, - {"Status", "install ok installed"}}); - } - static std::unique_ptr make_status_feature_pgh(const char* name, - const char* feature, - const char* depends = "") - { - using Pgh = std::unordered_map; - return std::make_unique(Pgh{{"Package", name}, - {"Version", "1"}, - {"Feature", feature}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", depends}, - {"Status", "install ok installed"}}); - } - struct PackageSpecMap - { - std::unordered_map map; - Triplet triplet; - PackageSpecMap(const Triplet& t) { triplet = t; } - - PackageSpec emplace(const char* name, - const char* depends = "", - const std::vector>& features = {}) - { - return emplace(std::move(*make_control_file(name, depends, features))); - } - PackageSpec emplace(vcpkg::SourceControlFile&& scf) - { - auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph->name, triplet); - Assert::IsTrue(spec.has_value()); - map.emplace(scf.core_paragraph->name, std::move(scf)); - return PackageSpec{*spec.get()}; - } - }; - - TEST_METHOD(basic_install_scheme) - { - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.emplace("a", "b"); - auto spec_b = spec_map.emplace("b", "c"); - auto spec_c = spec_map.emplace("c"); - - Dependencies::MapPortFile map_port(spec_map.map); - auto install_plan = - Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(3), install_plan.size()); - Assert::AreEqual("c", install_plan[0].spec.name().c_str()); - Assert::AreEqual("b", install_plan[1].spec.name().c_str()); - Assert::AreEqual("a", install_plan[2].spec.name().c_str()); - } - - TEST_METHOD(multiple_install_scheme) - { - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.emplace("a", "d"); - auto spec_b = spec_map.emplace("b", "d, e"); - auto spec_c = spec_map.emplace("c", "e, h"); - auto spec_d = spec_map.emplace("d", "f, g, h"); - auto spec_e = spec_map.emplace("e", "g"); - auto spec_f = spec_map.emplace("f"); - auto spec_g = spec_map.emplace("g"); - auto spec_h = spec_map.emplace("h"); - - Dependencies::MapPortFile map_port(spec_map.map); - auto install_plan = Dependencies::create_install_plan( - map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); - - auto iterator_pos = [&](const PackageSpec& spec) -> int { - auto it = std::find_if( - install_plan.begin(), install_plan.end(), [&](auto& action) { return action.spec == spec; }); - Assert::IsTrue(it != install_plan.end()); - return (int)(it - install_plan.begin()); - }; - - int a_pos = iterator_pos(spec_a), b_pos = iterator_pos(spec_b), c_pos = iterator_pos(spec_c), - d_pos = iterator_pos(spec_d), e_pos = iterator_pos(spec_e), f_pos = iterator_pos(spec_f), - g_pos = iterator_pos(spec_g), h_pos = iterator_pos(spec_h); - - Assert::IsTrue(a_pos > d_pos); - Assert::IsTrue(b_pos > e_pos); - Assert::IsTrue(b_pos > d_pos); - Assert::IsTrue(c_pos > e_pos); - Assert::IsTrue(c_pos > h_pos); - Assert::IsTrue(d_pos > f_pos); - Assert::IsTrue(d_pos > g_pos); - Assert::IsTrue(d_pos > h_pos); - Assert::IsTrue(e_pos > g_pos); - } - - TEST_METHOD(existing_package_scheme) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.emplace("a")}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(1), install_plan.size()); - auto p = install_plan[0].install_plan.get(); - Assert::IsNotNull(p); - Assert::AreEqual("a", p->spec.name().c_str()); - Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type); - Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p->request_type); - } - - TEST_METHOD(user_requested_package_scheme) - { - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b")}; - auto spec_b = FullPackageSpec{spec_map.emplace("b")}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(2), install_plan.size()); - auto p = install_plan[0].install_plan.get(); - Assert::IsNotNull(p); - Assert::AreEqual("b", p->spec.name().c_str()); - Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type); - Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type); - - auto p2 = install_plan[1].install_plan.get(); - Assert::IsNotNull(p2); - Assert::AreEqual("a", p2->spec.name().c_str()); - Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type); - Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p2->request_type); - } - - TEST_METHOD(long_install_scheme) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("j", "k")); - status_paragraphs.push_back(make_status_pgh("k")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = spec_map.emplace("a", "b, c, d, e, f, g, h, j, k"); - auto spec_b = spec_map.emplace("b", "c, d, e, f, g, h, j, k"); - auto spec_c = spec_map.emplace("c", "d, e, f, g, h, j, k"); - auto spec_d = spec_map.emplace("d", "e, f, g, h, j, k"); - auto spec_e = spec_map.emplace("e", "f, g, h, j, k"); - auto spec_f = spec_map.emplace("f", "g, h, j, k"); - auto spec_g = spec_map.emplace("g", "h, j, k"); - auto spec_h = spec_map.emplace("h", "j, k"); - auto spec_j = spec_map.emplace("j", "k"); - auto spec_k = spec_map.emplace("k"); - - Dependencies::MapPortFile map_port(spec_map.map); - auto install_plan = - Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(8), install_plan.size()); - Assert::AreEqual("h", install_plan[0].spec.name().c_str()); - Assert::AreEqual("g", install_plan[1].spec.name().c_str()); - Assert::AreEqual("f", install_plan[2].spec.name().c_str()); - Assert::AreEqual("e", install_plan[3].spec.name().c_str()); - Assert::AreEqual("d", install_plan[4].spec.name().c_str()); - Assert::AreEqual("c", install_plan[5].spec.name().c_str()); - Assert::AreEqual("b", install_plan[6].spec.name().c_str()); - Assert::AreEqual("a", install_plan[7].spec.name().c_str()); - } - - TEST_METHOD(basic_feature_test_1) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a", "b, b[b1]")); - status_paragraphs.push_back(make_status_pgh("b")); - status_paragraphs.push_back(make_status_feature_pgh("b", "b1")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(4), install_plan.size()); - remove_plan_check(&install_plan[0], "a"); - remove_plan_check(&install_plan[1], "b"); - features_check(&install_plan[2], "b", {"b1", "core", "b1"}); - features_check(&install_plan[3], "a", {"a1", "core"}); - } - - TEST_METHOD(basic_feature_test_2) - { - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(2), install_plan.size()); - features_check(&install_plan[0], "b", {"b1", "b2", "core"}); - features_check(&install_plan[1], "a", {"a1", "core"}); - } - - TEST_METHOD(basic_feature_test_3) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_c, spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(4), install_plan.size()); - remove_plan_check(&install_plan[0], "a"); - features_check(&install_plan[1], "b", {"core"}); - features_check(&install_plan[2], "a", {"a1", "core"}); - features_check(&install_plan[3], "c", {"core"}); - } - - TEST_METHOD(basic_feature_test_4) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.push_back(make_status_feature_pgh("a", "a1", "")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}})}; - auto spec_b = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_c}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(1), install_plan.size()); - features_check(&install_plan[0], "c", {"core"}); - } - - TEST_METHOD(basic_feature_test_5) - { - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = - FullPackageSpec{spec_map.emplace("a", "", {{"a1", "b[b1]"}, {"a2", "b[b2]"}, {"a3", "a[a2]"}}), {"a3"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}})}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(2), install_plan.size()); - features_check(&install_plan[0], "b", {"core", "b2"}); - features_check(&install_plan[1], "a", {"core", "a3", "a2"}); - } - - TEST_METHOD(basic_feature_test_6) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("b")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[core]"), {"core"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a, spec_b}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(3), install_plan.size()); - remove_plan_check(&install_plan[0], "b"); - features_check(&install_plan[1], "b", {"core", "b1"}); - features_check(&install_plan[2], "a", {"core"}); - } - - TEST_METHOD(basic_feature_test_7) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("x", "b")); - status_paragraphs.push_back(make_status_pgh("b")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = FullPackageSpec{spec_map.emplace("a")}; - auto spec_x = FullPackageSpec{spec_map.emplace("x", "a"), {"core"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_b}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(5), install_plan.size()); - remove_plan_check(&install_plan[0], "x"); - remove_plan_check(&install_plan[1], "b"); - - // TODO: order here may change but A < X, and B anywhere - features_check(&install_plan[2], "b", {"core", "b1"}); - features_check(&install_plan[3], "a", {"core"}); - features_check(&install_plan[4], "x", {"core"}); - } - - TEST_METHOD(basic_feature_test_8) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.back()->package.spec = - PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); - - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; - auto spec_b_64 = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - spec_map.triplet = Triplet::X86_WINDOWS; - auto spec_a_86 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; - auto spec_b_86 = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c_86 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({spec_c_64, spec_a_86, spec_a_64, spec_c_86}), - StatusParagraphs(std::move(status_paragraphs))); - - /*Assert::AreEqual(size_t(8), install_plan.size()); - auto iterator_pos = [&](const PackageSpec& spec, size_t start) -> int { - auto it = std::find_if(install_plan.begin() + start, install_plan.end(), [&](auto& action) { - return action.spec == spec; - }); - Assert::IsTrue(it != install_plan.end()); - return (int)(it - install_plan.begin()); - }; - int a_64_1 = iterator_pos(spec_a_64.package_spec, 0), a_86_1 = iterator_pos(spec_a_86.package_spec, 0), - b_64 = iterator_pos(spec_b_64.package_spec, 0), b_86 = iterator_pos(spec_b_86.package_spec, 0), - c_64 = iterator_pos(spec_c_64.package_spec, 0), c_86 = iterator_pos(spec_c_86.package_spec, 0), - a_64_2 = iterator_pos(spec_a_64.package_spec, a_64_1 + 1), - a_86_2 = iterator_pos(spec_a_86.package_spec, a_86_1 + 1);*/ - - remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); - remove_plan_check(&install_plan[1], "a"); - features_check(&install_plan[2], "b", {"core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[3], "a", {"a1", "core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[4], "c", {"core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[5], "b", {"core"}); - features_check(&install_plan[6], "a", {"a1", "core"}); - features_check(&install_plan[7], "c", {"core"}); - } - }; -} \ No newline at end of file diff --git a/toolsrc/src/tests.arguments.cpp b/toolsrc/src/tests.arguments.cpp new file mode 100644 index 000000000..25bf0f085 --- /dev/null +++ b/toolsrc/src/tests.arguments.cpp @@ -0,0 +1,58 @@ +#include +#include + +#pragma comment(lib, "version") +#pragma comment(lib, "winhttp") + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +using namespace vcpkg; + +namespace UnitTest1 +{ + class ArgumentTests : public TestClass + { + TEST_METHOD(create_from_arg_sequence_options_lower) + { + std::vector t = {"--vcpkg-root", "C:\\vcpkg", "--debug", "--sendmetrics", "--printmetrics"}; + auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); + Assert::AreEqual("C:\\vcpkg", v.vcpkg_root_dir.get()->c_str()); + Assert::IsTrue(v.debug && *v.debug.get()); + Assert::IsTrue(v.sendmetrics && v.sendmetrics.get()); + Assert::IsTrue(v.printmetrics && *v.printmetrics.get()); + } + + TEST_METHOD(create_from_arg_sequence_options_upper) + { + std::vector t = {"--VCPKG-ROOT", "C:\\vcpkg", "--DEBUG", "--SENDMETRICS", "--PRINTMETRICS"}; + auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); + Assert::AreEqual("C:\\vcpkg", v.vcpkg_root_dir.get()->c_str()); + Assert::IsTrue(v.debug && *v.debug.get()); + Assert::IsTrue(v.sendmetrics && v.sendmetrics.get()); + Assert::IsTrue(v.printmetrics && *v.printmetrics.get()); + } + + TEST_METHOD(create_from_arg_sequence_valued_options) + { + std::vector t = {"--a=b", "command", "argument"}; + auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); + auto opts = v.check_and_get_optional_command_arguments({}, {"--a"}); + Assert::AreEqual("b", opts.settings["--a"].c_str()); + Assert::AreEqual(size_t{1}, v.command_arguments.size()); + Assert::AreEqual("argument", v.command_arguments[0].c_str()); + Assert::AreEqual("command", v.command.c_str()); + } + + TEST_METHOD(create_from_arg_sequence_valued_options2) + { + std::vector t = {"--a", "--b=c"}; + auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); + auto opts = v.check_and_get_optional_command_arguments({"--a", "--c"}, {"--b", "--d"}); + Assert::AreEqual("c", opts.settings["--b"].c_str()); + Assert::IsTrue(opts.settings.find("--d") == opts.settings.end()); + Assert::IsTrue(opts.switches.find("--a") != opts.switches.end()); + Assert::IsTrue(opts.settings.find("--c") == opts.settings.end()); + Assert::AreEqual(size_t{0}, v.command_arguments.size()); + } + }; +} \ No newline at end of file diff --git a/toolsrc/src/tests.dependencies.cpp b/toolsrc/src/tests.dependencies.cpp new file mode 100644 index 000000000..3f6e0dd10 --- /dev/null +++ b/toolsrc/src/tests.dependencies.cpp @@ -0,0 +1,110 @@ +#include +#include +#include + +#pragma comment(lib, "version") +#pragma comment(lib, "winhttp") + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +using namespace vcpkg; +using Parse::parse_comma_list; + +namespace UnitTest1 +{ + class DependencyTests : public TestClass + { + TEST_METHOD(parse_depends_one) + { + auto v = expand_qualified_dependencies(parse_comma_list("libA (windows)")); + Assert::AreEqual(size_t(1), v.size()); + Assert::AreEqual("libA", v[0].depend.name.c_str()); + Assert::AreEqual("windows", v[0].qualifier.c_str()); + } + + TEST_METHOD(filter_depends) + { + auto deps = expand_qualified_dependencies(parse_comma_list("libA (windows), libB, libC (uwp)")); + auto v = filter_dependencies(deps, Triplet::X64_WINDOWS); + Assert::AreEqual(size_t(2), v.size()); + Assert::AreEqual("libA", v[0].c_str()); + Assert::AreEqual("libB", v[1].c_str()); + + auto v2 = filter_dependencies(deps, Triplet::ARM_UWP); + Assert::AreEqual(size_t(2), v.size()); + Assert::AreEqual("libB", v2[0].c_str()); + Assert::AreEqual("libC", v2[1].c_str()); + } + }; + + class SupportsTests : public TestClass + { + TEST_METHOD(parse_supports_all) + { + auto v = Supports::parse({ + "x64", + "x86", + "arm", + "windows", + "uwp", + "v140", + "v141", + "crt-static", + "crt-dynamic", + }); + Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); + + Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::UWP, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::ARM, + Supports::Platform::WINDOWS, + Supports::Linkage::STATIC, + Supports::ToolsetVersion::V141)); + } + + TEST_METHOD(parse_supports_invalid) + { + auto v = Supports::parse({"arm64"}); + Assert::AreEqual(uintptr_t(0), uintptr_t(v.get())); + Assert::AreEqual(size_t(1), v.error().size()); + Assert::AreEqual("arm64", v.error()[0].c_str()); + } + + TEST_METHOD(parse_supports_case_sensitive) + { + auto v = Supports::parse({"Windows"}); + Assert::AreEqual(uintptr_t(0), uintptr_t(v.get())); + Assert::AreEqual(size_t(1), v.error().size()); + Assert::AreEqual("Windows", v.error()[0].c_str()); + } + + TEST_METHOD(parse_supports_some) + { + auto v = Supports::parse({ + "x64", + "x86", + "windows", + }); + Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); + + Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::WINDOWS, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsFalse(v.get()->is_supported(System::CPUArchitecture::ARM, + Supports::Platform::WINDOWS, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsFalse(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::UWP, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::WINDOWS, + Supports::Linkage::STATIC, + Supports::ToolsetVersion::V141)); + } + }; +} diff --git a/toolsrc/src/tests.installplan.cpp b/toolsrc/src/tests.installplan.cpp new file mode 100644 index 000000000..120009db5 --- /dev/null +++ b/toolsrc/src/tests.installplan.cpp @@ -0,0 +1,487 @@ +#include +#include + +#include + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +using namespace vcpkg; + +namespace Microsoft::VisualStudio::CppUnitTestFramework +{ + template<> + inline std::wstring ToString(const vcpkg::Dependencies::InstallPlanType& t) + { + switch (t) + { + case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; + case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; + case Dependencies::InstallPlanType::INSTALL: return L"INSTALL"; + case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; + default: return ToString((int)t); + } + } + + template<> + inline std::wstring ToString(const vcpkg::Dependencies::RequestType& t) + { + switch (t) + { + case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED"; + case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED"; + case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN"; + default: return ToString((int)t); + } + } +} + +namespace UnitTest1 +{ + class InstallPlanTests : public TestClass + { + static std::unique_ptr make_control_file( + const char* name, + const char* depends, + const std::vector>& features = {}) + { + using Pgh = std::unordered_map; + std::vector scf_pghs; + scf_pghs.push_back(Pgh{ + {"Source", name}, + {"Version", "0"}, + {"Build-Depends", depends}, + }); + for (auto&& feature : features) + { + scf_pghs.push_back(Pgh{ + {"Feature", feature.first}, + {"Description", "feature"}, + {"Build-Depends", feature.second}, + }); + } + auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(scf_pghs)); + Assert::IsTrue(m_pgh.has_value()); + return std::move(*m_pgh.get()); + } + + static void features_check(Dependencies::AnyAction* install_action, + std::string pkg_name, + std::vector vec, + const Triplet& triplet = Triplet::X86_WINDOWS) + { + const auto& plan = install_action->install_plan.value_or_exit(VCPKG_LINE_INFO); + const auto& feature_list = plan.feature_list; + + Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); + + Assert::AreEqual(pkg_name.c_str(), + (*plan.any_paragraph.source_control_file.get())->core_paragraph->name.c_str()); + Assert::AreEqual(size_t(vec.size()), feature_list.size()); + + for (auto&& feature_name : vec) + { + if (feature_name == "core" || feature_name == "") + { + Assert::IsTrue(Util::find(feature_list, "core") != feature_list.end() || + Util::find(feature_list, "") != feature_list.end()); + continue; + } + Assert::IsTrue(Util::find(feature_list, feature_name) != feature_list.end()); + } + } + + static void remove_plan_check(Dependencies::AnyAction* remove_action, + std::string pkg_name, + const Triplet& triplet = Triplet::X86_WINDOWS) + { + const auto& plan = remove_action->remove_plan.value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); + Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); + } + + static std::unique_ptr make_status_pgh(const char* name, const char* depends = "") + { + using Pgh = std::unordered_map; + return std::make_unique(Pgh{{"Package", name}, + {"Version", "1"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Status", "install ok installed"}}); + } + static std::unique_ptr make_status_feature_pgh(const char* name, + const char* feature, + const char* depends = "") + { + using Pgh = std::unordered_map; + return std::make_unique(Pgh{{"Package", name}, + {"Version", "1"}, + {"Feature", feature}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Status", "install ok installed"}}); + } + struct PackageSpecMap + { + std::unordered_map map; + Triplet triplet; + PackageSpecMap(const Triplet& t) { triplet = t; } + + PackageSpec emplace(const char* name, + const char* depends = "", + const std::vector>& features = {}) + { + return emplace(std::move(*make_control_file(name, depends, features))); + } + PackageSpec emplace(vcpkg::SourceControlFile&& scf) + { + auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph->name, triplet); + Assert::IsTrue(spec.has_value()); + map.emplace(scf.core_paragraph->name, std::move(scf)); + return PackageSpec{*spec.get()}; + } + }; + + TEST_METHOD(basic_install_scheme) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "b"); + auto spec_b = spec_map.emplace("b", "c"); + auto spec_c = spec_map.emplace("c"); + + Dependencies::MapPortFile map_port(spec_map.map); + auto install_plan = + Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(3), install_plan.size()); + Assert::AreEqual("c", install_plan[0].spec.name().c_str()); + Assert::AreEqual("b", install_plan[1].spec.name().c_str()); + Assert::AreEqual("a", install_plan[2].spec.name().c_str()); + } + + TEST_METHOD(multiple_install_scheme) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "d"); + auto spec_b = spec_map.emplace("b", "d, e"); + auto spec_c = spec_map.emplace("c", "e, h"); + auto spec_d = spec_map.emplace("d", "f, g, h"); + auto spec_e = spec_map.emplace("e", "g"); + auto spec_f = spec_map.emplace("f"); + auto spec_g = spec_map.emplace("g"); + auto spec_h = spec_map.emplace("h"); + + Dependencies::MapPortFile map_port(spec_map.map); + auto install_plan = Dependencies::create_install_plan( + map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); + + auto iterator_pos = [&](const PackageSpec& spec) -> int { + auto it = std::find_if( + install_plan.begin(), install_plan.end(), [&](auto& action) { return action.spec == spec; }); + Assert::IsTrue(it != install_plan.end()); + return (int)(it - install_plan.begin()); + }; + + int a_pos = iterator_pos(spec_a), b_pos = iterator_pos(spec_b), c_pos = iterator_pos(spec_c), + d_pos = iterator_pos(spec_d), e_pos = iterator_pos(spec_e), f_pos = iterator_pos(spec_f), + g_pos = iterator_pos(spec_g), h_pos = iterator_pos(spec_h); + + Assert::IsTrue(a_pos > d_pos); + Assert::IsTrue(b_pos > e_pos); + Assert::IsTrue(b_pos > d_pos); + Assert::IsTrue(c_pos > e_pos); + Assert::IsTrue(c_pos > h_pos); + Assert::IsTrue(d_pos > f_pos); + Assert::IsTrue(d_pos > g_pos); + Assert::IsTrue(d_pos > h_pos); + Assert::IsTrue(e_pos > g_pos); + } + + TEST_METHOD(existing_package_scheme) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.emplace("a")}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(1), install_plan.size()); + auto p = install_plan[0].install_plan.get(); + Assert::IsNotNull(p); + Assert::AreEqual("a", p->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type); + Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p->request_type); + } + + TEST_METHOD(user_requested_package_scheme) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b")}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(2), install_plan.size()); + auto p = install_plan[0].install_plan.get(); + Assert::IsNotNull(p); + Assert::AreEqual("b", p->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type); + Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type); + + auto p2 = install_plan[1].install_plan.get(); + Assert::IsNotNull(p2); + Assert::AreEqual("a", p2->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type); + Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p2->request_type); + } + + TEST_METHOD(long_install_scheme) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("j", "k")); + status_paragraphs.push_back(make_status_pgh("k")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = spec_map.emplace("a", "b, c, d, e, f, g, h, j, k"); + auto spec_b = spec_map.emplace("b", "c, d, e, f, g, h, j, k"); + auto spec_c = spec_map.emplace("c", "d, e, f, g, h, j, k"); + auto spec_d = spec_map.emplace("d", "e, f, g, h, j, k"); + auto spec_e = spec_map.emplace("e", "f, g, h, j, k"); + auto spec_f = spec_map.emplace("f", "g, h, j, k"); + auto spec_g = spec_map.emplace("g", "h, j, k"); + auto spec_h = spec_map.emplace("h", "j, k"); + auto spec_j = spec_map.emplace("j", "k"); + auto spec_k = spec_map.emplace("k"); + + Dependencies::MapPortFile map_port(spec_map.map); + auto install_plan = + Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(8), install_plan.size()); + Assert::AreEqual("h", install_plan[0].spec.name().c_str()); + Assert::AreEqual("g", install_plan[1].spec.name().c_str()); + Assert::AreEqual("f", install_plan[2].spec.name().c_str()); + Assert::AreEqual("e", install_plan[3].spec.name().c_str()); + Assert::AreEqual("d", install_plan[4].spec.name().c_str()); + Assert::AreEqual("c", install_plan[5].spec.name().c_str()); + Assert::AreEqual("b", install_plan[6].spec.name().c_str()); + Assert::AreEqual("a", install_plan[7].spec.name().c_str()); + } + + TEST_METHOD(basic_feature_test_1) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a", "b, b[b1]")); + status_paragraphs.push_back(make_status_pgh("b")); + status_paragraphs.push_back(make_status_feature_pgh("b", "b1")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(4), install_plan.size()); + remove_plan_check(&install_plan[0], "a"); + remove_plan_check(&install_plan[1], "b"); + features_check(&install_plan[2], "b", {"b1", "core", "b1"}); + features_check(&install_plan[3], "a", {"a1", "core"}); + } + + TEST_METHOD(basic_feature_test_2) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(2), install_plan.size()); + features_check(&install_plan[0], "b", {"b1", "b2", "core"}); + features_check(&install_plan[1], "a", {"a1", "core"}); + } + + TEST_METHOD(basic_feature_test_3) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_c, spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(4), install_plan.size()); + remove_plan_check(&install_plan[0], "a"); + features_check(&install_plan[1], "b", {"core"}); + features_check(&install_plan[2], "a", {"a1", "core"}); + features_check(&install_plan[3], "c", {"core"}); + } + + TEST_METHOD(basic_feature_test_4) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.push_back(make_status_feature_pgh("a", "a1", "")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}})}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_c}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(1), install_plan.size()); + features_check(&install_plan[0], "c", {"core"}); + } + + TEST_METHOD(basic_feature_test_5) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = + FullPackageSpec{spec_map.emplace("a", "", {{"a1", "b[b1]"}, {"a2", "b[b2]"}, {"a3", "a[a2]"}}), {"a3"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}})}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(2), install_plan.size()); + features_check(&install_plan[0], "b", {"core", "b2"}); + features_check(&install_plan[1], "a", {"core", "a3", "a2"}); + } + + TEST_METHOD(basic_feature_test_6) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("b")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[core]"), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a, spec_b}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(3), install_plan.size()); + remove_plan_check(&install_plan[0], "b"); + features_check(&install_plan[1], "b", {"core", "b1"}); + features_check(&install_plan[2], "a", {"core"}); + } + + TEST_METHOD(basic_feature_test_7) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("x", "b")); + status_paragraphs.push_back(make_status_pgh("b")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = FullPackageSpec{spec_map.emplace("a")}; + auto spec_x = FullPackageSpec{spec_map.emplace("x", "a"), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_b}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(5), install_plan.size()); + remove_plan_check(&install_plan[0], "x"); + remove_plan_check(&install_plan[1], "b"); + + // TODO: order here may change but A < X, and B anywhere + features_check(&install_plan[2], "b", {"core", "b1"}); + features_check(&install_plan[3], "a", {"core"}); + features_check(&install_plan[4], "x", {"core"}); + } + + TEST_METHOD(basic_feature_test_8) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.spec = + PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + spec_map.triplet = Triplet::X86_WINDOWS; + auto spec_a_86 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b_86 = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c_86 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({spec_c_64, spec_a_86, spec_a_64, spec_c_86}), + StatusParagraphs(std::move(status_paragraphs))); + + /*Assert::AreEqual(size_t(8), install_plan.size()); + auto iterator_pos = [&](const PackageSpec& spec, size_t start) -> int { + auto it = std::find_if(install_plan.begin() + start, install_plan.end(), [&](auto& action) { + return action.spec == spec; + }); + Assert::IsTrue(it != install_plan.end()); + return (int)(it - install_plan.begin()); + }; + int a_64_1 = iterator_pos(spec_a_64.package_spec, 0), a_86_1 = iterator_pos(spec_a_86.package_spec, 0), + b_64 = iterator_pos(spec_b_64.package_spec, 0), b_86 = iterator_pos(spec_b_86.package_spec, 0), + c_64 = iterator_pos(spec_c_64.package_spec, 0), c_86 = iterator_pos(spec_c_86.package_spec, 0), + a_64_2 = iterator_pos(spec_a_64.package_spec, a_64_1 + 1), + a_86_2 = iterator_pos(spec_a_86.package_spec, a_86_1 + 1);*/ + + remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); + remove_plan_check(&install_plan[1], "a"); + features_check(&install_plan[2], "b", {"core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[3], "a", {"a1", "core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[4], "c", {"core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[5], "b", {"core"}); + features_check(&install_plan[6], "a", {"a1", "core"}); + features_check(&install_plan[7], "c", {"core"}); + } + }; +} \ No newline at end of file diff --git a/toolsrc/src/tests.packagespec.cpp b/toolsrc/src/tests.packagespec.cpp new file mode 100644 index 000000000..cb5c41af0 --- /dev/null +++ b/toolsrc/src/tests.packagespec.cpp @@ -0,0 +1,120 @@ +#include +#include +#include + +#include + +#pragma comment(lib, "version") +#pragma comment(lib, "winhttp") + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace Microsoft::VisualStudio::CppUnitTestFramework +{ + template<> + inline std::wstring ToString(const vcpkg::PackageSpecParseResult& t) + { + return ToString(static_cast(t)); + } + + template<> + inline std::wstring ToString(const vcpkg::PackageSpec& t) + { + return ToString(t.to_string()); + } +} + +namespace Strings = vcpkg::Strings; + +namespace UnitTest1 +{ + using namespace vcpkg; + + class SpecifierConversion : public TestClass + { + TEST_METHOD(full_package_spec_to_feature_specs) + { + auto a_spec = PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + auto b_spec = PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + auto fspecs = FullPackageSpec::to_feature_specs({{a_spec, {"0", "1"}}, {b_spec, {"2", "3"}}}); + + Assert::AreEqual(size_t(6), fspecs.size()); + + std::array features = {"", "0", "1", "", "2", "3"}; + std::array specs = {&a_spec, &a_spec, &a_spec, &b_spec, &b_spec, &b_spec}; + + for (size_t i = 0; i < features.size(); ++i) + { + Assert::AreEqual(features[i], fspecs[i].feature().c_str()); + Assert::AreEqual(*specs[i], fspecs[i].spec()); + } + } + }; + + class SpecifierParsing : public TestClass + { + TEST_METHOD(parsed_specifier_from_string) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::AreEqual(size_t(0), spec->features.size()); + Assert::AreEqual("", spec->triplet.c_str()); + } + + TEST_METHOD(parsed_specifier_from_string_with_triplet) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::AreEqual("x64-uwp", spec->triplet.c_str()); + } + + TEST_METHOD(parsed_specifier_from_string_with_colons) + { + auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error(); + Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); + } + + TEST_METHOD(parsed_specifier_from_string_with_feature) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::IsTrue(spec->features.size() == 1); + Assert::AreEqual("feature", spec->features.front().c_str()); + Assert::AreEqual("x64-uwp", spec->triplet.c_str()); + } + + TEST_METHOD(parsed_specifier_from_string_with_many_features) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::IsTrue(spec->features.size() == 3); + Assert::AreEqual("0", spec->features[0].c_str()); + Assert::AreEqual("1", spec->features[1].c_str()); + Assert::AreEqual("2", spec->features[2].c_str()); + Assert::AreEqual("", spec->triplet.c_str()); + } + + TEST_METHOD(utf8_to_utf16) + { + auto str = vcpkg::Strings::to_utf16("abc"); + Assert::AreEqual(L"abc", str.c_str()); + } + + TEST_METHOD(utf8_to_utf16_with_whitespace) + { + auto str = vcpkg::Strings::to_utf16("abc -x86-windows"); + Assert::AreEqual(L"abc -x86-windows", str.c_str()); + } + }; + + TEST_CLASS(Metrics){}; +} diff --git a/toolsrc/src/tests.paragraph.cpp b/toolsrc/src/tests.paragraph.cpp new file mode 100644 index 000000000..d9301abd0 --- /dev/null +++ b/toolsrc/src/tests.paragraph.cpp @@ -0,0 +1,389 @@ +#include +#include +#include + +#include + +#pragma comment(lib, "version") +#pragma comment(lib, "winhttp") + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace Microsoft::VisualStudio::CppUnitTestFramework +{ + template<> + inline std::wstring ToString(const vcpkg::PackageSpecParseResult& t) + { + return ToString(static_cast(t)); + } +} + +namespace Strings = vcpkg::Strings; + +namespace UnitTest1 +{ + class ControlParsing : public TestClass + { + TEST_METHOD(SourceParagraph_Construct_Minimum) + { + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "zlib"}, + {"Version", "1.2.8"}, + }}); + + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); + + Assert::AreEqual("zlib", pgh->core_paragraph->name.c_str()); + Assert::AreEqual("1.2.8", pgh->core_paragraph->version.c_str()); + Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str()); + Assert::AreEqual("", pgh->core_paragraph->description.c_str()); + Assert::AreEqual(size_t(0), pgh->core_paragraph->depends.size()); + } + + TEST_METHOD(SourceParagraph_Construct_Maximum) + { + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "s"}, + {"Version", "v"}, + {"Maintainer", "m"}, + {"Description", "d"}, + {"Build-Depends", "bd"}, + {"Supports", "x64"}, + }}); + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); + + Assert::AreEqual("s", pgh->core_paragraph->name.c_str()); + Assert::AreEqual("v", pgh->core_paragraph->version.c_str()); + Assert::AreEqual("m", pgh->core_paragraph->maintainer.c_str()); + Assert::AreEqual("d", pgh->core_paragraph->description.c_str()); + Assert::AreEqual(size_t(1), pgh->core_paragraph->depends.size()); + Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name().c_str()); + Assert::AreEqual(size_t(1), pgh->core_paragraph->supports.size()); + Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str()); + } + + TEST_METHOD(SourceParagraph_Two_Depends) + { + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Build-Depends", "z, openssl"}, + }}); + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); + + Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); + Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str()); + Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str()); + } + + TEST_METHOD(SourceParagraph_Three_Depends) + { + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Build-Depends", "z, openssl, xyz"}, + }}); + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); + + Assert::AreEqual(size_t(3), pgh->core_paragraph->depends.size()); + Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str()); + Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str()); + Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name().c_str()); + } + + TEST_METHOD(SourceParagraph_Three_Supports) + { + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Supports", "x64, windows, uwp"}, + }}); + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); + + Assert::AreEqual(size_t(3), pgh->core_paragraph->supports.size()); + Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str()); + Assert::AreEqual("windows", pgh->core_paragraph->supports[1].c_str()); + Assert::AreEqual("uwp", pgh->core_paragraph->supports[2].c_str()); + } + + TEST_METHOD(SourceParagraph_Construct_Qualified_Depends) + { + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Build-Depends", "libA (windows), libB (uwp)"}, + }}); + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); + + Assert::AreEqual("zlib", pgh->core_paragraph->name.c_str()); + Assert::AreEqual("1.2.8", pgh->core_paragraph->version.c_str()); + Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str()); + Assert::AreEqual("", pgh->core_paragraph->description.c_str()); + Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); + Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name().c_str()); + Assert::AreEqual("windows", pgh->core_paragraph->depends[0].qualifier.c_str()); + Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name().c_str()); + Assert::AreEqual("uwp", pgh->core_paragraph->depends[1].qualifier.c_str()); + } + + TEST_METHOD(BinaryParagraph_Construct_Minimum) + { + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + }); + + Assert::AreEqual("zlib", pgh.spec.name().c_str()); + Assert::AreEqual("1.2.8", pgh.version.c_str()); + Assert::AreEqual("", pgh.maintainer.c_str()); + Assert::AreEqual("", pgh.description.c_str()); + Assert::AreEqual("x86-windows", pgh.spec.triplet().canonical_name().c_str()); + Assert::AreEqual(size_t(0), pgh.depends.size()); + } + + TEST_METHOD(BinaryParagraph_Construct_Maximum) + { + vcpkg::BinaryParagraph pgh({ + {"Package", "s"}, + {"Version", "v"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Maintainer", "m"}, + {"Description", "d"}, + {"Depends", "bd"}, + }); + Assert::AreEqual("s", pgh.spec.name().c_str()); + Assert::AreEqual("v", pgh.version.c_str()); + Assert::AreEqual("m", pgh.maintainer.c_str()); + Assert::AreEqual("d", pgh.description.c_str()); + Assert::AreEqual(size_t(1), pgh.depends.size()); + Assert::AreEqual("bd", pgh.depends[0].c_str()); + } + + TEST_METHOD(BinaryParagraph_Three_Depends) + { + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", "a, b, c"}, + }); + + Assert::AreEqual(size_t(3), pgh.depends.size()); + Assert::AreEqual("a", pgh.depends[0].c_str()); + Assert::AreEqual("b", pgh.depends[1].c_str()); + Assert::AreEqual("c", pgh.depends[2].c_str()); + } + + TEST_METHOD(parse_paragraphs_empty) + { + const char* str = ""; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::IsTrue(pghs.empty()); + } + + TEST_METHOD(parse_paragraphs_one_field) + { + const char* str = "f1: v1"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(1), pghs.size()); + Assert::AreEqual(size_t(1), pghs[0].size()); + Assert::AreEqual("v1", pghs[0]["f1"].c_str()); + } + + TEST_METHOD(parse_paragraphs_one_pgh) + { + const char* str = "f1: v1\n" + "f2: v2"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(1), pghs.size()); + Assert::AreEqual(size_t(2), pghs[0].size()); + Assert::AreEqual("v1", pghs[0]["f1"].c_str()); + Assert::AreEqual("v2", pghs[0]["f2"].c_str()); + } + + TEST_METHOD(parse_paragraphs_two_pgh) + { + const char* str = "f1: v1\n" + "f2: v2\n" + "\n" + "f3: v3\n" + "f4: v4"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(2), pghs.size()); + Assert::AreEqual(size_t(2), pghs[0].size()); + Assert::AreEqual("v1", pghs[0]["f1"].c_str()); + Assert::AreEqual("v2", pghs[0]["f2"].c_str()); + Assert::AreEqual(size_t(2), pghs[1].size()); + Assert::AreEqual("v3", pghs[1]["f3"].c_str()); + Assert::AreEqual("v4", pghs[1]["f4"].c_str()); + } + + TEST_METHOD(parse_paragraphs_field_names) + { + const char* str = "1:\n" + "f:\n" + "F:\n" + "0:\n" + "F-2:\n"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(1), pghs.size()); + Assert::AreEqual(size_t(5), pghs[0].size()); + } + + TEST_METHOD(parse_paragraphs_multiple_blank_lines) + { + const char* str = "f1: v1\n" + "f2: v2\n" + "\n" + "\n" + "f3: v3\n" + "f4: v4"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(2), pghs.size()); + } + + TEST_METHOD(parse_paragraphs_empty_fields) + { + const char* str = "f1:\n" + "f2: "; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(1), pghs.size()); + Assert::AreEqual(size_t(2), pghs[0].size()); + Assert::AreEqual("", pghs[0]["f1"].c_str()); + Assert::AreEqual("", pghs[0]["f2"].c_str()); + Assert::AreEqual(size_t(2), pghs[0].size()); + } + + TEST_METHOD(parse_paragraphs_multiline_fields) + { + const char* str = "f1: simple\n" + " f1\r\n" + "f2:\r\n" + " f2\r\n" + " continue\r\n"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(1), pghs.size()); + Assert::AreEqual("simple\n f1", pghs[0]["f1"].c_str()); + Assert::AreEqual("\n f2\n continue", pghs[0]["f2"].c_str()); + } + + TEST_METHOD(parse_paragraphs_crlfs) + { + const char* str = "f1: v1\r\n" + "f2: v2\r\n" + "\r\n" + "f3: v3\r\n" + "f4: v4"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(2), pghs.size()); + Assert::AreEqual(size_t(2), pghs[0].size()); + Assert::AreEqual("v1", pghs[0]["f1"].c_str()); + Assert::AreEqual("v2", pghs[0]["f2"].c_str()); + Assert::AreEqual(size_t(2), pghs[1].size()); + Assert::AreEqual("v3", pghs[1]["f3"].c_str()); + Assert::AreEqual("v4", pghs[1]["f4"].c_str()); + } + + TEST_METHOD(parse_paragraphs_comment) + { + const char* str = "f1: v1\r\n" + "#comment\r\n" + "f2: v2\r\n" + "#comment\r\n" + "\r\n" + "#comment\r\n" + "f3: v3\r\n" + "#comment\r\n" + "f4: v4"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(2), pghs.size()); + Assert::AreEqual(size_t(2), pghs[0].size()); + Assert::AreEqual("v1", pghs[0]["f1"].c_str()); + Assert::AreEqual("v2", pghs[0]["f2"].c_str()); + Assert::AreEqual(size_t(2), pghs[1].size()); + Assert::AreEqual("v3", pghs[1]["f3"].c_str()); + Assert::AreEqual("v4", pghs[1]["f4"].c_str()); + } + + TEST_METHOD(parse_comment_before_single_slashN) + { + const char* str = "f1: v1\r\n" + "#comment\n"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(1), pghs[0].size()); + Assert::AreEqual("v1", pghs[0]["f1"].c_str()); + } + + TEST_METHOD(BinaryParagraph_serialize_min) + { + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + }); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(1), pghs.size()); + Assert::AreEqual(size_t(4), pghs[0].size()); + Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); + Assert::AreEqual("1.2.8", pghs[0]["Version"].c_str()); + Assert::AreEqual("x86-windows", pghs[0]["Architecture"].c_str()); + Assert::AreEqual("same", pghs[0]["Multi-Arch"].c_str()); + } + + TEST_METHOD(BinaryParagraph_serialize_max) + { + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Description", "first line\n second line"}, + {"Maintainer", "abc "}, + {"Depends", "dep"}, + {"Multi-Arch", "same"}, + }); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(1), pghs.size()); + Assert::AreEqual(size_t(7), pghs[0].size()); + Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); + Assert::AreEqual("1.2.8", pghs[0]["Version"].c_str()); + Assert::AreEqual("x86-windows", pghs[0]["Architecture"].c_str()); + Assert::AreEqual("same", pghs[0]["Multi-Arch"].c_str()); + Assert::AreEqual("first line\n second line", pghs[0]["Description"].c_str()); + Assert::AreEqual("dep", pghs[0]["Depends"].c_str()); + } + + TEST_METHOD(BinaryParagraph_serialize_multiple_deps) + { + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", "a, b, c"}, + }); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(1), pghs.size()); + Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str()); + } + }; +} diff --git a/toolsrc/src/tests_arguments.cpp b/toolsrc/src/tests_arguments.cpp deleted file mode 100644 index 14b3c3d4f..000000000 --- a/toolsrc/src/tests_arguments.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "CppUnitTest.h" -#include "VcpkgCmdArguments.h" - -#pragma comment(lib, "version") -#pragma comment(lib, "winhttp") - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -using namespace vcpkg; - -namespace UnitTest1 -{ - class ArgumentTests : public TestClass - { - TEST_METHOD(create_from_arg_sequence_options_lower) - { - std::vector t = {"--vcpkg-root", "C:\\vcpkg", "--debug", "--sendmetrics", "--printmetrics"}; - auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); - Assert::AreEqual("C:\\vcpkg", v.vcpkg_root_dir.get()->c_str()); - Assert::IsTrue(v.debug && *v.debug.get()); - Assert::IsTrue(v.sendmetrics && v.sendmetrics.get()); - Assert::IsTrue(v.printmetrics && *v.printmetrics.get()); - } - - TEST_METHOD(create_from_arg_sequence_options_upper) - { - std::vector t = {"--VCPKG-ROOT", "C:\\vcpkg", "--DEBUG", "--SENDMETRICS", "--PRINTMETRICS"}; - auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); - Assert::AreEqual("C:\\vcpkg", v.vcpkg_root_dir.get()->c_str()); - Assert::IsTrue(v.debug && *v.debug.get()); - Assert::IsTrue(v.sendmetrics && v.sendmetrics.get()); - Assert::IsTrue(v.printmetrics && *v.printmetrics.get()); - } - - TEST_METHOD(create_from_arg_sequence_valued_options) - { - std::vector t = {"--a=b", "command", "argument"}; - auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); - auto opts = v.check_and_get_optional_command_arguments({}, {"--a"}); - Assert::AreEqual("b", opts.settings["--a"].c_str()); - Assert::AreEqual(size_t{1}, v.command_arguments.size()); - Assert::AreEqual("argument", v.command_arguments[0].c_str()); - Assert::AreEqual("command", v.command.c_str()); - } - - TEST_METHOD(create_from_arg_sequence_valued_options2) - { - std::vector t = {"--a", "--b=c"}; - auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); - auto opts = v.check_and_get_optional_command_arguments({"--a", "--c"}, {"--b", "--d"}); - Assert::AreEqual("c", opts.settings["--b"].c_str()); - Assert::IsTrue(opts.settings.find("--d") == opts.settings.end()); - Assert::IsTrue(opts.switches.find("--a") != opts.switches.end()); - Assert::IsTrue(opts.settings.find("--c") == opts.settings.end()); - Assert::AreEqual(size_t{0}, v.command_arguments.size()); - } - }; -} \ No newline at end of file diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp deleted file mode 100644 index 6a6981d73..000000000 --- a/toolsrc/src/tests_dependencies.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "CppUnitTest.h" -#include "SourceParagraph.h" -#include "Triplet.h" - -#pragma comment(lib, "version") -#pragma comment(lib, "winhttp") - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -using namespace vcpkg; -using Parse::parse_comma_list; - -namespace UnitTest1 -{ - class DependencyTests : public TestClass - { - TEST_METHOD(parse_depends_one) - { - auto v = expand_qualified_dependencies(parse_comma_list("libA (windows)")); - Assert::AreEqual(size_t(1), v.size()); - Assert::AreEqual("libA", v[0].depend.name.c_str()); - Assert::AreEqual("windows", v[0].qualifier.c_str()); - } - - TEST_METHOD(filter_depends) - { - auto deps = expand_qualified_dependencies(parse_comma_list("libA (windows), libB, libC (uwp)")); - auto v = filter_dependencies(deps, Triplet::X64_WINDOWS); - Assert::AreEqual(size_t(2), v.size()); - Assert::AreEqual("libA", v[0].c_str()); - Assert::AreEqual("libB", v[1].c_str()); - - auto v2 = filter_dependencies(deps, Triplet::ARM_UWP); - Assert::AreEqual(size_t(2), v.size()); - Assert::AreEqual("libB", v2[0].c_str()); - Assert::AreEqual("libC", v2[1].c_str()); - } - }; - - class SupportsTests : public TestClass - { - TEST_METHOD(parse_supports_all) - { - auto v = Supports::parse({ - "x64", - "x86", - "arm", - "windows", - "uwp", - "v140", - "v141", - "crt-static", - "crt-dynamic", - }); - Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); - - Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, - Supports::Platform::UWP, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::ARM, - Supports::Platform::WINDOWS, - Supports::Linkage::STATIC, - Supports::ToolsetVersion::V141)); - } - - TEST_METHOD(parse_supports_invalid) - { - auto v = Supports::parse({"arm64"}); - Assert::AreEqual(uintptr_t(0), uintptr_t(v.get())); - Assert::AreEqual(size_t(1), v.error().size()); - Assert::AreEqual("arm64", v.error()[0].c_str()); - } - - TEST_METHOD(parse_supports_case_sensitive) - { - auto v = Supports::parse({"Windows"}); - Assert::AreEqual(uintptr_t(0), uintptr_t(v.get())); - Assert::AreEqual(size_t(1), v.error().size()); - Assert::AreEqual("Windows", v.error()[0].c_str()); - } - - TEST_METHOD(parse_supports_some) - { - auto v = Supports::parse({ - "x64", - "x86", - "windows", - }); - Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); - - Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, - Supports::Platform::WINDOWS, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsFalse(v.get()->is_supported(System::CPUArchitecture::ARM, - Supports::Platform::WINDOWS, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsFalse(v.get()->is_supported(System::CPUArchitecture::X64, - Supports::Platform::UWP, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, - Supports::Platform::WINDOWS, - Supports::Linkage::STATIC, - Supports::ToolsetVersion::V141)); - } - }; -} diff --git a/toolsrc/src/tests_package_spec.cpp b/toolsrc/src/tests_package_spec.cpp deleted file mode 100644 index a6b9d5b13..000000000 --- a/toolsrc/src/tests_package_spec.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "BinaryParagraph.h" -#include "CppUnitTest.h" -#include "Paragraphs.h" -#include "vcpkg_Strings.h" - -#pragma comment(lib, "version") -#pragma comment(lib, "winhttp") - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -namespace Microsoft::VisualStudio::CppUnitTestFramework -{ - template<> - inline std::wstring ToString(const vcpkg::PackageSpecParseResult& t) - { - return ToString(static_cast(t)); - } - - template<> - inline std::wstring ToString(const vcpkg::PackageSpec& t) - { - return ToString(t.to_string()); - } -} - -namespace Strings = vcpkg::Strings; - -namespace UnitTest1 -{ - using namespace vcpkg; - - class SpecifierConversion : public TestClass - { - TEST_METHOD(full_package_spec_to_feature_specs) - { - auto a_spec = PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); - auto b_spec = PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); - - auto fspecs = FullPackageSpec::to_feature_specs({{a_spec, {"0", "1"}}, {b_spec, {"2", "3"}}}); - - Assert::AreEqual(size_t(6), fspecs.size()); - - std::array features = {"", "0", "1", "", "2", "3"}; - std::array specs = {&a_spec, &a_spec, &a_spec, &b_spec, &b_spec, &b_spec}; - - for (size_t i = 0; i < features.size(); ++i) - { - Assert::AreEqual(features[i], fspecs[i].feature().c_str()); - Assert::AreEqual(*specs[i], fspecs[i].spec()); - } - } - }; - - class SpecifierParsing : public TestClass - { - TEST_METHOD(parsed_specifier_from_string) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::AreEqual(size_t(0), spec->features.size()); - Assert::AreEqual("", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_triplet) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::AreEqual("x64-uwp", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_colons) - { - auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error(); - Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); - } - - TEST_METHOD(parsed_specifier_from_string_with_feature) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::IsTrue(spec->features.size() == 1); - Assert::AreEqual("feature", spec->features.front().c_str()); - Assert::AreEqual("x64-uwp", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_many_features) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::IsTrue(spec->features.size() == 3); - Assert::AreEqual("0", spec->features[0].c_str()); - Assert::AreEqual("1", spec->features[1].c_str()); - Assert::AreEqual("2", spec->features[2].c_str()); - Assert::AreEqual("", spec->triplet.c_str()); - } - - TEST_METHOD(utf8_to_utf16) - { - auto str = vcpkg::Strings::to_utf16("abc"); - Assert::AreEqual(L"abc", str.c_str()); - } - - TEST_METHOD(utf8_to_utf16_with_whitespace) - { - auto str = vcpkg::Strings::to_utf16("abc -x86-windows"); - Assert::AreEqual(L"abc -x86-windows", str.c_str()); - } - }; - - TEST_CLASS(Metrics){}; -} diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp deleted file mode 100644 index 47a07e12d..000000000 --- a/toolsrc/src/tests_paragraph.cpp +++ /dev/null @@ -1,388 +0,0 @@ -#include "BinaryParagraph.h" -#include "CppUnitTest.h" -#include "Paragraphs.h" -#include "vcpkg_Strings.h" - -#pragma comment(lib, "version") -#pragma comment(lib, "winhttp") - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -namespace Microsoft::VisualStudio::CppUnitTestFramework -{ - template<> - inline std::wstring ToString(const vcpkg::PackageSpecParseResult& t) - { - return ToString(static_cast(t)); - } -} - -namespace Strings = vcpkg::Strings; - -namespace UnitTest1 -{ - class ControlParsing : public TestClass - { - TEST_METHOD(SourceParagraph_Construct_Minimum) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "zlib"}, - {"Version", "1.2.8"}, - }}); - - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual("zlib", pgh->core_paragraph->name.c_str()); - Assert::AreEqual("1.2.8", pgh->core_paragraph->version.c_str()); - Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str()); - Assert::AreEqual("", pgh->core_paragraph->description.c_str()); - Assert::AreEqual(size_t(0), pgh->core_paragraph->depends.size()); - } - - TEST_METHOD(SourceParagraph_Construct_Maximum) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "s"}, - {"Version", "v"}, - {"Maintainer", "m"}, - {"Description", "d"}, - {"Build-Depends", "bd"}, - {"Supports", "x64"}, - }}); - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual("s", pgh->core_paragraph->name.c_str()); - Assert::AreEqual("v", pgh->core_paragraph->version.c_str()); - Assert::AreEqual("m", pgh->core_paragraph->maintainer.c_str()); - Assert::AreEqual("d", pgh->core_paragraph->description.c_str()); - Assert::AreEqual(size_t(1), pgh->core_paragraph->depends.size()); - Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name().c_str()); - Assert::AreEqual(size_t(1), pgh->core_paragraph->supports.size()); - Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str()); - } - - TEST_METHOD(SourceParagraph_Two_Depends) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "zlib"}, - {"Version", "1.2.8"}, - {"Build-Depends", "z, openssl"}, - }}); - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); - Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str()); - Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str()); - } - - TEST_METHOD(SourceParagraph_Three_Depends) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "zlib"}, - {"Version", "1.2.8"}, - {"Build-Depends", "z, openssl, xyz"}, - }}); - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual(size_t(3), pgh->core_paragraph->depends.size()); - Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str()); - Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str()); - Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name().c_str()); - } - - TEST_METHOD(SourceParagraph_Three_Supports) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "zlib"}, - {"Version", "1.2.8"}, - {"Supports", "x64, windows, uwp"}, - }}); - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual(size_t(3), pgh->core_paragraph->supports.size()); - Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str()); - Assert::AreEqual("windows", pgh->core_paragraph->supports[1].c_str()); - Assert::AreEqual("uwp", pgh->core_paragraph->supports[2].c_str()); - } - - TEST_METHOD(SourceParagraph_Construct_Qualified_Depends) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector>{{ - {"Source", "zlib"}, - {"Version", "1.2.8"}, - {"Build-Depends", "libA (windows), libB (uwp)"}, - }}); - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual("zlib", pgh->core_paragraph->name.c_str()); - Assert::AreEqual("1.2.8", pgh->core_paragraph->version.c_str()); - Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str()); - Assert::AreEqual("", pgh->core_paragraph->description.c_str()); - Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); - Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name().c_str()); - Assert::AreEqual("windows", pgh->core_paragraph->depends[0].qualifier.c_str()); - Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name().c_str()); - Assert::AreEqual("uwp", pgh->core_paragraph->depends[1].qualifier.c_str()); - } - - TEST_METHOD(BinaryParagraph_Construct_Minimum) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - }); - - Assert::AreEqual("zlib", pgh.spec.name().c_str()); - Assert::AreEqual("1.2.8", pgh.version.c_str()); - Assert::AreEqual("", pgh.maintainer.c_str()); - Assert::AreEqual("", pgh.description.c_str()); - Assert::AreEqual("x86-windows", pgh.spec.triplet().canonical_name().c_str()); - Assert::AreEqual(size_t(0), pgh.depends.size()); - } - - TEST_METHOD(BinaryParagraph_Construct_Maximum) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "s"}, - {"Version", "v"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Maintainer", "m"}, - {"Description", "d"}, - {"Depends", "bd"}, - }); - Assert::AreEqual("s", pgh.spec.name().c_str()); - Assert::AreEqual("v", pgh.version.c_str()); - Assert::AreEqual("m", pgh.maintainer.c_str()); - Assert::AreEqual("d", pgh.description.c_str()); - Assert::AreEqual(size_t(1), pgh.depends.size()); - Assert::AreEqual("bd", pgh.depends[0].c_str()); - } - - TEST_METHOD(BinaryParagraph_Three_Depends) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "a, b, c"}, - }); - - Assert::AreEqual(size_t(3), pgh.depends.size()); - Assert::AreEqual("a", pgh.depends[0].c_str()); - Assert::AreEqual("b", pgh.depends[1].c_str()); - Assert::AreEqual("c", pgh.depends[2].c_str()); - } - - TEST_METHOD(parse_paragraphs_empty) - { - const char* str = ""; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::IsTrue(pghs.empty()); - } - - TEST_METHOD(parse_paragraphs_one_field) - { - const char* str = "f1: v1"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(1), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - } - - TEST_METHOD(parse_paragraphs_one_pgh) - { - const char* str = "f1: v1\n" - "f2: v2"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(2), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - Assert::AreEqual("v2", pghs[0]["f2"].c_str()); - } - - TEST_METHOD(parse_paragraphs_two_pgh) - { - const char* str = "f1: v1\n" - "f2: v2\n" - "\n" - "f3: v3\n" - "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(2), pghs.size()); - Assert::AreEqual(size_t(2), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - Assert::AreEqual("v2", pghs[0]["f2"].c_str()); - Assert::AreEqual(size_t(2), pghs[1].size()); - Assert::AreEqual("v3", pghs[1]["f3"].c_str()); - Assert::AreEqual("v4", pghs[1]["f4"].c_str()); - } - - TEST_METHOD(parse_paragraphs_field_names) - { - const char* str = "1:\n" - "f:\n" - "F:\n" - "0:\n" - "F-2:\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(5), pghs[0].size()); - } - - TEST_METHOD(parse_paragraphs_multiple_blank_lines) - { - const char* str = "f1: v1\n" - "f2: v2\n" - "\n" - "\n" - "f3: v3\n" - "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(2), pghs.size()); - } - - TEST_METHOD(parse_paragraphs_empty_fields) - { - const char* str = "f1:\n" - "f2: "; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(2), pghs[0].size()); - Assert::AreEqual("", pghs[0]["f1"].c_str()); - Assert::AreEqual("", pghs[0]["f2"].c_str()); - Assert::AreEqual(size_t(2), pghs[0].size()); - } - - TEST_METHOD(parse_paragraphs_multiline_fields) - { - const char* str = "f1: simple\n" - " f1\r\n" - "f2:\r\n" - " f2\r\n" - " continue\r\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual("simple\n f1", pghs[0]["f1"].c_str()); - Assert::AreEqual("\n f2\n continue", pghs[0]["f2"].c_str()); - } - - TEST_METHOD(parse_paragraphs_crlfs) - { - const char* str = "f1: v1\r\n" - "f2: v2\r\n" - "\r\n" - "f3: v3\r\n" - "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(2), pghs.size()); - Assert::AreEqual(size_t(2), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - Assert::AreEqual("v2", pghs[0]["f2"].c_str()); - Assert::AreEqual(size_t(2), pghs[1].size()); - Assert::AreEqual("v3", pghs[1]["f3"].c_str()); - Assert::AreEqual("v4", pghs[1]["f4"].c_str()); - } - - TEST_METHOD(parse_paragraphs_comment) - { - const char* str = "f1: v1\r\n" - "#comment\r\n" - "f2: v2\r\n" - "#comment\r\n" - "\r\n" - "#comment\r\n" - "f3: v3\r\n" - "#comment\r\n" - "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(2), pghs.size()); - Assert::AreEqual(size_t(2), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - Assert::AreEqual("v2", pghs[0]["f2"].c_str()); - Assert::AreEqual(size_t(2), pghs[1].size()); - Assert::AreEqual("v3", pghs[1]["f3"].c_str()); - Assert::AreEqual("v4", pghs[1]["f4"].c_str()); - } - - TEST_METHOD(parse_comment_before_single_slashN) - { - const char* str = "f1: v1\r\n" - "#comment\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - } - - TEST_METHOD(BinaryParagraph_serialize_min) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - }); - std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(4), pghs[0].size()); - Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); - Assert::AreEqual("1.2.8", pghs[0]["Version"].c_str()); - Assert::AreEqual("x86-windows", pghs[0]["Architecture"].c_str()); - Assert::AreEqual("same", pghs[0]["Multi-Arch"].c_str()); - } - - TEST_METHOD(BinaryParagraph_serialize_max) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Description", "first line\n second line"}, - {"Maintainer", "abc "}, - {"Depends", "dep"}, - {"Multi-Arch", "same"}, - }); - std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(7), pghs[0].size()); - Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); - Assert::AreEqual("1.2.8", pghs[0]["Version"].c_str()); - Assert::AreEqual("x86-windows", pghs[0]["Architecture"].c_str()); - Assert::AreEqual("same", pghs[0]["Multi-Arch"].c_str()); - Assert::AreEqual("first line\n second line", pghs[0]["Description"].c_str()); - Assert::AreEqual("dep", pghs[0]["Depends"].c_str()); - } - - TEST_METHOD(BinaryParagraph_serialize_multiple_deps) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "a, b, c"}, - }); - std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str()); - } - }; -} diff --git a/toolsrc/src/triplet.cpp b/toolsrc/src/triplet.cpp deleted file mode 100644 index 3b56da02a..000000000 --- a/toolsrc/src/triplet.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "pch.h" - -#include "Triplet.h" -#include "vcpkg_Checks.h" -#include "vcpkg_Strings.h" - -namespace vcpkg -{ - struct TripletInstance - { - TripletInstance(std::string&& s) : value(std::move(s)), hash(std::hash()(value)) {} - - const std::string value; - const size_t hash = 0; - - bool operator==(const TripletInstance& o) const { return o.value == value; } - }; - const TripletInstance Triplet::DEFAULT_INSTANCE({}); -} - -template<> -struct std::hash -{ - size_t operator()(const vcpkg::TripletInstance& t) const { return t.hash; } -}; - -namespace vcpkg -{ - static std::unordered_set g_triplet_instances; - - const Triplet Triplet::X86_WINDOWS = from_canonical_name("x86-windows"); - const Triplet Triplet::X64_WINDOWS = from_canonical_name("x64-windows"); - const Triplet Triplet::X86_UWP = from_canonical_name("x86-uwp"); - const Triplet Triplet::X64_UWP = from_canonical_name("x64-uwp"); - const Triplet Triplet::ARM_UWP = from_canonical_name("arm-uwp"); - - bool Triplet::operator==(const Triplet& other) const { return this->m_instance == other.m_instance; } - - bool operator!=(const Triplet& left, const Triplet& right) { return !(left == right); } - - Triplet Triplet::from_canonical_name(const std::string& triplet_as_string) - { - std::string s(Strings::ascii_to_lowercase(triplet_as_string)); - const auto it = std::find(s.cbegin(), s.cend(), '-'); - Checks::check_exit(VCPKG_LINE_INFO, it != s.cend(), "Invalid triplet: %s", triplet_as_string); - - const auto p = g_triplet_instances.emplace(std::move(s)); - return &*p.first; - } - - const std::string& Triplet::canonical_name() const { return this->m_instance->value; } - - const std::string& Triplet::to_string() const { return this->canonical_name(); } - size_t Triplet::hash_code() const { return m_instance->hash; } -} diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 706c641fb..748b4f0ee 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -1,16 +1,18 @@ #define WIN32_LEAN_AND_MEAN #include -#include "Paragraphs.h" -#include "metrics.h" -#include "vcpkg_Chrono.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Files.h" -#include "vcpkg_GlobalState.h" -#include "vcpkg_Input.h" -#include "vcpkg_Strings.h" -#include "vcpkg_System.h" -#include "vcpkglib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #pragma warning(push) #pragma warning(disable : 4768) #include @@ -19,12 +21,15 @@ #include #include +#pragma comment(lib, "ole32") +#pragma comment(lib, "shell32") + using namespace vcpkg; void invalid_command(const std::string& cmd) { System::println(System::Color::error, "invalid command: %s", cmd); - Commands::Help::print_usage(); + Help::print_usage(); Checks::exit_fail(VCPKG_LINE_INFO); } @@ -33,13 +38,26 @@ static void inner(const VcpkgCmdArguments& args) Metrics::g_metrics.lock()->track_property("command", args.command); if (args.command.empty()) { - Commands::Help::print_usage(); + Help::print_usage(); Checks::exit_fail(VCPKG_LINE_INFO); } - if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_c())) + static const auto find_command = [&](auto&& commands) { + auto it = Util::find_if(commands, [&](auto&& commandc) { + return Strings::case_insensitive_ascii_compare(commandc.name, args.command); + }); + using std::end; + if (it != end(commands)) + { + return &*it; + } + else + return static_cast(nullptr); + }; + + if (const auto command_function = find_command(Commands::get_available_commands_type_c())) { - return command_function(args); + return command_function->function(args); } fs::path vcpkg_root_dir; @@ -74,9 +92,9 @@ static void inner(const VcpkgCmdArguments& args) Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed"); Commands::Version::warn_if_vcpkg_version_mismatch(paths); - if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_b())) + if (const auto command_function = find_command(Commands::get_available_commands_type_b())) { - return command_function(args, paths); + return command_function->function(args, paths); } Triplet default_triplet; @@ -100,9 +118,9 @@ static void inner(const VcpkgCmdArguments& args) Input::check_triplet(default_triplet, paths); - if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_a())) + if (const auto command_function = find_command(Commands::get_available_commands_type_a())) { - return command_function(args, paths, default_triplet); + return command_function->function(args, paths, default_triplet); } return invalid_command(args.command); @@ -202,7 +220,7 @@ int wmain(const int argc, const wchar_t* const* const argv) SetConsoleCP(65001); SetConsoleOutputCP(65001); - *GlobalState::timer.lock() = ElapsedTime::create_started(); + *GlobalState::timer.lock() = Chrono::ElapsedTime::create_started(); const std::string trimmed_command_line = trim_path_from_command_line(Strings::to_utf8(GetCommandLineW())); diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp new file mode 100644 index 000000000..73c7b9b1a --- /dev/null +++ b/toolsrc/src/vcpkg/base/checks.cpp @@ -0,0 +1,81 @@ +#include "pch.h" + +#include +#include + +#include +#include + +namespace vcpkg::Checks +{ + [[noreturn]] static void cleanup_and_exit(const int exit_code) + { + const auto elapsed_us = GlobalState::timer.lock()->microseconds(); + + auto metrics = Metrics::g_metrics.lock(); + metrics->track_metric("elapsed_us", elapsed_us); + GlobalState::debugging = false; + metrics->flush(); + + SetConsoleCP(GlobalState::g_init_console_cp); + SetConsoleOutputCP(GlobalState::g_init_console_output_cp); + + fflush(nullptr); + + ::TerminateProcess(::GetCurrentProcess(), exit_code); + } + + static BOOL ctrl_handler(DWORD fdw_ctrl_type) + { + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_property("CtrlHandler", std::to_string(fdw_ctrl_type)); + locked_metrics->track_property("error", "CtrlHandler was fired."); + } + cleanup_and_exit(EXIT_FAILURE); + } + + void register_console_ctrl_handler() + { + SetConsoleCtrlHandler(reinterpret_cast(ctrl_handler), TRUE); + } + + [[noreturn]] void unreachable(const LineInfo& line_info) + { + System::println(System::Color::error, "Error: Unreachable code was reached"); + System::println(System::Color::error, line_info.to_string()); // Always print line_info here +#ifndef NDEBUG + std::abort(); +#else + cleanup_and_exit(EXIT_FAILURE); +#endif + } + + [[noreturn]] void exit_with_code(const LineInfo& line_info, const int exit_code) + { + Debug::println(System::Color::error, line_info.to_string()); + cleanup_and_exit(exit_code); + } + + [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView error_message) + { + System::println(System::Color::error, error_message); + exit_fail(line_info); + } + + void check_exit(const LineInfo& line_info, bool expression) + { + if (!expression) + { + exit_with_message(line_info, Strings::EMPTY); + } + } + + void check_exit(const LineInfo& line_info, bool expression, const CStringView error_message) + { + if (!expression) + { + exit_with_message(line_info, error_message); + } + } +} diff --git a/toolsrc/src/vcpkg/base/chrono.cpp b/toolsrc/src/vcpkg/base/chrono.cpp new file mode 100644 index 000000000..5d28909fc --- /dev/null +++ b/toolsrc/src/vcpkg/base/chrono.cpp @@ -0,0 +1,61 @@ +#include "pch.h" + +#include +#include + +namespace vcpkg::Chrono +{ + static std::string format_time_userfriendly(const std::chrono::nanoseconds& nanos) + { + using std::chrono::duration_cast; + using std::chrono::hours; + using std::chrono::microseconds; + using std::chrono::milliseconds; + using std::chrono::minutes; + using std::chrono::nanoseconds; + using std::chrono::seconds; + + const double nanos_as_double = static_cast(nanos.count()); + + if (duration_cast(nanos) > hours()) + { + const auto t = nanos_as_double / duration_cast(hours(1)).count(); + return Strings::format("%.4g h", t); + } + + if (duration_cast(nanos) > minutes()) + { + const auto t = nanos_as_double / duration_cast(minutes(1)).count(); + return Strings::format("%.4g min", t); + } + + if (duration_cast(nanos) > seconds()) + { + const auto t = nanos_as_double / duration_cast(seconds(1)).count(); + return Strings::format("%.4g s", t); + } + + if (duration_cast(nanos) > milliseconds()) + { + const auto t = nanos_as_double / duration_cast(milliseconds(1)).count(); + return Strings::format("%.4g ms", t); + } + + if (duration_cast(nanos) > microseconds()) + { + const auto t = nanos_as_double / duration_cast(microseconds(1)).count(); + return Strings::format("%.4g us", t); + } + + return Strings::format("%.4g ns", nanos_as_double); + } + + ElapsedTime ElapsedTime::create_started() + { + ElapsedTime t; + t.m_start_tick = std::chrono::high_resolution_clock::now(); + return t; + } + + std::string ElapsedTime::to_string() const { return format_time_userfriendly(elapsed()); } +} diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp new file mode 100644 index 000000000..5e9c86998 --- /dev/null +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -0,0 +1,308 @@ +#include "pch.h" + +#include +#include + +using namespace std; + +namespace vcpkg::CoffFileReader +{ + template + static T reinterpret_bytes(const char* data) + { + return (*reinterpret_cast(&data[0])); + } + + template + static T read_value_from_stream(fstream& fs) + { + T data; + fs.read(reinterpret_cast(&data), sizeof data); + return data; + } + + template + static T peek_value_from_stream(fstream& fs) + { + const fpos_t original_pos = fs.tellg().seekpos(); + T data; + fs.read(reinterpret_cast(&data), sizeof data); + fs.seekg(original_pos); + return data; + } + + static void verify_equal_strings( + const LineInfo& line_info, const char* expected, const char* actual, int size, const char* label) + { + Checks::check_exit(line_info, + memcmp(expected, actual, size) == 0, + "Incorrect string (%s) found. Expected: (%s) but found (%s)", + label, + expected, + actual); + } + + static void read_and_verify_PE_signature(fstream& fs) + { + static const size_t OFFSET_TO_PE_SIGNATURE_OFFSET = 0x3c; + + static const char* PE_SIGNATURE = "PE\0\0"; + static const size_t PE_SIGNATURE_SIZE = 4; + + fs.seekg(OFFSET_TO_PE_SIGNATURE_OFFSET, ios_base::beg); + const int32_t offset_to_PE_signature = read_value_from_stream(fs); + + fs.seekg(offset_to_PE_signature); + char signature[PE_SIGNATURE_SIZE]; + fs.read(signature, PE_SIGNATURE_SIZE); + verify_equal_strings(VCPKG_LINE_INFO, PE_SIGNATURE, signature, PE_SIGNATURE_SIZE, "PE_SIGNATURE"); + fs.seekg(offset_to_PE_signature + PE_SIGNATURE_SIZE, ios_base::beg); + } + + static fpos_t align_to_size(const uint64_t unaligned, const uint64_t alignment_size) + { + fpos_t aligned = unaligned - 1; + aligned /= alignment_size; + aligned += 1; + aligned *= alignment_size; + return aligned; + } + + struct CoffFileHeader + { + static const size_t HEADER_SIZE = 20; + + static CoffFileHeader read(fstream& fs) + { + CoffFileHeader ret; + ret.data.resize(HEADER_SIZE); + fs.read(&ret.data[0], HEADER_SIZE); + return ret; + } + + MachineType machine_type() const + { + static const size_t MACHINE_TYPE_OFFSET = 0; + static const size_t MACHINE_TYPE_SIZE = 2; + + std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE); + const uint16_t machine = reinterpret_bytes(machine_field_as_string.c_str()); + return to_machine_type(machine); + } + + private: + std::string data; + }; + + struct ArchiveMemberHeader + { + static const size_t HEADER_SIZE = 60; + + static ArchiveMemberHeader read(fstream& fs) + { + static const size_t HEADER_END_OFFSET = 58; + static const char* HEADER_END = "`\n"; + static const size_t HEADER_END_SIZE = 2; + + ArchiveMemberHeader ret; + ret.data.resize(HEADER_SIZE); + fs.read(&ret.data[0], HEADER_SIZE); + + if (ret.data[0] != '\0') // Due to freeglut. github issue #223 + { + const std::string header_end = ret.data.substr(HEADER_END_OFFSET, HEADER_END_SIZE); + verify_equal_strings( + VCPKG_LINE_INFO, HEADER_END, header_end.c_str(), HEADER_END_SIZE, "LIB HEADER_END"); + } + + return ret; + } + + std::string name() const + { + static const size_t HEADER_NAME_OFFSET = 0; + static const size_t HEADER_NAME_SIZE = 16; + return data.substr(HEADER_NAME_OFFSET, HEADER_NAME_SIZE); + } + + uint64_t member_size() const + { + static const size_t ALIGNMENT_SIZE = 2; + + static const size_t HEADER_SIZE_OFFSET = 48; + static const size_t HEADER_SIZE_FIELD_SIZE = 10; + const std::string as_string = data.substr(HEADER_SIZE_OFFSET, HEADER_SIZE_FIELD_SIZE); + // This is in ASCII decimal representation + const uint64_t value = std::strtoull(as_string.c_str(), nullptr, 10); + + const uint64_t aligned = align_to_size(value, ALIGNMENT_SIZE); + return aligned; + } + + std::string data; + }; + + struct OffsetsArray + { + static OffsetsArray read(fstream& fs, const uint32_t offset_count) + { + static const size_t OFFSET_WIDTH = 4; + + std::string raw_offsets; + const size_t raw_offset_size = offset_count * OFFSET_WIDTH; + raw_offsets.resize(raw_offset_size); + fs.read(&raw_offsets[0], raw_offset_size); + + OffsetsArray ret; + for (uint32_t i = 0; i < offset_count; ++i) + { + const std::string value_as_string = raw_offsets.substr(OFFSET_WIDTH * i, OFFSET_WIDTH * (i + 1)); + const uint32_t value = reinterpret_bytes(value_as_string.c_str()); + + // Ignore offsets that point to offset 0. See vcpkg github #223 #288 #292 + if (value != 0) + { + ret.data.push_back(value); + } + } + + // Sort the offsets, because it is possible for them to be unsorted. See vcpkg github #292 + std::sort(ret.data.begin(), ret.data.end()); + return ret; + } + + std::vector data; + }; + + struct ImportHeader + { + static const size_t HEADER_SIZE = 20; + + static ImportHeader read(fstream& fs) + { + static const size_t SIG1_OFFSET = 0; + static const uint16_t SIG1 = static_cast(MachineType::UNKNOWN); + static const size_t SIG1_SIZE = 2; + + static const size_t SIG2_OFFSET = 2; + static const uint16_t SIG2 = 0xFFFF; + static const size_t SIG2_SIZE = 2; + + ImportHeader ret; + ret.data.resize(HEADER_SIZE); + fs.read(&ret.data[0], HEADER_SIZE); + + const std::string sig1_as_string = ret.data.substr(SIG1_OFFSET, SIG1_SIZE); + const uint16_t sig1 = reinterpret_bytes(sig1_as_string.c_str()); + Checks::check_exit(VCPKG_LINE_INFO, sig1 == SIG1, "Sig1 was incorrect. Expected %s but got %s", SIG1, sig1); + + const std::string sig2_as_string = ret.data.substr(SIG2_OFFSET, SIG2_SIZE); + const uint16_t sig2 = reinterpret_bytes(sig2_as_string.c_str()); + Checks::check_exit(VCPKG_LINE_INFO, sig2 == SIG2, "Sig2 was incorrect. Expected %s but got %s", SIG2, sig2); + + return ret; + } + + MachineType machine_type() const + { + static const size_t MACHINE_TYPE_OFFSET = 6; + static const size_t MACHINE_TYPE_SIZE = 2; + + std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE); + const uint16_t machine = reinterpret_bytes(machine_field_as_string.c_str()); + return to_machine_type(machine); + } + + private: + std::string data; + }; + + static void read_and_verify_archive_file_signature(fstream& fs) + { + static const char* FILE_START = "!\n"; + static const size_t FILE_START_SIZE = 8; + + fs.seekg(fs.beg); + + char file_start[FILE_START_SIZE]; + fs.read(file_start, FILE_START_SIZE); + verify_equal_strings(VCPKG_LINE_INFO, FILE_START, file_start, FILE_START_SIZE, "LIB FILE_START"); + } + + DllInfo read_dll(const fs::path& path) + { + std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate); + Checks::check_exit(VCPKG_LINE_INFO, fs.is_open(), "Could not open file %s for reading", path.generic_string()); + + read_and_verify_PE_signature(fs); + CoffFileHeader header = CoffFileHeader::read(fs); + const MachineType machine = header.machine_type(); + return {machine}; + } + + struct Marker + { + void set_to_offset(const fpos_t position) { this->m_absolute_position = position; } + + void set_to_current_pos(fstream& fs) { this->m_absolute_position = fs.tellg().seekpos(); } + + void seek_to_marker(fstream& fs) const { fs.seekg(this->m_absolute_position, ios_base::beg); } + + void advance_by(const uint64_t offset) { this->m_absolute_position += offset; } + + private: + fpos_t m_absolute_position = 0; + }; + + LibInfo read_lib(const fs::path& path) + { + std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate); + Checks::check_exit(VCPKG_LINE_INFO, fs.is_open(), "Could not open file %s for reading", path.generic_string()); + + read_and_verify_archive_file_signature(fs); + + Marker marker; + marker.set_to_current_pos(fs); + + // First Linker Member + const ArchiveMemberHeader first_linker_member_header = ArchiveMemberHeader::read(fs); + Checks::check_exit(VCPKG_LINE_INFO, + first_linker_member_header.name().substr(0, 2) == "/ ", + "Could not find proper first linker member"); + marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + first_linker_member_header.member_size()); + marker.seek_to_marker(fs); + + const ArchiveMemberHeader second_linker_member_header = ArchiveMemberHeader::read(fs); + Checks::check_exit(VCPKG_LINE_INFO, + second_linker_member_header.name().substr(0, 2) == "/ ", + "Could not find proper second linker member"); + // The first 4 bytes contains the number of archive members + const uint32_t archive_member_count = read_value_from_stream(fs); + const OffsetsArray offsets = OffsetsArray::read(fs, archive_member_count); + marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + second_linker_member_header.member_size()); + marker.seek_to_marker(fs); + + const bool hasLongnameMemberHeader = peek_value_from_stream(fs) == 0x2F2F; + if (hasLongnameMemberHeader) + { + const ArchiveMemberHeader longnames_member_header = ArchiveMemberHeader::read(fs); + marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + longnames_member_header.member_size()); + marker.seek_to_marker(fs); + } + + std::set machine_types; + // Next we have the obj and pseudo-object files + for (const uint32_t offset : offsets.data) + { + marker.set_to_offset(offset + ArchiveMemberHeader::HEADER_SIZE); // Skip the header, no need to read it. + marker.seek_to_marker(fs); + const uint16_t first_two_bytes = peek_value_from_stream(fs); + const bool isImportHeader = to_machine_type(first_two_bytes) == MachineType::UNKNOWN; + const MachineType machine = + isImportHeader ? ImportHeader::read(fs).machine_type() : CoffFileHeader::read(fs).machine_type(); + machine_types.insert(machine); + } + + return {std::vector(machine_types.cbegin(), machine_types.cend())}; + } +} diff --git a/toolsrc/src/vcpkg/base/enums.cpp b/toolsrc/src/vcpkg/base/enums.cpp new file mode 100644 index 000000000..aa124f3aa --- /dev/null +++ b/toolsrc/src/vcpkg/base/enums.cpp @@ -0,0 +1,14 @@ +#include "pch.h" + +#include +#include + +namespace vcpkg::Enums +{ + std::string nullvalue_to_string(const CStringView enum_name) { return Strings::format("%s_NULLVALUE", enum_name); } + + [[noreturn]] void nullvalue_used(const LineInfo& line_info, const CStringView enum_name) + { + Checks::exit_with_message(line_info, "NULLVALUE of enum %s was used", enum_name); + } +} diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp new file mode 100644 index 000000000..f8b239eaa --- /dev/null +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -0,0 +1,208 @@ +#include "pch.h" + +#include +#include +#include + +namespace vcpkg::Files +{ + static const std::regex FILESYSTEM_INVALID_CHARACTERS_REGEX = std::regex(R"([\/:*?"<>|])"); + + struct RealFilesystem final : Filesystem + { + virtual Expected read_contents(const fs::path& file_path) const override + { + std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); + if (file_stream.fail()) + { + return std::make_error_code(std::errc::no_such_file_or_directory); + } + + file_stream.seekg(0, file_stream.end); + auto length = file_stream.tellg(); + file_stream.seekg(0, file_stream.beg); + + if (length > SIZE_MAX) + { + return std::make_error_code(std::errc::file_too_large); + } + + std::string output; + output.resize(static_cast(length)); + file_stream.read(&output[0], length); + file_stream.close(); + + return std::move(output); + } + virtual Expected> read_lines(const fs::path& file_path) const override + { + std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); + if (file_stream.fail()) + { + return std::make_error_code(std::errc::no_such_file_or_directory); + } + + std::vector output; + std::string line; + while (std::getline(file_stream, line)) + { + output.push_back(line); + } + file_stream.close(); + + return std::move(output); + } + virtual fs::path find_file_recursively_up(const fs::path& starting_dir, + const std::string& filename) const override + { + fs::path current_dir = starting_dir; + for (; !current_dir.empty(); current_dir = current_dir.parent_path()) + { + const fs::path candidate = current_dir / filename; + if (exists(candidate)) + { + break; + } + } + + return current_dir; + } + + virtual std::vector get_files_recursive(const fs::path& dir) const override + { + std::vector ret; + + fs::stdfs::recursive_directory_iterator b(dir), e{}; + for (; b != e; ++b) + { + ret.push_back(b->path()); + } + + return ret; + } + + virtual std::vector get_files_non_recursive(const fs::path& dir) const override + { + std::vector ret; + + fs::stdfs::directory_iterator b(dir), e{}; + for (; b != e; ++b) + { + ret.push_back(b->path()); + } + + return ret; + } + + virtual void write_lines(const fs::path& file_path, const std::vector& lines) override + { + std::fstream output(file_path, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); + for (const std::string& line : lines) + { + output << line << "\n"; + } + output.close(); + } + + virtual void rename(const fs::path& oldpath, const fs::path& newpath) override + { + fs::stdfs::rename(oldpath, newpath); + } + virtual bool remove(const fs::path& path) override { return fs::stdfs::remove(path); } + virtual bool remove(const fs::path& path, std::error_code& ec) override { return fs::stdfs::remove(path, ec); } + virtual std::uintmax_t remove_all(const fs::path& path, std::error_code& ec) override + { + // Working around the currently buggy remove_all() + std::uintmax_t out = fs::stdfs::remove_all(path, ec); + + for (int i = 0; i < 5 && this->exists(path); i++) + { + using namespace std::chrono_literals; + std::this_thread::sleep_for(i * 100ms); + out += fs::stdfs::remove_all(path, ec); + } + + if (this->exists(path)) + { + System::println(System::Color::warning, + "Some files in %s were unable to be removed. Close any editors operating in this " + "directory and retry.", + path.string()); + } + + return out; + } + virtual bool exists(const fs::path& path) const override { return fs::stdfs::exists(path); } + virtual bool is_directory(const fs::path& path) const override { return fs::stdfs::is_directory(path); } + virtual bool is_regular_file(const fs::path& path) const override { return fs::stdfs::is_regular_file(path); } + virtual bool is_empty(const fs::path& path) const override { return fs::stdfs::is_empty(path); } + virtual bool create_directory(const fs::path& path, std::error_code& ec) override + { + return fs::stdfs::create_directory(path, ec); + } + virtual bool create_directories(const fs::path& path, std::error_code& ec) override + { + return fs::stdfs::create_directories(path, ec); + } + virtual void copy(const fs::path& oldpath, const fs::path& newpath, fs::copy_options opts) override + { + fs::stdfs::copy(oldpath, newpath, opts); + } + virtual bool copy_file(const fs::path& oldpath, + const fs::path& newpath, + fs::copy_options opts, + std::error_code& ec) override + { + return fs::stdfs::copy_file(oldpath, newpath, opts, ec); + } + + virtual fs::file_status status(const fs::path& path, std::error_code& ec) const override + { + return fs::stdfs::status(path, ec); + } + virtual void write_contents(const fs::path& file_path, const std::string& data) override + { + FILE* f = nullptr; + auto ec = _wfopen_s(&f, file_path.native().c_str(), L"wb"); + Checks::check_exit( + VCPKG_LINE_INFO, ec == 0, "Error: Could not open file for writing: %s", file_path.u8string().c_str()); + auto count = fwrite(data.data(), sizeof(data[0]), data.size(), f); + fclose(f); + + Checks::check_exit(VCPKG_LINE_INFO, count == data.size()); + } + }; + + Filesystem& get_real_filesystem() + { + static RealFilesystem real_fs; + return real_fs; + } + + bool has_invalid_chars_for_filesystem(const std::string& s) + { + return std::regex_search(s, FILESYSTEM_INVALID_CHARACTERS_REGEX); + } + + void print_paths(const std::vector& paths) + { + System::println(); + for (const fs::path& p : paths) + { + System::println(" %s", p.generic_string()); + } + System::println(); + } + + std::vector find_from_PATH(const std::wstring& name) + { + const std::wstring cmd = Strings::wformat(L"where.exe %s", name); + auto out = System::cmd_execute_and_capture_output(cmd); + if (out.exit_code != 0) + { + return {}; + } + + return Util::fmap(Strings::split(out.output, "\n"), [](auto&& s) { return fs::path(s); }); + } +} diff --git a/toolsrc/src/vcpkg/base/lineinfo.cpp b/toolsrc/src/vcpkg/base/lineinfo.cpp new file mode 100644 index 000000000..7435ed666 --- /dev/null +++ b/toolsrc/src/vcpkg/base/lineinfo.cpp @@ -0,0 +1,9 @@ +#include "pch.h" + +#include +#include + +namespace vcpkg +{ + std::string LineInfo::to_string() const { return Strings::format("%s(%d)", this->file_name, this->line_number); } +} diff --git a/toolsrc/src/vcpkg/base/machinetype.cpp b/toolsrc/src/vcpkg/base/machinetype.cpp new file mode 100644 index 000000000..2b7bd5e3a --- /dev/null +++ b/toolsrc/src/vcpkg/base/machinetype.cpp @@ -0,0 +1,41 @@ +#include "pch.h" + +#include +#include + +namespace vcpkg +{ + MachineType to_machine_type(const uint16_t value) + { + const MachineType t = static_cast(value); + switch (t) + { + case MachineType::UNKNOWN: + case MachineType::AM33: + case MachineType::AMD64: + case MachineType::ARM: + case MachineType::ARM64: + case MachineType::ARMNT: + case MachineType::EBC: + case MachineType::I386: + case MachineType::IA64: + case MachineType::M32R: + case MachineType::MIPS16: + case MachineType::MIPSFPU: + case MachineType::MIPSFPU16: + case MachineType::POWERPC: + case MachineType::POWERPCFP: + case MachineType::R4000: + case MachineType::RISCV32: + case MachineType::RISCV64: + case MachineType::RISCV128: + case MachineType::SH3: + case MachineType::SH3DSP: + case MachineType::SH4: + case MachineType::SH5: + case MachineType::THUMB: + case MachineType::WCEMIPSV2: return t; + default: Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown machine type code 0x%x", value); + } + } +} diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp new file mode 100644 index 000000000..2a6d3dff2 --- /dev/null +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -0,0 +1,174 @@ +#include "pch.h" + +#include +#include +#include + +namespace vcpkg::Strings::details +{ + // To disambiguate between two overloads + static const auto isspace = [](const char c) { return std::isspace(c); }; + + // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower() + static char tolower_char(const char c) { return static_cast(std::tolower(c)); } + +#if defined(_WIN32) + static _locale_t& c_locale() + { + static _locale_t c_locale_impl = _create_locale(LC_ALL, "C"); + return c_locale_impl; + } +#endif + + std::string format_internal(const char* fmtstr, ...) + { + va_list args; + va_start(args, fmtstr); + +#if defined(_WIN32) + const int sz = _vscprintf_l(fmtstr, c_locale(), args); +#else + const int sz = vsnprintf(nullptr, 0, fmtstr, args); +#endif + Checks::check_exit(VCPKG_LINE_INFO, sz > 0); + + std::string output(sz, '\0'); + +#if defined(_WIN32) + _vsnprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args); +#else + vsnprintf(&output.at(0), output.size() + 1, fmtstr, args); +#endif + va_end(args); + + return output; + } + + std::wstring wformat_internal(const wchar_t* fmtstr, ...) + { + va_list args; + va_start(args, fmtstr); + +#if defined(_WIN32) + const int sz = _vscwprintf_l(fmtstr, c_locale(), args); +#else + const int sz = vswprintf(nullptr, 0, fmtstr, args); +#endif + Checks::check_exit(VCPKG_LINE_INFO, sz > 0); + + std::wstring output(sz, L'\0'); + +#if defined(_WIN32) + _vsnwprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args); +#else + vswprintf(&output.at(0), output.size() + 1, fmtstr, args); +#endif + va_end(args); + + return output; + } +} + +namespace vcpkg::Strings +{ + std::wstring to_utf16(const CStringView s) + { + const int size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0); + std::wstring output; + output.resize(size - 1); + MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, output.data(), size - 1); + return output; + } + + std::string to_utf8(const CWStringView w) + { + const int size = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr); + std::string output; + output.resize(size - 1); + WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, output.data(), size - 1, nullptr, nullptr); + return output; + } + + std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern) + { + const std::string pattern_as_lower_case(ascii_to_lowercase(pattern)); + return search(s.begin(), + s.end(), + pattern_as_lower_case.begin(), + pattern_as_lower_case.end(), + [](const char a, const char b) { return details::tolower_char(a) == b; }); + } + + bool case_insensitive_ascii_contains(const std::string& s, const std::string& pattern) + { + return case_insensitive_ascii_find(s, pattern) != s.end(); + } + + bool case_insensitive_ascii_compare(const CStringView left, const CStringView right) + { + return _stricmp(left.c_str(), right.c_str()) == 0; + } + + std::string ascii_to_lowercase(const std::string& input) + { + std::string output(input); + std::transform(output.begin(), output.end(), output.begin(), &details::tolower_char); + return output; + } + + bool case_insensitive_ascii_starts_with(const std::string& s, const std::string& pattern) + { + return _strnicmp(s.c_str(), pattern.c_str(), pattern.size()) == 0; + } + + void trim(std::string* s) + { + s->erase(std::find_if_not(s->rbegin(), s->rend(), details::isspace).base(), s->end()); + s->erase(s->begin(), std::find_if_not(s->begin(), s->end(), details::isspace)); + } + + std::string trimmed(const std::string& s) + { + auto whitespace_back = std::find_if_not(s.rbegin(), s.rend(), details::isspace).base(); + auto whitespace_front = std::find_if_not(s.begin(), whitespace_back, details::isspace); + return std::string(whitespace_front, whitespace_back); + } + + void trim_all_and_remove_whitespace_strings(std::vector* strings) + { + for (std::string& s : *strings) + { + trim(&s); + } + + Util::erase_remove_if(*strings, [](const std::string& s) { return s.empty(); }); + } + + std::vector split(const std::string& s, const std::string& delimiter) + { + std::vector output; + + if (delimiter.empty()) + { + output.push_back(s); + return output; + } + + const size_t delimiter_length = delimiter.length(); + size_t i = 0; + for (size_t pos = s.find(delimiter); pos != std::string::npos; pos = s.find(delimiter, pos)) + { + output.push_back(s.substr(i, pos - i)); + pos += delimiter_length; + i = pos; + } + + // Add the rest of the string after the last delimiter, unless there is nothing after it + if (i != s.length()) + { + output.push_back(s.substr(i, s.length())); + } + + return output; + } +} diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp new file mode 100644 index 000000000..716c2a6a6 --- /dev/null +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -0,0 +1,350 @@ +#include "pch.h" + +#include +#include +#include + +#pragma comment(lib, "Advapi32") + +namespace vcpkg::System +{ + tm get_current_date_time() + { + using std::chrono::system_clock; + std::time_t now_time = system_clock::to_time_t(system_clock::now()); + tm parts; + localtime_s(&parts, &now_time); + return parts; + } + + fs::path get_exe_path_of_current_process() + { + wchar_t buf[_MAX_PATH]; + const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); + if (bytes == 0) std::abort(); + return fs::path(buf, buf + bytes); + } + + Optional to_cpu_architecture(CStringView arch) + { + if (Strings::case_insensitive_ascii_compare(arch, "x86")) return CPUArchitecture::X86; + if (Strings::case_insensitive_ascii_compare(arch, "x64")) return CPUArchitecture::X64; + if (Strings::case_insensitive_ascii_compare(arch, "amd64")) return CPUArchitecture::X64; + if (Strings::case_insensitive_ascii_compare(arch, "arm")) return CPUArchitecture::ARM; + if (Strings::case_insensitive_ascii_compare(arch, "arm64")) return CPUArchitecture::ARM64; + return nullopt; + } + + CPUArchitecture get_host_processor() + { + auto w6432 = get_environment_variable(L"PROCESSOR_ARCHITEW6432"); + if (const auto p = w6432.get()) return to_cpu_architecture(Strings::to_utf8(*p)).value_or_exit(VCPKG_LINE_INFO); + + const auto procarch = get_environment_variable(L"PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO); + return to_cpu_architecture(Strings::to_utf8(procarch)).value_or_exit(VCPKG_LINE_INFO); + } + + std::vector get_supported_host_architectures() + { + std::vector supported_architectures; + supported_architectures.push_back(get_host_processor()); + + // AMD64 machines support to run x86 applications + if (supported_architectures.back() == CPUArchitecture::X64) + { + supported_architectures.push_back(CPUArchitecture::X86); + } + + return supported_architectures; + } + + int cmd_execute_clean(const CWStringView cmd_line) + { + static const std::wstring SYSTEM_ROOT = get_environment_variable(L"SystemRoot").value_or_exit(VCPKG_LINE_INFO); + static const std::wstring SYSTEM_32 = SYSTEM_ROOT + LR"(\system32)"; + static const std::wstring NEW_PATH = Strings::wformat( + LR"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32); + + std::vector env_wstrings = { + L"ALLUSERSPROFILE", + L"APPDATA", + L"CommonProgramFiles", + L"CommonProgramFiles(x86)", + L"CommonProgramW6432", + L"COMPUTERNAME", + L"ComSpec", + L"HOMEDRIVE", + L"HOMEPATH", + L"LOCALAPPDATA", + L"LOGONSERVER", + L"NUMBER_OF_PROCESSORS", + L"OS", + L"PATHEXT", + L"PROCESSOR_ARCHITECTURE", + L"PROCESSOR_ARCHITEW6432", + L"PROCESSOR_IDENTIFIER", + L"PROCESSOR_LEVEL", + L"PROCESSOR_REVISION", + L"ProgramData", + L"ProgramFiles", + L"ProgramFiles(x86)", + L"ProgramW6432", + L"PROMPT", + L"PSModulePath", + L"PUBLIC", + L"SystemDrive", + L"SystemRoot", + L"TEMP", + L"TMP", + L"USERDNSDOMAIN", + L"USERDOMAIN", + L"USERDOMAIN_ROAMINGPROFILE", + L"USERNAME", + L"USERPROFILE", + L"windir", + // Enables proxy information to be passed to Curl, the underlying download library in cmake.exe + L"HTTP_PROXY", + L"HTTPS_PROXY", + // Enables find_package(CUDA) in CMake + L"CUDA_PATH", + }; + + // Flush stdout before launching external process + fflush(nullptr); + + std::wstring env_cstr; + + for (auto&& env_wstring : env_wstrings) + { + const Optional value = System::get_environment_variable(env_wstring); + const auto v = value.get(); + if (!v || v->empty()) continue; + + env_cstr.append(env_wstring); + env_cstr.push_back(L'='); + env_cstr.append(*v); + env_cstr.push_back(L'\0'); + } + + env_cstr.append(NEW_PATH); + env_cstr.push_back(L'\0'); + + STARTUPINFOW startup_info; + memset(&startup_info, 0, sizeof(STARTUPINFOW)); + startup_info.cb = sizeof(STARTUPINFOW); + + PROCESS_INFORMATION process_info; + memset(&process_info, 0, sizeof(PROCESS_INFORMATION)); + + // Basically we are wrapping it in quotes + std::wstring actual_cmd_line = Strings::wformat(LR"###(cmd.exe /c "%s")###", cmd_line); + Debug::println("CreateProcessW(%s)", Strings::to_utf8(actual_cmd_line)); + bool succeeded = TRUE == CreateProcessW(nullptr, + actual_cmd_line.data(), + nullptr, + nullptr, + FALSE, + BELOW_NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, + env_cstr.data(), + nullptr, + &startup_info, + &process_info); + + Checks::check_exit(VCPKG_LINE_INFO, succeeded, "Process creation failed with error code: %lu", GetLastError()); + + CloseHandle(process_info.hThread); + + const DWORD result = WaitForSingleObject(process_info.hProcess, INFINITE); + Checks::check_exit(VCPKG_LINE_INFO, result != WAIT_FAILED, "WaitForSingleObject failed"); + + DWORD exit_code = 0; + GetExitCodeProcess(process_info.hProcess, &exit_code); + + Debug::println("CreateProcessW() returned %lu", exit_code); + return static_cast(exit_code); + } + + int cmd_execute(const CWStringView cmd_line) + { + // Flush stdout before launching external process + fflush(nullptr); + + // Basically we are wrapping it in quotes + const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); + Debug::println("_wsystem(%s)", Strings::to_utf8(actual_cmd_line)); + const int exit_code = _wsystem(actual_cmd_line.c_str()); + Debug::println("_wsystem() returned %d", exit_code); + return exit_code; + } + + // On Win7, output from powershell calls contain a byte order mark, so we strip it out if it is present + static void remove_byte_order_marks(std::wstring* s) + { + const wchar_t* a = s->c_str(); + // This is the UTF-8 byte-order mark + while (s->size() >= 3 && a[0] == 0xEF && a[1] == 0xBB && a[2] == 0xBF) + { + s->erase(0, 3); + } + } + + ExitCodeAndOutput cmd_execute_and_capture_output(const CWStringView cmd_line) + { + // Flush stdout before launching external process + fflush(stdout); + + const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s 2>&1")###", cmd_line); + + Debug::println("_wpopen(%s)", Strings::to_utf8(actual_cmd_line)); + std::wstring output; + wchar_t buf[1024]; + const auto pipe = _wpopen(actual_cmd_line.c_str(), L"r"); + if (pipe == nullptr) + { + return {1, Strings::to_utf8(output)}; + } + while (fgetws(buf, 1024, pipe)) + { + output.append(buf); + } + if (!feof(pipe)) + { + return {1, Strings::to_utf8(output)}; + } + + const auto ec = _pclose(pipe); + Debug::println("_pclose() returned %d", ec); + remove_byte_order_marks(&output); + return {ec, Strings::to_utf8(output)}; + } + + std::wstring create_powershell_script_cmd(const fs::path& script_path, const CWStringView args) + { + // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned + return Strings::wformat( + LR"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.native(), args); + } + + void println() { println(Strings::EMPTY); } + + void print(const CStringView message) { fputs(message.c_str(), stdout); } + + void println(const CStringView message) + { + print(message); + putchar('\n'); + } + + void print(const Color c, const CStringView message) + { + const HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); + + CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info{}; + GetConsoleScreenBufferInfo(console_handle, &console_screen_buffer_info); + const auto original_color = console_screen_buffer_info.wAttributes; + + SetConsoleTextAttribute(console_handle, static_cast(c) | (original_color & 0xF0)); + print(message); + SetConsoleTextAttribute(console_handle, original_color); + } + + void println(const Color c, const CStringView message) + { + print(c, message); + putchar('\n'); + } + + Optional get_environment_variable(const CWStringView varname) noexcept + { + const auto sz = GetEnvironmentVariableW(varname.c_str(), nullptr, 0); + if (sz == 0) return nullopt; + + std::wstring ret(sz, L'\0'); + + Checks::check_exit(VCPKG_LINE_INFO, MAXDWORD >= ret.size()); + const auto sz2 = GetEnvironmentVariableW(varname.c_str(), ret.data(), static_cast(ret.size())); + Checks::check_exit(VCPKG_LINE_INFO, sz2 + 1 == sz); + ret.pop_back(); + return ret; + } + + static bool is_string_keytype(DWORD hkey_type) + { + return hkey_type == REG_SZ || hkey_type == REG_MULTI_SZ || hkey_type == REG_EXPAND_SZ; + } + + Optional get_registry_string(HKEY base, const CWStringView sub_key, const CWStringView valuename) + { + HKEY k = nullptr; + const LSTATUS ec = RegOpenKeyExW(base, sub_key.c_str(), NULL, KEY_READ, &k); + if (ec != ERROR_SUCCESS) return nullopt; + + DWORD dw_buffer_size = 0; + DWORD dw_type = 0; + auto rc = RegQueryValueExW(k, valuename.c_str(), nullptr, &dw_type, nullptr, &dw_buffer_size); + if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size == 0 || + dw_buffer_size % sizeof(wchar_t) != 0) + return nullopt; + std::wstring ret; + ret.resize(dw_buffer_size / sizeof(wchar_t)); + + rc = RegQueryValueExW( + k, valuename.c_str(), nullptr, &dw_type, reinterpret_cast(ret.data()), &dw_buffer_size); + if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size != sizeof(wchar_t) * ret.size()) + return nullopt; + + ret.pop_back(); // remove extra trailing null byte + return ret; + } + + static const fs::path& get_program_files() + { + static const fs::path PATH = System::get_environment_variable(L"PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO); + return PATH; + } + + const fs::path& get_program_files_32_bit() + { + static const fs::path PATH = []() -> fs::path { + auto value = System::get_environment_variable(L"ProgramFiles(x86)"); + if (auto v = value.get()) + { + return std::move(*v); + } + return get_program_files(); + }(); + return PATH; + } + + const fs::path& get_program_files_platform_bitness() + { + static const fs::path PATH = []() -> fs::path { + auto value = System::get_environment_variable(L"ProgramW6432"); + if (auto v = value.get()) + { + return std::move(*v); + } + return get_program_files(); + }(); + return PATH; + } +} + +namespace vcpkg::Debug +{ + void println(const CStringView message) + { + if (GlobalState::debugging) + { + System::println("[DEBUG] %s", message); + } + } + + void println(const System::Color c, const CStringView message) + { + if (GlobalState::debugging) + { + System::println(c, "[DEBUG] %s", message); + } + } +} diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp new file mode 100644 index 000000000..ef943011f --- /dev/null +++ b/toolsrc/src/vcpkg/binaryparagraph.cpp @@ -0,0 +1,123 @@ +#include "pch.h" + +#include +#include +#include + +namespace vcpkg +{ + namespace Fields + { + static const std::string PACKAGE = "Package"; + static const std::string VERSION = "Version"; + static const std::string ARCHITECTURE = "Architecture"; + static const std::string MULTI_ARCH = "Multi-Arch"; + } + + namespace Fields + { + static const std::string FEATURE = "Feature"; + static const std::string DESCRIPTION = "Description"; + static const std::string MAINTAINER = "Maintainer"; + static const std::string DEPENDS = "Depends"; + static const std::string DEFAULTFEATURES = "Default-Features"; + } + + BinaryParagraph::BinaryParagraph() = default; + + BinaryParagraph::BinaryParagraph(std::unordered_map fields) + { + using namespace vcpkg::Parse; + + ParagraphParser parser(std::move(fields)); + + { + std::string name; + parser.required_field(Fields::PACKAGE, name); + std::string architecture; + parser.required_field(Fields::ARCHITECTURE, architecture); + this->spec = PackageSpec::from_name_and_triplet(name, Triplet::from_canonical_name(architecture)) + .value_or_exit(VCPKG_LINE_INFO); + } + + // one or the other + this->version = parser.optional_field(Fields::VERSION); + this->feature = parser.optional_field(Fields::FEATURE); + + this->description = parser.optional_field(Fields::DESCRIPTION); + this->maintainer = parser.optional_field(Fields::MAINTAINER); + + std::string multi_arch; + parser.required_field(Fields::MULTI_ARCH, multi_arch); + + this->depends = parse_comma_list(parser.optional_field(Fields::DEPENDS)); + if (this->feature.empty()) + { + this->default_features = parse_comma_list(parser.optional_field(Fields::DEFAULTFEATURES)); + } + + if (const auto err = parser.error_info(this->spec.to_string())) + { + System::println( + System::Color::error, "Error: while parsing the Binary Paragraph for %s", this->spec.to_string()); + print_error_message(err); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + // prefer failing above when possible because it gives better information + Checks::check_exit(VCPKG_LINE_INFO, multi_arch == "same", "Multi-Arch must be 'same' but was %s", multi_arch); + } + + BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const Triplet& triplet) + { + this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); + this->version = spgh.version; + this->description = spgh.description; + this->maintainer = spgh.maintainer; + this->depends = filter_dependencies(spgh.depends, triplet); + } + + BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, const Triplet& triplet) + { + this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); + this->version = Strings::EMPTY; + this->feature = fpgh.name; + this->description = fpgh.description; + this->maintainer = Strings::EMPTY; + this->depends = filter_dependencies(fpgh.depends, triplet); + } + + std::string BinaryParagraph::displayname() const + { + const auto f = this->feature.empty() ? "core" : this->feature; + return Strings::format("%s[%s]:%s", this->spec.name(), f, this->spec.triplet()); + } + + std::string BinaryParagraph::dir() const { return this->spec.dir(); } + + std::string BinaryParagraph::fullstem() const + { + return Strings::format("%s_%s_%s", this->spec.name(), this->version, this->spec.triplet()); + } + + void serialize(const BinaryParagraph& pgh, std::string& out_str) + { + out_str.append("Package: ").append(pgh.spec.name()).push_back('\n'); + if (!pgh.version.empty()) + out_str.append("Version: ").append(pgh.version).push_back('\n'); + else if (!pgh.feature.empty()) + out_str.append("Feature: ").append(pgh.feature).push_back('\n'); + if (!pgh.depends.empty()) + { + out_str.append("Depends: "); + out_str.append(Strings::join(", ", pgh.depends)); + out_str.push_back('\n'); + } + + out_str.append("Architecture: ").append(pgh.spec.triplet().to_string()).push_back('\n'); + out_str.append("Multi-Arch: same\n"); + + if (!pgh.maintainer.empty()) out_str.append("Maintainer: ").append(pgh.maintainer).push_back('\n'); + if (!pgh.description.empty()) out_str.append("Description: ").append(pgh.description).push_back('\n'); + } +} diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp new file mode 100644 index 000000000..99ec541c1 --- /dev/null +++ b/toolsrc/src/vcpkg/build.cpp @@ -0,0 +1,533 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using vcpkg::Build::BuildResult; +using vcpkg::Parse::ParseControlErrorInfo; +using vcpkg::Parse::ParseExpected; + +namespace vcpkg::Build::Command +{ + using Dependencies::InstallPlanAction; + using Dependencies::InstallPlanType; + + static const std::string OPTION_CHECKS_ONLY = "--checks-only"; + + void perform_and_exit(const FullPackageSpec& full_spec, + const fs::path& port_dir, + const std::unordered_set& options, + const VcpkgPaths& paths) + { + const PackageSpec& spec = full_spec.package_spec; + if (options.find(OPTION_CHECKS_ONLY) != options.end()) + { + const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet()); + const auto build_info = Build::read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); + const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); + Checks::check_exit(VCPKG_LINE_INFO, error_count == 0); + Checks::exit_success(VCPKG_LINE_INFO); + } + + const ParseExpected source_control_file = + Paragraphs::try_load_port(paths.get_filesystem(), port_dir); + + if (!source_control_file.has_value()) + { + print_error_message(source_control_file.error()); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + for (const std::string& str : full_spec.features) + { + System::println("%s \n", str); + } + const auto& scf = source_control_file.value_or_exit(VCPKG_LINE_INFO); + Checks::check_exit(VCPKG_LINE_INFO, + spec.name() == scf->core_paragraph->name, + "The Name: field inside the CONTROL does not match the port directory: '%s' != '%s'", + scf->core_paragraph->name, + spec.name()); + + const StatusParagraphs status_db = database_load_check(paths); + const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; + + const Build::BuildPackageConfig build_config{ + *scf->core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options}; + + const auto result = Build::build_package(paths, build_config, status_db); + if (result.code == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES) + { + System::println(System::Color::error, + "The build command requires all dependencies to be already installed."); + System::println("The following dependencies are missing:"); + System::println(); + for (const auto& p : result.unmet_dependencies) + { + System::println(" %s", p); + } + System::println(); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + if (result.code != BuildResult::SUCCEEDED) + { + System::println(System::Color::error, Build::create_error_message(result.code, spec)); + System::println(Build::create_user_troubleshooting_message(spec)); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + Checks::exit_success(VCPKG_LINE_INFO); + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + static const std::string EXAMPLE = Help::create_example_string("build zlib:x64-windows"); + // Build only takes a single package and all dependencies must already be installed + args.check_exact_arg_count(1, EXAMPLE); + const std::string command_argument = args.command_arguments.at(0); + const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, EXAMPLE); + Input::check_triplet(spec.package_spec.triplet(), paths); + const std::unordered_set options = + args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}); + perform_and_exit(spec, paths.port_dir(spec.package_spec), options, paths); + } +} + +namespace vcpkg::Build +{ + static const std::string NAME_EMPTY_PACKAGE = "PolicyEmptyPackage"; + static const std::string NAME_DLLS_WITHOUT_LIBS = "PolicyDLLsWithoutLIBs"; + static const std::string NAME_ONLY_RELEASE_CRT = "PolicyOnlyReleaseCRT"; + static const std::string NAME_EMPTY_INCLUDE_FOLDER = "PolicyEmptyIncludeFolder"; + static const std::string NAME_ALLOW_OBSOLETE_MSVCRT = "PolicyAllowObsoleteMsvcrt"; + + const std::string& to_string(BuildPolicy policy) + { + switch (policy) + { + case BuildPolicy::EMPTY_PACKAGE: return NAME_EMPTY_PACKAGE; + case BuildPolicy::DLLS_WITHOUT_LIBS: return NAME_DLLS_WITHOUT_LIBS; + case BuildPolicy::ONLY_RELEASE_CRT: return NAME_ONLY_RELEASE_CRT; + case BuildPolicy::EMPTY_INCLUDE_FOLDER: return NAME_EMPTY_INCLUDE_FOLDER; + case BuildPolicy::ALLOW_OBSOLETE_MSVCRT: return NAME_ALLOW_OBSOLETE_MSVCRT; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + + CStringView to_cmake_variable(BuildPolicy policy) + { + switch (policy) + { + case BuildPolicy::EMPTY_PACKAGE: return "VCPKG_POLICY_EMPTY_PACKAGE"; + case BuildPolicy::DLLS_WITHOUT_LIBS: return "VCPKG_POLICY_DLLS_WITHOUT_LIBS"; + case BuildPolicy::ONLY_RELEASE_CRT: return "VCPKG_POLICY_ONLY_RELEASE_CRT"; + case BuildPolicy::EMPTY_INCLUDE_FOLDER: return "VCPKG_POLICY_EMPTY_INCLUDE_FOLDER"; + case BuildPolicy::ALLOW_OBSOLETE_MSVCRT: return "VCPKG_POLICY_ALLOW_OBSOLETE_MSVCRT"; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + + Optional to_linkage_type(const std::string& str) + { + if (str == "dynamic") return LinkageType::DYNAMIC; + if (str == "static") return LinkageType::STATIC; + return nullopt; + } + + namespace BuildInfoRequiredField + { + static const std::string CRT_LINKAGE = "CRTLinkage"; + static const std::string LIBRARY_LINKAGE = "LibraryLinkage"; + } + + CWStringView to_vcvarsall_target(const std::string& cmake_system_name) + { + if (cmake_system_name == Strings::EMPTY) return Strings::WEMPTY; + if (cmake_system_name == "Windows") return Strings::WEMPTY; + if (cmake_system_name == "WindowsStore") return L"store"; + + Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported vcvarsall target %s", cmake_system_name); + } + + CWStringView to_vcvarsall_toolchain(const std::string& target_architecture, const Toolset& toolset) + { + auto maybe_target_arch = System::to_cpu_architecture(target_architecture); + Checks::check_exit( + VCPKG_LINE_INFO, maybe_target_arch.has_value(), "Invalid architecture string: %s", target_architecture); + auto target_arch = maybe_target_arch.value_or_exit(VCPKG_LINE_INFO); + auto host_architectures = System::get_supported_host_architectures(); + + for (auto&& host : host_architectures) + { + auto it = Util::find_if(toolset.supported_architectures, [&](const ToolsetArchOption& opt) { + return host == opt.host_arch && target_arch == opt.target_arch; + }); + if (it != toolset.supported_architectures.end()) return it->name; + } + + Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported toolchain combination %s", target_architecture); + } + + std::wstring make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset) + { + const wchar_t* tonull = L" >nul"; + if (GlobalState::debugging) + { + tonull = Strings::WEMPTY; + } + + const auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset); + const auto target = to_vcvarsall_target(pre_build_info.cmake_system_name); + + return Strings::wformat(LR"("%s" %s %s %s %s 2>&1)", + toolset.vcvarsall.native(), + Strings::join(L" ", toolset.vcvarsall_options), + arch, + target, + tonull); + } + + static void create_binary_feature_control_file(const SourceParagraph& source_paragraph, + const FeatureParagraph& feature_paragraph, + const Triplet& triplet, + BinaryControlFile& bcf) + { + BinaryParagraph bpgh(source_paragraph, feature_paragraph, triplet); + bcf.features.emplace_back(std::move(bpgh)); + } + + static void create_binary_control_file(const SourceParagraph& source_paragraph, + const Triplet& triplet, + const BuildInfo& build_info, + BinaryControlFile& bcf) + { + BinaryParagraph bpgh(source_paragraph, triplet); + if (const auto p_ver = build_info.version.get()) + { + bpgh.version = *p_ver; + } + bcf.core_paragraph = std::move(bpgh); + } + + static void write_binary_control_file(const VcpkgPaths& paths, BinaryControlFile bcf) + { + std::string start = Strings::serialize(bcf.core_paragraph); + for (auto&& feature : bcf.features) + { + start += "\n" + Strings::serialize(feature); + } + const fs::path binary_control_file = paths.packages / bcf.core_paragraph.dir() / "CONTROL"; + paths.get_filesystem().write_contents(binary_control_file, start); + } + + ExtendedBuildResult build_package(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const StatusParagraphs& status_db) + { + const PackageSpec spec = + PackageSpec::from_name_and_triplet(config.src.name, config.triplet).value_or_exit(VCPKG_LINE_INFO); + + const Triplet& triplet = config.triplet; + { + std::vector missing_specs; + for (auto&& dep : filter_dependencies(config.src.depends, triplet)) + { + if (status_db.find_installed(dep, triplet) == status_db.end()) + { + missing_specs.push_back( + PackageSpec::from_name_and_triplet(dep, triplet).value_or_exit(VCPKG_LINE_INFO)); + } + } + // Fail the build if any dependencies were missing + if (!missing_specs.empty()) + { + return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(missing_specs)}; + } + } + + const fs::path& cmake_exe_path = paths.get_cmake_exe(); + const fs::path& git_exe_path = paths.get_git_exe(); + + const fs::path ports_cmake_script_path = paths.ports_cmake; + const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); + const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); + + std::string features; + if (GlobalState::feature_packages) + { + if (config.feature_list) + { + for (auto&& feature : *config.feature_list) + { + features.append(feature + ";"); + } + if (features.size() > 0) + { + features.pop_back(); + } + } + } + + const std::wstring cmd_launch_cmake = make_cmake_cmd( + cmake_exe_path, + ports_cmake_script_path, + { + {L"CMD", L"BUILD"}, + {L"PORT", config.src.name}, + {L"CURRENT_PORT_DIR", config.port_dir / "/."}, + {L"TARGET_TRIPLET", triplet.canonical_name()}, + {L"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, + {L"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? L"1" : L"0"}, + {L"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? L"1" : L"0"}, + {L"GIT", git_exe_path}, + {L"FEATURES", features}, + }); + + const std::wstring command = Strings::wformat(LR"(%s && %s)", cmd_set_environment, cmd_launch_cmake); + + const auto timer = Chrono::ElapsedTime::create_started(); + + const int return_code = System::cmd_execute_clean(command); + const auto buildtimeus = timer.microseconds(); + const auto spec_string = spec.to_string(); + + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_metric("buildtimeus-" + spec_string, buildtimeus); + if (return_code != 0) + { + locked_metrics->track_property("error", "build failed"); + locked_metrics->track_property("build_error", spec_string); + return {BuildResult::BUILD_FAILED, {}}; + } + } + + const BuildInfo build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); + const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); + + BinaryControlFile bcf; + + create_binary_control_file(config.src, triplet, build_info, bcf); + + if (error_count != 0) + { + return {BuildResult::POST_BUILD_CHECKS_FAILED, {}}; + } + if (GlobalState::feature_packages) + { + if (config.feature_list) + { + for (auto&& feature : *config.feature_list) + { + for (auto&& f_pgh : config.scf->feature_paragraphs) + { + if (f_pgh->name == feature) + create_binary_feature_control_file(*config.scf->core_paragraph, *f_pgh, triplet, bcf); + } + } + } + } + + write_binary_control_file(paths, bcf); + + // const fs::path port_buildtrees_dir = paths.buildtrees / spec.name; + // delete_directory(port_buildtrees_dir); + + return {BuildResult::SUCCEEDED, {}}; + } + + const std::string& to_string(const BuildResult build_result) + { + static const std::string NULLVALUE_STRING = Enums::nullvalue_to_string("vcpkg::Commands::Build::BuildResult"); + static const std::string SUCCEEDED_STRING = "SUCCEEDED"; + static const std::string BUILD_FAILED_STRING = "BUILD_FAILED"; + static const std::string FILE_CONFLICTS_STRING = "FILE_CONFLICTS"; + static const std::string POST_BUILD_CHECKS_FAILED_STRING = "POST_BUILD_CHECKS_FAILED"; + static const std::string CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING = "CASCADED_DUE_TO_MISSING_DEPENDENCIES"; + + switch (build_result) + { + case BuildResult::NULLVALUE: return NULLVALUE_STRING; + case BuildResult::SUCCEEDED: return SUCCEEDED_STRING; + case BuildResult::BUILD_FAILED: return BUILD_FAILED_STRING; + case BuildResult::POST_BUILD_CHECKS_FAILED: return POST_BUILD_CHECKS_FAILED_STRING; + case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: return CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING; + case BuildResult::FILE_CONFLICTS: return FILE_CONFLICTS_STRING; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + + std::string create_error_message(const BuildResult build_result, const PackageSpec& spec) + { + return Strings::format("Error: Building package %s failed with: %s", spec, Build::to_string(build_result)); + } + + std::string create_user_troubleshooting_message(const PackageSpec& spec) + { + return Strings::format("Please ensure you're using the latest portfiles with `.\\vcpkg update`, then\n" + "submit an issue at https://github.com/Microsoft/vcpkg/issues including:\n" + " Package: %s\n" + " Vcpkg version: %s\n" + "\n" + "Additionally, attach any relevant sections from the log files above.", + spec, + Commands::Version::version()); + } + + static BuildInfo inner_create_buildinfo(std::unordered_map pgh) + { + Parse::ParagraphParser parser(std::move(pgh)); + + BuildInfo build_info; + + { + std::string crt_linkage_as_string; + parser.required_field(BuildInfoRequiredField::CRT_LINKAGE, crt_linkage_as_string); + + auto crtlinkage = to_linkage_type(crt_linkage_as_string); + if (const auto p = crtlinkage.get()) + build_info.crt_linkage = *p; + else + Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid crt linkage type: [%s]", crt_linkage_as_string); + } + + { + std::string library_linkage_as_string; + parser.required_field(BuildInfoRequiredField::LIBRARY_LINKAGE, library_linkage_as_string); + auto liblinkage = to_linkage_type(library_linkage_as_string); + if (const auto p = liblinkage.get()) + build_info.library_linkage = *p; + else + Checks::exit_with_message( + VCPKG_LINE_INFO, "Invalid library linkage type: [%s]", library_linkage_as_string); + } + std::string version = parser.optional_field("Version"); + if (!version.empty()) build_info.version = std::move(version); + + std::map policies; + for (auto policy : G_ALL_POLICIES) + { + const auto setting = parser.optional_field(to_string(policy)); + if (setting.empty()) continue; + if (setting == "enabled") + policies.emplace(policy, true); + else if (setting == "disabled") + policies.emplace(policy, false); + else + Checks::exit_with_message( + VCPKG_LINE_INFO, "Unknown setting for policy '%s': %s", to_string(policy), setting); + } + + if (const auto err = parser.error_info("PostBuildInformation")) + { + print_error_message(err); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + build_info.policies = BuildPolicies(std::move(policies)); + + return build_info; + } + + BuildInfo read_build_info(const Files::Filesystem& fs, const fs::path& filepath) + { + const Expected> pghs = + Paragraphs::get_single_paragraph(fs, filepath); + Checks::check_exit(VCPKG_LINE_INFO, pghs.get() != nullptr, "Invalid BUILD_INFO file for package"); + return inner_create_buildinfo(*pghs.get()); + } + + PreBuildInfo PreBuildInfo::from_triplet_file(const VcpkgPaths& paths, const Triplet& triplet) + { + static constexpr CStringView FLAG_GUID = "c35112b6-d1ba-415b-aa5d-81de856ef8eb"; + + const fs::path& cmake_exe_path = paths.get_cmake_exe(); + const fs::path ports_cmake_script_path = paths.scripts / "get_triplet_environment.cmake"; + const fs::path triplet_file_path = paths.triplets / (triplet.canonical_name() + ".cmake"); + + const std::wstring cmd_launch_cmake = make_cmake_cmd(cmake_exe_path, + ports_cmake_script_path, + { + {L"CMAKE_TRIPLET_FILE", triplet_file_path}, + }); + + const std::wstring command = Strings::wformat(LR"(%s)", cmd_launch_cmake); + const auto ec_data = System::cmd_execute_and_capture_output(command); + Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0); + + const std::vector lines = Strings::split(ec_data.output, "\n"); + + PreBuildInfo pre_build_info; + + const auto e = lines.cend(); + auto cur = std::find(lines.cbegin(), e, FLAG_GUID); + if (cur != e) ++cur; + + for (; cur != e; ++cur) + { + auto&& line = *cur; + + const std::vector s = Strings::split(line, "="); + Checks::check_exit(VCPKG_LINE_INFO, + s.size() == 1 || s.size() == 2, + "Expected format is [VARIABLE_NAME=VARIABLE_VALUE], but was [%s]", + line); + + const bool variable_with_no_value = s.size() == 1; + const std::string variable_name = s.at(0); + const std::string variable_value = variable_with_no_value ? Strings::EMPTY : s.at(1); + + if (variable_name == "VCPKG_TARGET_ARCHITECTURE") + { + pre_build_info.target_architecture = variable_value; + continue; + } + + if (variable_name == "VCPKG_CMAKE_SYSTEM_NAME") + { + pre_build_info.cmake_system_name = variable_value; + continue; + } + + if (variable_name == "VCPKG_CMAKE_SYSTEM_VERSION") + { + pre_build_info.cmake_system_version = variable_value; + continue; + } + + if (variable_name == "VCPKG_PLATFORM_TOOLSET") + { + pre_build_info.platform_toolset = + variable_value.empty() ? nullopt : Optional{variable_value}; + continue; + } + + if (variable_name == "VCPKG_VISUAL_STUDIO_PATH") + { + pre_build_info.visual_studio_path = + variable_value.empty() ? nullopt : Optional{variable_value}; + continue; + } + + Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown variable name %s", line); + } + + return pre_build_info; + } +} diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp new file mode 100644 index 000000000..ad2a5b227 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp @@ -0,0 +1,78 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::Autocomplete +{ + std::vector autocomplete_install( + const std::vector>& source_paragraphs, const std::string& start_with) + { + std::vector results; + const auto& istartswith = Strings::case_insensitive_ascii_starts_with; + + for (const auto& source_control_file : source_paragraphs) + { + auto&& sp = *source_control_file->core_paragraph; + + if (istartswith(sp.name, start_with)) + { + results.push_back(sp.name); + } + } + return results; + } + + std::vector autocomplete_remove(std::vector installed_packages, + const std::string& start_with) + { + std::vector results; + const auto& istartswith = Strings::case_insensitive_ascii_starts_with; + + for (const auto& installed_package : installed_packages) + { + auto sp = installed_package->package.displayname(); + + if (istartswith(sp, start_with)) + { + results.push_back(sp); + } + } + return results; + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = Strings::format("The argument should be a command line to autocomplete.\n%s", + Help::create_example_string("autocomplete install z")); + + args.check_min_arg_count(1, EXAMPLE); + args.check_max_arg_count(2, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + + const std::string requested_command = args.command_arguments.at(0); + const std::string start_with = + args.command_arguments.size() > 1 ? args.command_arguments.at(1) : Strings::EMPTY; + std::vector results; + if (requested_command == "install") + { + auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + auto& source_paragraphs = sources_and_errors.paragraphs; + + results = autocomplete_install(source_paragraphs, start_with); + } + else if (requested_command == "remove") + { + const StatusParagraphs status_db = database_load_check(paths); + std::vector installed_packages = get_installed_ports(status_db); + results = autocomplete_remove(installed_packages, start_with); + } + + System::println(Strings::join(" ", results)); + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.buildexternal.cpp b/toolsrc/src/vcpkg/commands.buildexternal.cpp new file mode 100644 index 000000000..3991beb62 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.buildexternal.cpp @@ -0,0 +1,23 @@ +#include "pch.h" + +#include +#include +#include +#include + +namespace vcpkg::Commands::BuildExternal +{ + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + static const std::string EXAMPLE = + Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)"); + args.check_exact_arg_count(2, EXAMPLE); + const FullPackageSpec spec = + Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, EXAMPLE); + Input::check_triplet(spec.package_spec.triplet(), paths); + const std::unordered_set options = args.check_and_get_optional_command_arguments({}); + + const fs::path port_dir = args.command_arguments.at(1); + Build::Command::perform_and_exit(spec, port_dir, options, paths); + } +} diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp new file mode 100644 index 000000000..77f0a20f6 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.cache.cpp @@ -0,0 +1,69 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::Cache +{ + static std::vector read_all_binary_paragraphs(const VcpkgPaths& paths) + { + std::vector output; + for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.packages)) + { + const Expected> pghs = + Paragraphs::get_single_paragraph(paths.get_filesystem(), path / "CONTROL"); + if (const auto p = pghs.get()) + { + const BinaryParagraph binary_paragraph = BinaryParagraph(*p); + output.push_back(binary_paragraph); + } + } + + return output; + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = Strings::format( + "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s", + Help::create_example_string("cache png")); + args.check_max_arg_count(1, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + + const std::vector binary_paragraphs = read_all_binary_paragraphs(paths); + if (binary_paragraphs.empty()) + { + System::println("No packages are cached."); + Checks::exit_success(VCPKG_LINE_INFO); + } + + if (args.command_arguments.size() == 0) + { + for (const BinaryParagraph& binary_paragraph : binary_paragraphs) + { + const std::string displayname = binary_paragraph.displayname(); + System::println(displayname); + } + } + else + { + // At this point there is 1 argument + for (const BinaryParagraph& binary_paragraph : binary_paragraphs) + { + const std::string displayname = binary_paragraph.displayname(); + if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end()) + { + continue; + } + + System::println(displayname); + } + } + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp new file mode 100644 index 000000000..1c98d1d83 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -0,0 +1,62 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::CI +{ + using Build::BuildResult; + using Dependencies::InstallPlanAction; + using Dependencies::InstallPlanType; + + static std::vector load_all_package_specs(Files::Filesystem& fs, + const fs::path& ports_directory, + const Triplet& triplet) + { + auto ports = Paragraphs::load_all_ports(fs, ports_directory); + return Util::fmap(ports, [&](auto&& control_file) -> PackageSpec { + return PackageSpec::from_name_and_triplet(control_file->core_paragraph->name, triplet) + .value_or_exit(VCPKG_LINE_INFO); + }); + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + static const std::string EXAMPLE = Help::create_example_string("ci x64-windows"); + args.check_max_arg_count(1, EXAMPLE); + const Triplet triplet = args.command_arguments.size() == 1 + ? Triplet::from_canonical_name(args.command_arguments.at(0)) + : default_triplet; + Input::check_triplet(triplet, paths); + args.check_and_get_optional_command_arguments({}); + const std::vector specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet); + + StatusParagraphs status_db = database_load_check(paths); + const auto& paths_port_file = Dependencies::PathsPortFile(paths); + std::vector install_plan = + Dependencies::create_install_plan(paths_port_file, specs, status_db); + Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); + + const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; + + const std::vector action_plan = + Util::fmap(install_plan, [](InstallPlanAction& install_action) { + return Dependencies::AnyAction(std::move(install_action)); + }); + + Install::perform_and_exit_ex( + action_plan, install_plan_options, Install::KeepGoing::YES, Install::PrintSummary::YES, paths, status_db); + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.contact.cpp b/toolsrc/src/vcpkg/commands.contact.cpp new file mode 100644 index 000000000..421b8a230 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.contact.cpp @@ -0,0 +1,22 @@ +#include "pch.h" + +#include +#include + +namespace vcpkg::Commands::Contact +{ + const std::string& email() + { + static const std::string S_EMAIL = R"(vcpkg@microsoft.com)"; + return S_EMAIL; + } + + void perform_and_exit(const VcpkgCmdArguments& args) + { + args.check_exact_arg_count(0); + args.check_and_get_optional_command_arguments({}); + + System::println("Send an email to %s with any feedback.", email()); + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp new file mode 100644 index 000000000..9d969ea28 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.cpp @@ -0,0 +1,56 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Commands +{ + Span> get_available_commands_type_a() + { + static std::vector> t = { + {"install", &Install::perform_and_exit}, + {"ci", &CI::perform_and_exit}, + {"remove", &Remove::perform_and_exit}, + {"build", &Build::Command::perform_and_exit}, + {"env", &Env::perform_and_exit}, + {"build-external", &BuildExternal::perform_and_exit}, + {"export", &Export::perform_and_exit}, + }; + return t; + } + + Span> get_available_commands_type_b() + { + static std::vector> t = { + {"/?", &Help::perform_and_exit}, + {"help", &Help::perform_and_exit}, + {"search", &Search::perform_and_exit}, + {"list", &List::perform_and_exit}, + {"integrate", &Integrate::perform_and_exit}, + {"owns", &Owns::perform_and_exit}, + {"update", &Update::perform_and_exit}, + {"depend-info", &DependInfo::perform_and_exit}, + {"edit", &Edit::perform_and_exit}, + {"create", &Create::perform_and_exit}, + {"import", &Import::perform_and_exit}, + {"cache", &Cache::perform_and_exit}, + {"portsdiff", &PortsDiff::perform_and_exit}, + {"autocomplete", &Autocomplete::perform_and_exit}}; + return t; + } + + Span> get_available_commands_type_c() + { + static std::vector> t = { + {"version", &Version::perform_and_exit}, + {"contact", &Contact::perform_and_exit}, + {"hash", &Hash::perform_and_exit}, + }; + return t; + } +} diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp new file mode 100644 index 000000000..d923cf555 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.create.cpp @@ -0,0 +1,39 @@ +#include "pch.h" + +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::Create +{ + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = Help::create_example_string( + R"###(create zlib2 http://zlib.net/zlib1211.zip "zlib1211-2.zip")###"); + args.check_max_arg_count(3, EXAMPLE); + args.check_min_arg_count(2, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + const std::string port_name = args.command_arguments.at(0); + const std::string url = args.command_arguments.at(1); + + const fs::path& cmake_exe = paths.get_cmake_exe(); + + std::vector cmake_args{{L"CMD", L"CREATE"}, {L"PORT", port_name}, {L"URL", url}}; + + if (args.command_arguments.size() >= 3) + { + const std::string& zip_file_name = args.command_arguments.at(2); + Checks::check_exit(VCPKG_LINE_INFO, + !Files::has_invalid_chars_for_filesystem(zip_file_name), + R"(Filename cannot contain invalid chars %s, but was %s)", + Files::FILESYSTEM_INVALID_CHARACTERS, + zip_file_name); + cmake_args.push_back({L"FILENAME", zip_file_name}); + } + + const std::wstring cmd_launch_cmake = make_cmake_cmd(cmake_exe, paths.ports_cmake, cmake_args); + Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute_clean(cmd_launch_cmake)); + } +} diff --git a/toolsrc/src/vcpkg/commands.dependinfo.cpp b/toolsrc/src/vcpkg/commands.dependinfo.cpp new file mode 100644 index 000000000..89c7e0c7f --- /dev/null +++ b/toolsrc/src/vcpkg/commands.dependinfo.cpp @@ -0,0 +1,56 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::DependInfo +{ + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = Help::create_example_string(R"###(depend-info [pat])###"); + args.check_max_arg_count(1, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + + std::vector> source_control_files = + Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + + if (args.command_arguments.size() == 1) + { + const std::string filter = args.command_arguments.at(0); + + Util::erase_remove_if(source_control_files, + [&](const std::unique_ptr& source_control_file) { + + const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; + + if (Strings::case_insensitive_ascii_contains(source_paragraph.name, filter)) + { + return false; + } + + for (const Dependency& dependency : source_paragraph.depends) + { + if (Strings::case_insensitive_ascii_contains(dependency.name(), filter)) + { + return false; + } + } + + return true; + }); + } + + for (auto&& source_control_file : source_control_files) + { + const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; + const auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name(); }); + System::println("%s: %s", source_paragraph.name, s); + } + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp new file mode 100644 index 000000000..9497bd76e --- /dev/null +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -0,0 +1,87 @@ +#include "pch.h" + +#include +#include +#include +#include + +namespace vcpkg::Commands::Edit +{ + static std::vector find_from_registry() + { + static const std::array REGKEYS = { + LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", + LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1)", + LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", + }; + + std::vector output; + for (auto&& keypath : REGKEYS) + { + const Optional code_installpath = + System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation"); + if (const auto c = code_installpath.get()) + { + const fs::path install_path = fs::path(*c); + output.push_back(install_path / "Code - Insiders.exe"); + output.push_back(install_path / "Code.exe"); + } + } + return output; + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string OPTION_BUILDTREES = "--buildtrees"; + + static const fs::path VS_CODE_INSIDERS = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe"; + static const fs::path VS_CODE = fs::path{"Microsoft VS Code"} / "Code.exe"; + + auto& fs = paths.get_filesystem(); + + static const std::string EXAMPLE = Help::create_example_string("edit zlib"); + args.check_exact_arg_count(1, EXAMPLE); + const std::unordered_set options = + args.check_and_get_optional_command_arguments({OPTION_BUILDTREES}); + const std::string port_name = args.command_arguments.at(0); + + const fs::path portpath = paths.ports / port_name; + Checks::check_exit(VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name); + + std::vector candidate_paths; + const std::vector from_path = Files::find_from_PATH(L"EDITOR"); + candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE_INSIDERS); + candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE_INSIDERS); + candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE); + candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE); + + const std::vector from_registry = find_from_registry(); + candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend()); + + auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { return fs.exists(p); }); + if (it == candidate_paths.cend()) + { + System::println(System::Color::error, + "Error: Visual Studio Code was not found and the environment variable EDITOR is not set."); + System::println("The following paths were examined:"); + Files::print_paths(candidate_paths); + System::println("You can also set the environmental variable EDITOR to your editor of choice."); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + const fs::path env_editor = *it; + if (options.find(OPTION_BUILDTREES) != options.cend()) + { + const auto buildtrees_current_dir = paths.buildtrees / port_name; + + const std::wstring cmd_line = + Strings::wformat(LR"("%s" "%s" -n)", env_editor, buildtrees_current_dir.native()); + Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); + } + + const std::wstring cmd_line = Strings::wformat( + LR"("%s" "%s" "%s" -n)", env_editor, portpath.native(), (portpath / "portfile.cmake").native()); + Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); + } +} diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp new file mode 100644 index 000000000..089881588 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.env.cpp @@ -0,0 +1,22 @@ +#include "pch.h" + +#include +#include +#include +#include + +namespace vcpkg::Commands::Env +{ + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + static const std::string EXAMPLE = Help::create_example_string(R"(env --triplet x64-windows)"); + args.check_exact_arg_count(0, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + + const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); + System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, toolset) + L" && cmd"); + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.exportifw.cpp b/toolsrc/src/vcpkg/commands.exportifw.cpp new file mode 100644 index 000000000..35a3c97a7 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.exportifw.cpp @@ -0,0 +1,482 @@ +#include "pch.h" + +#include +#include +#include +#include + +namespace vcpkg::Export::IFW +{ + using Dependencies::ExportPlanAction; + using Dependencies::ExportPlanType; + using Install::InstallDir; + + static std::string create_release_date() + { + const tm date_time = System::get_current_date_time(); + + // Format is: YYYY-mm-dd + // 10 characters + 1 null terminating character will be written for a total of 11 chars + char mbstr[11]; + const size_t bytes_written = std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%d", &date_time); + Checks::check_exit(VCPKG_LINE_INFO, + bytes_written == 10, + "Expected 10 bytes to be written, but %u were written", + bytes_written); + const std::string date_time_as_string(mbstr); + return date_time_as_string; + } + + fs::path get_packages_dir_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_packages_dir_path.has_value() + ? fs::path(ifw_options.maybe_packages_dir_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-packages"); + } + + fs::path get_repository_dir_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_repository_dir_path.has_value() + ? fs::path(ifw_options.maybe_repository_dir_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-repository"); + } + + fs::path get_config_file_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_config_file_path.has_value() + ? fs::path(ifw_options.maybe_config_file_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-configuration.xml"); + } + + fs::path get_installer_file_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_installer_file_path.has_value() + ? fs::path(ifw_options.maybe_installer_file_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-installer.exe"); + } + + fs::path export_real_package(const fs::path& ifw_packages_dir_path, + const ExportPlanAction& action, + Files::Filesystem& fs) + { + std::error_code ec; + + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + // Prepare meta dir + const fs::path package_xml_file_path = + ifw_packages_dir_path / + Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "meta" / + "package.xml"; + const fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + auto deps = Strings::join( + ",", binary_paragraph.depends, [](const std::string& dep) { return "packages." + dep + ":"; }); + + if (!deps.empty()) deps = "\n " + deps + ""; + + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( + + %s + %s + %s + packages.%s:,triplets.%s:%s + true + +)###", + action.spec.to_string(), + binary_paragraph.version, + create_release_date(), + action.spec.name(), + action.spec.triplet().canonical_name(), + deps)); + + // Return dir path for export package data + return ifw_packages_dir_path / + Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "data" / + "installed"; + } + + void export_unique_packages(const fs::path& raw_exported_dir_path, + std::map unique_packages, + Files::Filesystem& fs) + { + std::error_code ec; + + // packages + + fs::path package_xml_file_path = raw_exported_dir_path / "packages" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( + + Packages + 1.0.0 + %s + +)###", + create_release_date())); + + for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) + { + const ExportPlanAction& action = *(package->second); + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + package_xml_file_path = + raw_exported_dir_path / Strings::format("packages.%s", package->first) / "meta" / "package.xml"; + package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( + + %s + %s + %s + %s + +)###", + action.spec.name(), + binary_paragraph.description, + binary_paragraph.version, + create_release_date())); + } + } + + void export_unique_triplets(const fs::path& raw_exported_dir_path, + std::set unique_triplets, + Files::Filesystem& fs) + { + std::error_code ec; + + // triplets + + fs::path package_xml_file_path = raw_exported_dir_path / "triplets" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( + + Triplets + 1.0.0 + %s + +)###", + create_release_date())); + + for (const std::string& triplet : unique_triplets) + { + package_xml_file_path = + raw_exported_dir_path / Strings::format("triplets.%s", triplet) / "meta" / "package.xml"; + package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( + + %s + 1.0.0 + %s + +)###", + triplet, + create_release_date())); + } + } + + void export_integration(const fs::path& raw_exported_dir_path, Files::Filesystem& fs) + { + std::error_code ec; + + // integration + fs::path package_xml_file_path = raw_exported_dir_path / "integration" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( + + Integration + 1.0.0 + %s + +)###", + create_release_date())); + } + + void export_config(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + const fs::path config_xml_file_path = get_config_file_path(export_id, ifw_options, paths); + + fs::path config_xml_dir_path = config_xml_file_path.parent_path(); + fs.create_directories(config_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for configuration file %s", + config_xml_file_path.generic_string()); + + std::string formatted_repo_url; + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) + { + formatted_repo_url = Strings::format(R"###( + + + %s + + )###", + ifw_repo_url); + } + + fs.write_contents(config_xml_file_path, + Strings::format( + R"###( + + vcpkg + 1.0.0 + vcpkg + @RootDir@/src/vcpkg%s + +)###", + formatted_repo_url)); + } + + void export_maintenance_tool(const fs::path& ifw_packages_dir_path, const VcpkgPaths& paths) + { + System::println("Exporting maintenance tool... "); + + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + const fs::path& installerbase_exe = paths.get_ifw_installerbase_exe(); + fs::path tempmaintenancetool = ifw_packages_dir_path / "maintenance" / "data" / "tempmaintenancetool.exe"; + fs.create_directories(tempmaintenancetool.parent_path(), ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + tempmaintenancetool.generic_string()); + fs.copy_file(installerbase_exe, tempmaintenancetool, fs::copy_options::overwrite_existing, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not write package file %s", tempmaintenancetool.generic_string()); + + fs::path package_xml_file_path = ifw_packages_dir_path / "maintenance" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###( + + Maintenance Tool + Maintenance Tool + 1.0.0 + %s + + true + true + true + +)###", + create_release_date())); + const fs::path script_source = paths.root / "scripts" / "ifw" / "maintenance.qs"; + const fs::path script_destination = ifw_packages_dir_path / "maintenance" / "meta" / "maintenance.qs"; + fs.copy_file(script_source, script_destination, fs::copy_options::overwrite_existing, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not write package file %s", script_destination.generic_string()); + + System::println("Exporting maintenance tool... done"); + } + + void do_repository(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + const fs::path& repogen_exe = paths.get_ifw_repogen_exe(); + const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); + const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); + + System::println("Generating repository %s...", repository_dir.generic_string()); + + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + fs.remove_all(repository_dir, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not remove outdated repository directory %s", repository_dir.generic_string()); + + const std::wstring cmd_line = Strings::wformat(LR"("%s" --packages "%s" "%s" > nul)", + repogen_exe.native(), + packages_dir.native(), + repository_dir.native()); + + const int exit_code = System::cmd_execute_clean(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW repository generating failed"); + + System::println(System::Color::success, "Generating repository %s... done.", repository_dir.generic_string()); + } + + void do_installer(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + const fs::path& binarycreator_exe = paths.get_ifw_binarycreator_exe(); + const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); + const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); + const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); + const fs::path installer_file = get_installer_file_path(export_id, ifw_options, paths); + + System::println("Generating installer %s...", installer_file.generic_string()); + + std::wstring cmd_line; + + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) + { + cmd_line = Strings::wformat(LR"("%s" --online-only --config "%s" --repository "%s" "%s" > nul)", + binarycreator_exe.native(), + config_file.native(), + repository_dir.native(), + installer_file.native()); + } + else + { + cmd_line = Strings::wformat(LR"("%s" --config "%s" --packages "%s" "%s" > nul)", + binarycreator_exe.native(), + config_file.native(), + packages_dir.native(), + installer_file.native()); + } + + const int exit_code = System::cmd_execute_clean(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW installer generating failed"); + + System::println(System::Color::success, "Generating installer %s... done.", installer_file.generic_string()); + } + + void do_export(const std::vector& export_plan, + const std::string& export_id, + const Options& ifw_options, + const VcpkgPaths& paths) + { + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + // Prepare packages directory + const fs::path ifw_packages_dir_path = get_packages_dir_path(export_id, ifw_options, paths); + + fs.remove_all(ifw_packages_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not remove outdated packages directory %s", + ifw_packages_dir_path.generic_string()); + + fs.create_directory(ifw_packages_dir_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create packages directory %s", ifw_packages_dir_path.generic_string()); + + // Export maintenance tool + export_maintenance_tool(ifw_packages_dir_path, paths); + + System::println("Exporting packages %s... ", ifw_packages_dir_path.generic_string()); + + // execute the plan + std::map unique_packages; + std::set unique_triplets; + for (const ExportPlanAction& action : export_plan) + { + if (action.plan_type != ExportPlanType::ALREADY_BUILT) + { + Checks::unreachable(VCPKG_LINE_INFO); + } + + const std::string display_name = action.spec.to_string(); + System::println("Exporting package %s... ", display_name); + + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + unique_packages[action.spec.name()] = &action; + unique_triplets.insert(action.spec.triplet().canonical_name()); + + // Export real package and return data dir for installation + fs::path ifw_package_dir_path = export_real_package(ifw_packages_dir_path, action, fs); + + // Copy package data + const InstallDir dirs = InstallDir::from_destination_root(ifw_package_dir_path, + action.spec.triplet().to_string(), + ifw_package_dir_path / "vcpkg" / "info" / + (binary_paragraph.fullstem() + ".list")); + + Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); + System::println("Exporting package %s... done", display_name); + } + + System::println("Exporting packages %s... done", ifw_packages_dir_path.generic_string()); + + const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); + + System::println("Generating configuration %s...", config_file.generic_string()); + + // Unique packages + export_unique_packages(ifw_packages_dir_path, unique_packages, fs); + + // Unique triplets + export_unique_triplets(ifw_packages_dir_path, unique_triplets, fs); + + // Copy files needed for integration + export_integration_files(ifw_packages_dir_path / "integration" / "data", paths); + // Integration + export_integration(ifw_packages_dir_path, fs); + + // Configuration + export_config(export_id, ifw_options, paths); + + System::println("Generating configuration %s... done.", config_file.generic_string()); + + // Do repository (optional) + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) + { + do_repository(export_id, ifw_options, paths); + } + + // Do installer + do_installer(export_id, ifw_options, paths); + } +} diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp new file mode 100644 index 000000000..394a02e23 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -0,0 +1,55 @@ +#include "pch.h" + +#include +#include +#include +#include + +namespace vcpkg::Commands::Hash +{ + static void do_file_hash(fs::path const& path, std::wstring const& hash_type) + { + const auto cmd_line = Strings::wformat(LR"(CertUtil.exe -hashfile "%s" %s)", path.c_str(), hash_type); + const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); + Checks::check_exit( + VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::to_utf8(cmd_line)); + + std::string const& output = ec_data.output; + + const auto start = output.find_first_of("\r\n"); + Checks::check_exit(VCPKG_LINE_INFO, + start != std::string::npos, + "Unexpected output format from command: %s", + Strings::to_utf8(cmd_line)); + + const auto end = output.find_first_of("\r\n", start + 1); + Checks::check_exit(VCPKG_LINE_INFO, + end != std::string::npos, + "Unexpected output format from command: %s", + Strings::to_utf8(cmd_line)); + + auto hash = output.substr(start, end - start); + Util::erase_remove_if(hash, isspace); + System::println(hash); + } + + void perform_and_exit(const VcpkgCmdArguments& args) + { + static const std::string EXAMPLE = Strings::format("The argument should be a file path\n%s", + Help::create_example_string("hash boost_1_62_0.tar.bz2")); + args.check_min_arg_count(1, EXAMPLE); + args.check_max_arg_count(2, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + + if (args.command_arguments.size() == 1) + { + do_file_hash(args.command_arguments[0], L"SHA512"); + } + if (args.command_arguments.size() == 2) + { + do_file_hash(args.command_arguments[0], Strings::to_utf16(args.command_arguments[1])); + } + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.import.cpp b/toolsrc/src/vcpkg/commands.import.cpp new file mode 100644 index 000000000..119aee022 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.import.cpp @@ -0,0 +1,120 @@ +#include "pch.h" + +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::Import +{ + struct Binaries + { + std::vector dlls; + std::vector libs; + }; + + static void check_is_directory(const LineInfo& line_info, const Files::Filesystem& fs, const fs::path& dirpath) + { + Checks::check_exit(line_info, fs.is_directory(dirpath), "The path %s is not a directory", dirpath.string()); + } + + static Binaries find_binaries_in_dir(const Files::Filesystem& fs, const fs::path& path) + { + auto files = fs.get_files_recursive(path); + + check_is_directory(VCPKG_LINE_INFO, fs, path); + + Binaries binaries; + for (auto&& file : files) + { + if (fs.is_directory(file)) continue; + const auto ext = file.extension(); + if (ext == ".dll") + binaries.dlls.push_back(std::move(file)); + else if (ext == ".lib") + binaries.libs.push_back(std::move(file)); + } + return binaries; + } + + static void copy_files_into_directory(Files::Filesystem& fs, + const std::vector& files, + const fs::path& destination_folder) + { + std::error_code ec; + fs.create_directory(destination_folder, ec); + + for (auto const& src_path : files) + { + const fs::path dest_path = destination_folder / src_path.filename(); + fs.copy(src_path, dest_path, fs::copy_options::overwrite_existing); + } + } + + static void place_library_files_in(Files::Filesystem& fs, + const fs::path& include_directory, + const fs::path& project_directory, + const fs::path& destination_path) + { + check_is_directory(VCPKG_LINE_INFO, fs, include_directory); + check_is_directory(VCPKG_LINE_INFO, fs, project_directory); + check_is_directory(VCPKG_LINE_INFO, fs, destination_path); + const Binaries debug_binaries = find_binaries_in_dir(fs, project_directory / "Debug"); + const Binaries release_binaries = find_binaries_in_dir(fs, project_directory / "Release"); + + const fs::path destination_include_directory = destination_path / "include"; + fs.copy(include_directory, + destination_include_directory, + fs::copy_options::recursive | fs::copy_options::overwrite_existing); + + copy_files_into_directory(fs, release_binaries.dlls, destination_path / "bin"); + copy_files_into_directory(fs, release_binaries.libs, destination_path / "lib"); + + std::error_code ec; + fs.create_directory(destination_path / "debug", ec); + copy_files_into_directory(fs, debug_binaries.dlls, destination_path / "debug" / "bin"); + copy_files_into_directory(fs, debug_binaries.libs, destination_path / "debug" / "lib"); + } + + static void do_import(const VcpkgPaths& paths, + const fs::path& include_directory, + const fs::path& project_directory, + const BinaryParagraph& control_file_data) + { + auto& fs = paths.get_filesystem(); + const fs::path library_destination_path = paths.package_dir(control_file_data.spec); + std::error_code ec; + fs.create_directory(library_destination_path, ec); + place_library_files_in(paths.get_filesystem(), include_directory, project_directory, library_destination_path); + + const fs::path control_file_path = library_destination_path / "CONTROL"; + fs.write_contents(control_file_path, Strings::serialize(control_file_data)); + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = Help::create_example_string( + R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)"); + args.check_exact_arg_count(3, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + + const fs::path control_file_path(args.command_arguments[0]); + const fs::path include_directory(args.command_arguments[1]); + const fs::path project_directory(args.command_arguments[2]); + + const Expected> pghs = + Paragraphs::get_single_paragraph(paths.get_filesystem(), control_file_path); + Checks::check_exit(VCPKG_LINE_INFO, + pghs.get() != nullptr, + "Invalid control file %s for package", + control_file_path.generic_string()); + + StatusParagraph spgh; + spgh.package = BinaryParagraph(*pghs.get()); + auto& control_file_data = spgh.package; + + do_import(paths, include_directory, project_directory, control_file_data); + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp new file mode 100644 index 000000000..7f6639222 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -0,0 +1,342 @@ +#include "pch.h" + +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::Integrate +{ + static const std::array OLD_SYSTEM_TARGET_FILES = { + System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", + System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"}; + static const fs::path SYSTEM_WIDE_TARGETS_FILE = + System::get_program_files_32_bit() / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; + + static std::string create_appdata_targets_shortcut(const std::string& target_path) noexcept + { + return Strings::format(R"###( + + + +)###", + target_path, + target_path); + } + + static std::string create_system_targets_shortcut() noexcept + { + return R"###( + + + + $(LOCALAPPDATA)\vcpkg\vcpkg.user + + + +)###"; + } + + static std::string create_nuget_targets_file_contents(const fs::path& msbuild_vcpkg_targets_file) noexcept + { + const std::string as_string = msbuild_vcpkg_targets_file.string(); + + return Strings::format(R"###( + + + + + + +)###", + as_string, + as_string); + } + + static std::string create_nuget_props_file_contents() noexcept + { + return R"###( + + + true + + +)###"; + } + + static std::string get_nuget_id(const fs::path& vcpkg_root_dir) + { + std::string dir_id = vcpkg_root_dir.generic_string(); + std::replace(dir_id.begin(), dir_id.end(), '/', '.'); + dir_id.erase(1, 1); // Erasing the ":" + + // NuGet id cannot have invalid characters. We will only use alphanumeric and dot. + Util::erase_remove_if(dir_id, [](char c) { return !isalnum(c) && (c != '.'); }); + + const std::string nuget_id = "vcpkg." + dir_id; + return nuget_id; + } + + static std::string create_nuspec_file_contents(const fs::path& vcpkg_root_dir, + const std::string& nuget_id, + const std::string& nupkg_version) + { + static constexpr auto CONTENT_TEMPLATE = R"( + + + @NUGET_ID@ + @VERSION@ + vcpkg + + This package imports all libraries currently installed in @VCPKG_DIR@. This package does not contain any libraries and instead refers to the folder directly (like a symlink). + + + + + + + +)"; + + std::string content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id); + content = std::regex_replace(content, std::regex("@VCPKG_DIR@"), vcpkg_root_dir.string()); + content = std::regex_replace(content, std::regex("@VERSION@"), nupkg_version); + return content; + } + + enum class ElevationPromptChoice + { + YES, + NO + }; + + static ElevationPromptChoice elevated_cmd_execute(const std::string& param) + { + SHELLEXECUTEINFOW sh_ex_info = {0}; + sh_ex_info.cbSize = sizeof(sh_ex_info); + sh_ex_info.fMask = SEE_MASK_NOCLOSEPROCESS; + sh_ex_info.hwnd = nullptr; + sh_ex_info.lpVerb = L"runas"; + sh_ex_info.lpFile = L"cmd"; // Application to start + + auto wparam = Strings::to_utf16(param); + sh_ex_info.lpParameters = wparam.c_str(); // Additional parameters + sh_ex_info.lpDirectory = nullptr; + sh_ex_info.nShow = SW_HIDE; + sh_ex_info.hInstApp = nullptr; + + if (!ShellExecuteExW(&sh_ex_info)) + { + return ElevationPromptChoice::NO; + } + if (sh_ex_info.hProcess == nullptr) + { + return ElevationPromptChoice::NO; + } + WaitForSingleObject(sh_ex_info.hProcess, INFINITE); + CloseHandle(sh_ex_info.hProcess); + return ElevationPromptChoice::YES; + } + + static fs::path get_appdata_targets_path() + { + static const fs::path LOCAL_APP_DATA = + fs::path(System::get_environment_variable(L"LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO)); + return LOCAL_APP_DATA / "vcpkg" / "vcpkg.user.targets"; + } + + static void integrate_install(const VcpkgPaths& paths) + { + auto& fs = paths.get_filesystem(); + + // TODO: This block of code should eventually be removed + for (auto&& old_system_wide_targets_file : OLD_SYSTEM_TARGET_FILES) + { + if (fs.exists(old_system_wide_targets_file)) + { + const std::string param = + Strings::format(R"(/c DEL "%s" /Q > nul)", old_system_wide_targets_file.string()); + const ElevationPromptChoice user_choice = elevated_cmd_execute(param); + switch (user_choice) + { + case ElevationPromptChoice::YES: break; + case ElevationPromptChoice::NO: + System::println(System::Color::warning, "Warning: Previous integration file was not removed"); + Checks::exit_fail(VCPKG_LINE_INFO); + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + } + + std::error_code ec; + const fs::path tmp_dir = paths.buildsystems / "tmp"; + fs.create_directory(paths.buildsystems, ec); + fs.create_directory(tmp_dir, ec); + + bool should_install_system = true; + const Expected system_wide_file_contents = fs.read_contents(SYSTEM_WIDE_TARGETS_FILE); + static const std::regex RE(R"###()###"); + if (const auto contents_data = system_wide_file_contents.get()) + { + std::match_results match; + const auto found = std::regex_search(*contents_data, match, RE); + if (found) + { + const int ver = atoi(match[1].str().c_str()); + if (ver >= 1) should_install_system = false; + } + } + + if (should_install_system) + { + const fs::path sys_src_path = tmp_dir / "vcpkg.system.targets"; + fs.write_contents(sys_src_path, create_system_targets_shortcut()); + + const std::string param = Strings::format(R"(/c mkdir "%s" & copy "%s" "%s" /Y > nul)", + SYSTEM_WIDE_TARGETS_FILE.parent_path().string(), + sys_src_path.string(), + SYSTEM_WIDE_TARGETS_FILE.string()); + const ElevationPromptChoice user_choice = elevated_cmd_execute(param); + switch (user_choice) + { + case ElevationPromptChoice::YES: break; + case ElevationPromptChoice::NO: + System::println(System::Color::warning, "Warning: integration was not applied"); + Checks::exit_fail(VCPKG_LINE_INFO); + default: Checks::unreachable(VCPKG_LINE_INFO); + } + + Checks::check_exit(VCPKG_LINE_INFO, + fs.exists(SYSTEM_WIDE_TARGETS_FILE), + "Error: failed to copy targets file to %s", + SYSTEM_WIDE_TARGETS_FILE.string()); + } + + const fs::path appdata_src_path = tmp_dir / "vcpkg.user.targets"; + fs.write_contents(appdata_src_path, + create_appdata_targets_shortcut(paths.buildsystems_msbuild_targets.string())); + auto appdata_dst_path = get_appdata_targets_path(); + + const auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec); + + if (!rc || ec) + { + System::println(System::Color::error, + "Error: Failed to copy file: %s -> %s", + appdata_src_path.string(), + appdata_dst_path.string()); + Checks::exit_fail(VCPKG_LINE_INFO); + } + System::println(System::Color::success, "Applied user-wide integration for this vcpkg root."); + const fs::path cmake_toolchain = paths.buildsystems / "vcpkg.cmake"; + System::println("\n" + "All MSBuild C++ projects can now #include any installed libraries.\n" + "Linking will be handled automatically.\n" + "Installing new libraries will make them instantly available.\n" + "\n" + "CMake projects should use -DCMAKE_TOOLCHAIN_FILE=%s", + cmake_toolchain.generic_string()); + + Checks::exit_success(VCPKG_LINE_INFO); + } + + static void integrate_remove(Files::Filesystem& fs) + { + const fs::path path = get_appdata_targets_path(); + + std::error_code ec; + const bool was_deleted = fs.remove(path, ec); + + Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %d", ec.message()); + + if (was_deleted) + { + System::println(System::Color::success, "User-wide integration was removed"); + } + else + { + System::println(System::Color::success, "User-wide integration is not installed"); + } + + Checks::exit_success(VCPKG_LINE_INFO); + } + + static void integrate_project(const VcpkgPaths& paths) + { + auto& fs = paths.get_filesystem(); + + const fs::path& nuget_exe = paths.get_nuget_exe(); + + const fs::path& buildsystems_dir = paths.buildsystems; + const fs::path tmp_dir = buildsystems_dir / "tmp"; + std::error_code ec; + fs.create_directory(buildsystems_dir, ec); + fs.create_directory(tmp_dir, ec); + + const fs::path targets_file_path = tmp_dir / "vcpkg.nuget.targets"; + const fs::path props_file_path = tmp_dir / "vcpkg.nuget.props"; + const fs::path nuspec_file_path = tmp_dir / "vcpkg.nuget.nuspec"; + const std::string nuget_id = get_nuget_id(paths.root); + const std::string nupkg_version = "1.0.0"; + + fs.write_contents(targets_file_path, create_nuget_targets_file_contents(paths.buildsystems_msbuild_targets)); + fs.write_contents(props_file_path, create_nuget_props_file_contents()); + fs.write_contents(nuspec_file_path, create_nuspec_file_contents(paths.root, nuget_id, nupkg_version)); + + // Using all forward slashes for the command line + const std::wstring cmd_line = Strings::wformat(LR"("%s" pack -OutputDirectory "%s" "%s" > nul)", + nuget_exe.native(), + buildsystems_dir.native(), + nuspec_file_path.native()); + + const int exit_code = System::cmd_execute_clean(cmd_line); + + const fs::path nuget_package = buildsystems_dir / Strings::format("%s.%s.nupkg", nuget_id, nupkg_version); + Checks::check_exit( + VCPKG_LINE_INFO, exit_code == 0 && fs.exists(nuget_package), "Error: NuGet package creation failed"); + System::println(System::Color::success, "Created nupkg: %s", nuget_package.string()); + + auto source_path = buildsystems_dir.u8string(); + source_path = std::regex_replace(source_path, std::regex("`"), "``"); + + System::println(R"( +With a project open, go to Tools->NuGet Package Manager->Package Manager Console and paste: + Install-Package %s -Source "%s" +)", + nuget_id, + source_path); + + Checks::exit_success(VCPKG_LINE_INFO); + } + + const char* const INTEGRATE_COMMAND_HELPSTRING = + " vcpkg integrate install Make installed packages available user-wide. Requires admin privileges on " + "first use\n" + " vcpkg integrate remove Remove user-wide integration\n" + " vcpkg integrate project Generate a referencing nuget package for individual VS project use\n"; + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = Strings::format("Commands:\n" + "%s", + INTEGRATE_COMMAND_HELPSTRING); + args.check_exact_arg_count(1, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + + if (args.command_arguments[0] == "install") + { + return integrate_install(paths); + } + if (args.command_arguments[0] == "remove") + { + return integrate_remove(paths.get_filesystem()); + } + if (args.command_arguments[0] == "project") + { + return integrate_project(paths); + } + + Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown parameter %s for integrate", args.command_arguments[0]); + } +} diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp new file mode 100644 index 000000000..d0e8e00b4 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.list.cpp @@ -0,0 +1,75 @@ +#include "pch.h" + +#include +#include +#include +#include + +namespace vcpkg::Commands::List +{ + static const std::string OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually + + static void do_print(const StatusParagraph& pgh, bool full_desc) + { + if (full_desc) + { + System::println("%-30s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description); + } + else + { + System::println("%-30s %-16s %s", + vcpkg::shorten_text(pgh.package.displayname(), 30), + vcpkg::shorten_text(pgh.package.version, 16), + vcpkg::shorten_text(pgh.package.description, 71)); + } + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = Strings::format( + "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", + Help::create_example_string("list png")); + args.check_max_arg_count(1, EXAMPLE); + const std::unordered_set options = + args.check_and_get_optional_command_arguments({OPTION_FULLDESC}); + + const StatusParagraphs status_paragraphs = database_load_check(paths); + std::vector installed_packages = get_installed_ports(status_paragraphs); + + if (installed_packages.empty()) + { + System::println("No packages are installed. Did you mean `search`?"); + Checks::exit_success(VCPKG_LINE_INFO); + } + + std::sort(installed_packages.begin(), + installed_packages.end(), + [](const StatusParagraph* lhs, const StatusParagraph* rhs) -> bool { + return lhs->package.displayname() < rhs->package.displayname(); + }); + + if (args.command_arguments.size() == 0) + { + for (const StatusParagraph* status_paragraph : installed_packages) + { + do_print(*status_paragraph, options.find(OPTION_FULLDESC) != options.cend()); + } + } + else + { + // At this point there is 1 argument + for (const StatusParagraph* status_paragraph : installed_packages) + { + const std::string displayname = status_paragraph->package.displayname(); + if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end()) + { + continue; + } + + do_print(*status_paragraph, options.find(OPTION_FULLDESC) != options.cend()); + } + } + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.owns.cpp b/toolsrc/src/vcpkg/commands.owns.cpp new file mode 100644 index 000000000..69079e829 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.owns.cpp @@ -0,0 +1,38 @@ +#include "pch.h" + +#include +#include +#include +#include + +namespace vcpkg::Commands::Owns +{ + static void search_file(const VcpkgPaths& paths, const std::string& file_substr, const StatusParagraphs& status_db) + { + const std::vector installed_files = get_installed_files(paths, status_db); + for (const StatusParagraphAndAssociatedFiles& pgh_and_file : installed_files) + { + const StatusParagraph& pgh = pgh_and_file.pgh; + + for (const std::string& file : pgh_and_file.files) + { + if (file.find(file_substr) != std::string::npos) + { + System::println("%s: %s", pgh.package.displayname(), file); + } + } + } + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = Strings::format("The argument should be a pattern to search for. %s", + Help::create_example_string("owns zlib.dll")); + args.check_exact_arg_count(1, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + + StatusParagraphs status_db = database_load_check(paths); + search_file(paths, args.command_arguments[0], status_db); + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp new file mode 100644 index 000000000..b70ad2b80 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp @@ -0,0 +1,182 @@ +#include "pch.h" + +#include +#include +#include + +#include +#include +#include + +namespace vcpkg::Commands::PortsDiff +{ + struct UpdatedPort + { + static bool compare_by_name(const UpdatedPort& left, const UpdatedPort& right) + { + return left.port < right.port; + } + + std::string port; + VersionDiff version_diff; + }; + + template + struct SetElementPresence + { + static SetElementPresence create(std::vector left, std::vector right) + { + // TODO: This can be done with one pass instead of three passes + SetElementPresence output; + std::set_difference( + left.cbegin(), left.cend(), right.cbegin(), right.cend(), std::back_inserter(output.only_left)); + std::set_intersection( + left.cbegin(), left.cend(), right.cbegin(), right.cend(), std::back_inserter(output.both)); + std::set_difference( + right.cbegin(), right.cend(), left.cbegin(), left.cend(), std::back_inserter(output.only_right)); + + return output; + } + + std::vector only_left; + std::vector both; + std::vector only_right; + }; + + static std::vector find_updated_ports( + const std::vector& ports, + const std::map& previous_names_and_versions, + const std::map& current_names_and_versions) + { + std::vector output; + for (const std::string& name : ports) + { + const VersionT& previous_version = previous_names_and_versions.at(name); + const VersionT& current_version = current_names_and_versions.at(name); + if (previous_version == current_version) + { + continue; + } + + output.push_back({name, VersionDiff(previous_version, current_version)}); + } + + return output; + } + + static void do_print_name_and_version(const std::vector& ports_to_print, + const std::map& names_and_versions) + { + for (const std::string& name : ports_to_print) + { + const VersionT& version = names_and_versions.at(name); + System::println(" - %-14s %-16s", name, version); + } + } + + static std::map read_ports_from_commit(const VcpkgPaths& paths, + const std::wstring& git_commit_id) + { + std::error_code ec; + auto& fs = paths.get_filesystem(); + const fs::path& git_exe = paths.get_git_exe(); + const fs::path dot_git_dir = paths.root / ".git"; + const std::wstring ports_dir_name_as_string = paths.ports.filename().native(); + const fs::path temp_checkout_path = + paths.root / Strings::wformat(L"%s-%s", ports_dir_name_as_string, git_commit_id); + fs.create_directory(temp_checkout_path, ec); + const std::wstring checkout_this_dir = + Strings::wformat(LR"(.\%s)", ports_dir_name_as_string); // Must be relative to the root of the repository + + const std::wstring cmd = + Strings::wformat(LR"("%s" --git-dir="%s" --work-tree="%s" checkout %s -f -q -- %s %s & "%s" reset >NUL)", + git_exe.native(), + dot_git_dir.native(), + temp_checkout_path.native(), + git_commit_id, + checkout_this_dir, + L".vcpkg-root", + git_exe.native()); + System::cmd_execute_clean(cmd); + const std::map names_and_versions = Paragraphs::load_all_port_names_and_versions( + paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); + fs.remove_all(temp_checkout_path, ec); + return names_and_versions; + } + + static void check_commit_exists(const fs::path& git_exe, const std::wstring& git_commit_id) + { + static const std::string VALID_COMMIT_OUTPUT = "commit\n"; + + const std::wstring cmd = Strings::wformat(LR"("%s" cat-file -t %s)", git_exe.native(), git_commit_id); + const System::ExitCodeAndOutput output = System::cmd_execute_and_capture_output(cmd); + Checks::check_exit(VCPKG_LINE_INFO, + output.output == VALID_COMMIT_OUTPUT, + "Invalid commit id %s", + Strings::to_utf8(git_commit_id)); + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = Strings::format("The argument should be a branch/tag/hash to checkout.\n%s", + Help::create_example_string("portsdiff mybranchname")); + args.check_min_arg_count(1, EXAMPLE); + args.check_max_arg_count(2, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + + const fs::path& git_exe = paths.get_git_exe(); + + const std::wstring git_commit_id_for_previous_snapshot = Strings::to_utf16(args.command_arguments.at(0)); + const std::wstring git_commit_id_for_current_snapshot = + args.command_arguments.size() < 2 ? L"HEAD" : Strings::to_utf16(args.command_arguments.at(1)); + + check_commit_exists(git_exe, git_commit_id_for_current_snapshot); + check_commit_exists(git_exe, git_commit_id_for_previous_snapshot); + + const std::map current_names_and_versions = + read_ports_from_commit(paths, git_commit_id_for_current_snapshot); + const std::map previous_names_and_versions = + read_ports_from_commit(paths, git_commit_id_for_previous_snapshot); + + // Already sorted, so set_difference can work on std::vector too + const std::vector current_ports = Util::extract_keys(current_names_and_versions); + const std::vector previous_ports = Util::extract_keys(previous_names_and_versions); + + const SetElementPresence setp = + SetElementPresence::create(current_ports, previous_ports); + + const std::vector& added_ports = setp.only_left; + if (!added_ports.empty()) + { + System::println("\nThe following %d ports were added:", added_ports.size()); + do_print_name_and_version(added_ports, current_names_and_versions); + } + + const std::vector& removed_ports = setp.only_right; + if (!removed_ports.empty()) + { + System::println("\nThe following %d ports were removed:", removed_ports.size()); + do_print_name_and_version(removed_ports, previous_names_and_versions); + } + + const std::vector& common_ports = setp.both; + const std::vector updated_ports = + find_updated_ports(common_ports, previous_names_and_versions, current_names_and_versions); + + if (!updated_ports.empty()) + { + System::println("\nThe following %d ports were updated:", updated_ports.size()); + for (const UpdatedPort& p : updated_ports) + { + System::println(" - %-14s %-16s", p.port, p.version_diff.to_string()); + } + } + + if (added_ports.empty() && removed_ports.empty() && updated_ports.empty()) + { + System::println("There were no changes in the ports between the two commits."); + } + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.search.cpp b/toolsrc/src/vcpkg/commands.search.cpp new file mode 100644 index 000000000..3ba8707de --- /dev/null +++ b/toolsrc/src/vcpkg/commands.search.cpp @@ -0,0 +1,146 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::Search +{ + static const std::string OPTION_GRAPH = "--graph"; // TODO: This should find a better home, eventually + static const std::string OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually + + static std::string replace_dashes_with_underscore(const std::string& input) + { + std::string output = input; + std::replace(output.begin(), output.end(), '-', '_'); + return output; + } + + static std::string create_graph_as_string( + const std::vector>& source_control_files) + { + int empty_node_count = 0; + + std::string s; + s.append("digraph G{ rankdir=LR; edge [minlen=3]; overlap=false;"); + + for (const auto& source_control_file : source_control_files) + { + const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; + if (source_paragraph.depends.empty()) + { + empty_node_count++; + continue; + } + + const std::string name = replace_dashes_with_underscore(source_paragraph.name); + s.append(Strings::format("%s;", name)); + for (const Dependency& d : source_paragraph.depends) + { + const std::string dependency_name = replace_dashes_with_underscore(d.name()); + s.append(Strings::format("%s -> %s;", name, dependency_name)); + } + } + + s.append(Strings::format("empty [label=\"%d singletons...\"]; }", empty_node_count)); + return s; + } + static void do_print(const SourceParagraph& source_paragraph, bool full_desc) + { + if (full_desc) + { + System::println( + "%-20s %-16s %s", source_paragraph.name, source_paragraph.version, source_paragraph.description); + } + else + { + System::println("%-20s %-16s %s", + vcpkg::shorten_text(source_paragraph.name, 20), + vcpkg::shorten_text(source_paragraph.version, 16), + vcpkg::shorten_text(source_paragraph.description, 81)); + } + } + + static void do_print(const std::string& name, const FeatureParagraph& feature_paragraph, bool full_desc) + { + if (full_desc) + { + System::println("%-37s %s", name + "[" + feature_paragraph.name + "]", feature_paragraph.description); + } + else + { + System::println("%-37s %s", + vcpkg::shorten_text(name + "[" + feature_paragraph.name + "]", 37), + vcpkg::shorten_text(feature_paragraph.description, 81)); + } + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = Strings::format( + "The argument should be a substring to search for, or no argument to display all libraries.\n%s", + Help::create_example_string("search png")); + args.check_max_arg_count(1, EXAMPLE); + const std::unordered_set options = + args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC}); + + auto source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + + if (options.find(OPTION_GRAPH) != options.cend()) + { + const std::string graph_as_string = create_graph_as_string(source_paragraphs); + System::println(graph_as_string); + Checks::exit_success(VCPKG_LINE_INFO); + } + + if (args.command_arguments.empty()) + { + for (const auto& source_control_file : source_paragraphs) + { + do_print(*source_control_file->core_paragraph, options.find(OPTION_FULLDESC) != options.cend()); + for (auto&& feature_paragraph : source_control_file->feature_paragraphs) + { + do_print(source_control_file->core_paragraph->name, + *feature_paragraph, + options.find(OPTION_FULLDESC) != options.cend()); + } + } + } + else + { + const auto& icontains = Strings::case_insensitive_ascii_contains; + + // At this point there is 1 argument + auto&& args_zero = args.command_arguments[0]; + for (const auto& source_control_file : source_paragraphs) + { + auto&& sp = *source_control_file->core_paragraph; + + bool contains_name = icontains(sp.name, args_zero); + if (contains_name || icontains(sp.description, args_zero)) + { + do_print(sp, options.find(OPTION_FULLDESC) != options.cend()); + } + + for (auto&& feature_paragraph : source_control_file->feature_paragraphs) + { + if (contains_name || icontains(feature_paragraph->name, args_zero) || + icontains(feature_paragraph->description, args_zero)) + { + do_print(sp.name, *feature_paragraph, options.find(OPTION_FULLDESC) != options.cend()); + } + } + } + } + + System::println( + "\nIf your library is not listed, please open an issue at and/or consider making a pull request:\n" + " https://github.com/Microsoft/vcpkg/issues"); + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.version.cpp b/toolsrc/src/vcpkg/commands.version.cpp new file mode 100644 index 000000000..c6cc82d1f --- /dev/null +++ b/toolsrc/src/vcpkg/commands.version.cpp @@ -0,0 +1,67 @@ +#include "pch.h" + +#include +#include +#include + +#define STRINGIFY(...) #__VA_ARGS__ +#define MACRO_TO_STRING(X) STRINGIFY(X) + +#define VCPKG_VERSION_AS_STRING MACRO_TO_STRING(VCPKG_VERSION) + +namespace vcpkg::Commands::Version +{ + const std::string& version() + { + static const std::string S_VERSION = +#include "../VERSION.txt" + + +std::string(VCPKG_VERSION_AS_STRING) +#ifndef NDEBUG + + std::string("-debug") +#endif + + std::string(Metrics::get_compiled_metrics_enabled() ? Strings::EMPTY : "-external"); + return S_VERSION; + } + + void warn_if_vcpkg_version_mismatch(const VcpkgPaths& paths) + { + auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt"); + if (const auto version_contents = version_file.get()) + { + int maj1, min1, rev1; + const auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1); + + int maj2, min2, rev2; + const auto num2 = sscanf_s(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2); + + if (num1 == 3 && num2 == 3) + { + if (maj1 != maj2 || min1 != min2 || rev1 != rev2) + { + System::println(System::Color::warning, + "Warning: Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use " + ".\\bootstrap-vcpkg.bat to update.", + maj2, + min2, + rev2, + maj1, + min1, + rev1); + } + } + } + } + + void perform_and_exit(const VcpkgCmdArguments& args) + { + args.check_exact_arg_count(0); + args.check_and_get_optional_command_arguments({}); + + System::println("Vcpkg package management program version %s\n" + "\n" + "See LICENSE.txt for license information.", + version()); + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp new file mode 100644 index 000000000..da8f1e178 --- /dev/null +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -0,0 +1,669 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Dependencies +{ + struct FeatureNodeEdges + { + std::vector remove_edges; + std::vector build_edges; + bool plus = false; + }; + + struct Cluster : Util::MoveOnlyBase + { + std::vector status_paragraphs; + Optional source_control_file; + PackageSpec spec; + std::unordered_map edges; + std::unordered_set to_install_features; + std::unordered_set original_features; + bool will_remove = false; + bool transient_uninstalled = true; + RequestType request_type = RequestType::AUTO_SELECTED; + }; + + struct ClusterPtr + { + Cluster* ptr; + + Cluster* operator->() const { return ptr; } + }; + + bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } +} + +template<> +struct std::hash +{ + size_t operator()(const vcpkg::Dependencies::ClusterPtr& value) const + { + return std::hash()(value.ptr->spec); + } +}; + +namespace vcpkg::Dependencies +{ + struct GraphPlan + { + Graphs::Graph remove_graph; + Graphs::Graph install_graph; + }; + + struct ClusterGraph : Util::MoveOnlyBase + { + explicit ClusterGraph(std::unordered_map&& ports) + : m_ports(std::move(ports)) + { + } + + Cluster& get(const PackageSpec& spec) + { + auto it = m_graph.find(spec); + if (it == m_graph.end()) + { + // Load on-demand from m_ports + auto it_ports = m_ports.find(spec.name()); + if (it_ports != m_ports.end()) + { + auto& clust = m_graph[spec]; + clust.spec = spec; + cluster_from_scf(*it_ports->second, clust); + return clust; + } + return m_graph[spec]; + } + return it->second; + } + + private: + void cluster_from_scf(const SourceControlFile& scf, Cluster& out_cluster) const + { + FeatureNodeEdges core_dependencies; + core_dependencies.build_edges = + filter_dependencies_to_specs(scf.core_paragraph->depends, out_cluster.spec.triplet()); + out_cluster.edges.emplace("core", std::move(core_dependencies)); + + for (const auto& feature : scf.feature_paragraphs) + { + FeatureNodeEdges added_edges; + added_edges.build_edges = filter_dependencies_to_specs(feature->depends, out_cluster.spec.triplet()); + out_cluster.edges.emplace(feature->name, std::move(added_edges)); + } + out_cluster.source_control_file = &scf; + } + + std::unordered_map m_graph; + std::unordered_map m_ports; + }; + + std::vector AnyParagraph::dependencies(const Triplet& triplet) const + { + auto to_package_specs = [&](const std::vector& dependencies_as_string) { + return Util::fmap(dependencies_as_string, [&](const std::string s) { + return PackageSpec::from_name_and_triplet(s, triplet).value_or_exit(VCPKG_LINE_INFO); + }); + }; + + if (auto p = this->status_paragraph.get()) + { + return to_package_specs(p->package.depends); + } + + if (auto p = this->binary_control_file.get()) + { + auto deps = Util::fmap_flatten(p->features, [](const BinaryParagraph& pgh) { return pgh.depends; }); + deps.insert(deps.end(), p->core_paragraph.depends.begin(), p->core_paragraph.depends.end()); + return to_package_specs(deps); + } + + if (auto p = this->source_paragraph.get()) + { + return to_package_specs(filter_dependencies(p->depends, triplet)); + } + + Checks::exit_with_message(VCPKG_LINE_INFO, + "Cannot get dependencies because there was none of: source/binary/status paragraphs"); + } + + std::string to_output_string(RequestType request_type, const CStringView s) + { + switch (request_type) + { + case RequestType::AUTO_SELECTED: return Strings::format(" * %s", s); + case RequestType::USER_REQUESTED: return Strings::format(" %s", s); + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + + InstallPlanAction::InstallPlanAction() : plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} + + InstallPlanAction::InstallPlanAction(const PackageSpec& spec, + const SourceControlFile& any_paragraph, + const std::unordered_set& features, + const RequestType& request_type) + : spec(spec), plan_type(InstallPlanType::BUILD_AND_INSTALL), request_type(request_type), feature_list(features) + { + this->any_paragraph.source_control_file = &any_paragraph; + } + + InstallPlanAction::InstallPlanAction(const PackageSpec& spec, + const std::unordered_set& features, + const RequestType& request_type) + : spec(spec), plan_type(InstallPlanType::ALREADY_INSTALLED), request_type(request_type), feature_list(features) + { + } + + InstallPlanAction::InstallPlanAction(const PackageSpec& spec, + const AnyParagraph& any_paragraph, + const RequestType& request_type) + : spec(spec), any_paragraph(any_paragraph), plan_type(InstallPlanType::UNKNOWN), request_type(request_type) + { + if (auto p = any_paragraph.status_paragraph.get()) + { + this->plan_type = InstallPlanType::ALREADY_INSTALLED; + return; + } + + if (auto p = any_paragraph.binary_control_file.get()) + { + this->plan_type = InstallPlanType::INSTALL; + return; + } + + if (auto p = any_paragraph.source_paragraph.get()) + { + this->plan_type = InstallPlanType::BUILD_AND_INSTALL; + return; + } + } + + std::string InstallPlanAction::displayname() const + { + if (this->feature_list.empty()) + { + return this->spec.to_string(); + } + + const std::string features = Strings::join(",", this->feature_list); + return Strings::format("%s[%s]:%s", this->spec.name(), features, this->spec.triplet()); + } + + bool InstallPlanAction::compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right) + { + return left->spec.name() < right->spec.name(); + } + + RemovePlanAction::RemovePlanAction() : plan_type(RemovePlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} + + RemovePlanAction::RemovePlanAction(const PackageSpec& spec, + const RemovePlanType& plan_type, + const RequestType& request_type) + : spec(spec), plan_type(plan_type), request_type(request_type) + { + } + + const PackageSpec& AnyAction::spec() const + { + if (const auto p = install_plan.get()) + { + return p->spec; + } + + if (const auto p = remove_plan.get()) + { + return p->spec; + } + + Checks::exit_with_message(VCPKG_LINE_INFO, "Null action"); + } + + bool ExportPlanAction::compare_by_name(const ExportPlanAction* left, const ExportPlanAction* right) + { + return left->spec.name() < right->spec.name(); + } + + ExportPlanAction::ExportPlanAction() : plan_type(ExportPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} + + ExportPlanAction::ExportPlanAction(const PackageSpec& spec, + const AnyParagraph& any_paragraph, + const RequestType& request_type) + : spec(spec), any_paragraph(any_paragraph), plan_type(ExportPlanType::UNKNOWN), request_type(request_type) + { + if (auto p = any_paragraph.binary_control_file.get()) + { + this->plan_type = ExportPlanType::ALREADY_BUILT; + return; + } + + if (auto p = any_paragraph.source_paragraph.get()) + { + this->plan_type = ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT; + return; + } + } + + bool RemovePlanAction::compare_by_name(const RemovePlanAction* left, const RemovePlanAction* right) + { + return left->spec.name() < right->spec.name(); + } + + MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map) {} + + const SourceControlFile& MapPortFile::get_control_file(const std::string& spec) const + { + auto scf = ports.find(spec); + if (scf == ports.end()) + { + Checks::exit_fail(VCPKG_LINE_INFO); + } + return scf->second; + } + + PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths) {} + + const SourceControlFile& PathsPortFile::get_control_file(const std::string& spec) const + { + auto cache_it = cache.find(spec); + if (cache_it != cache.end()) + { + return cache_it->second; + } + Parse::ParseExpected source_control_file = + Paragraphs::try_load_port(ports.get_filesystem(), ports.port_dir(spec)); + + if (auto scf = source_control_file.get()) + { + auto it = cache.emplace(spec, std::move(*scf->get())); + return it.first->second; + } + print_error_message(source_control_file.error()); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + std::vector create_install_plan(const PortFileProvider& port_file_provider, + const std::vector& specs, + const StatusParagraphs& status_db) + { + struct InstallAdjacencyProvider final : Graphs::AdjacencyProvider + { + const PortFileProvider& port_file_provider; + const StatusParagraphs& status_db; + const std::unordered_set& specs_as_set; + + InstallAdjacencyProvider(const PortFileProvider& port_file_provider, + const StatusParagraphs& s, + const std::unordered_set& specs_as_set) + : port_file_provider(port_file_provider), status_db(s), specs_as_set(specs_as_set) + { + } + + std::vector adjacency_list(const InstallPlanAction& plan) const override + { + if (plan.any_paragraph.status_paragraph.get()) return std::vector{}; + return plan.any_paragraph.dependencies(plan.spec.triplet()); + } + + InstallPlanAction load_vertex_data(const PackageSpec& spec) const override + { + const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() + ? RequestType::USER_REQUESTED + : RequestType::AUTO_SELECTED; + auto it = status_db.find_installed(spec); + if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type}; + return InstallPlanAction{ + spec, + {nullopt, nullopt, *port_file_provider.get_control_file(spec.name()).core_paragraph}, + request_type}; + } + }; + + const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); + std::vector toposort = + Graphs::topological_sort(specs, InstallAdjacencyProvider{port_file_provider, status_db, specs_as_set}); + Util::erase_remove_if(toposort, [](const InstallPlanAction& plan) { + return plan.request_type == RequestType::AUTO_SELECTED && + plan.plan_type == InstallPlanType::ALREADY_INSTALLED; + }); + + return toposort; + } + + std::vector create_remove_plan(const std::vector& specs, + const StatusParagraphs& status_db) + { + struct RemoveAdjacencyProvider final : Graphs::AdjacencyProvider + { + const StatusParagraphs& status_db; + const std::vector& installed_ports; + const std::unordered_set& specs_as_set; + + RemoveAdjacencyProvider(const StatusParagraphs& status_db, + const std::vector& installed_ports, + const std::unordered_set& specs_as_set) + : status_db(status_db), installed_ports(installed_ports), specs_as_set(specs_as_set) + { + } + + std::vector adjacency_list(const RemovePlanAction& plan) const override + { + if (plan.plan_type == RemovePlanType::NOT_INSTALLED) + { + return {}; + } + + const PackageSpec& spec = plan.spec; + std::vector dependents; + for (const StatusParagraph* an_installed_package : installed_ports) + { + if (an_installed_package->package.spec.triplet() != spec.triplet()) continue; + + const std::vector& deps = an_installed_package->package.depends; + if (std::find(deps.begin(), deps.end(), spec.name()) == deps.end()) continue; + + dependents.push_back(an_installed_package->package.spec); + } + + return dependents; + } + + RemovePlanAction load_vertex_data(const PackageSpec& spec) const override + { + const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() + ? RequestType::USER_REQUESTED + : RequestType::AUTO_SELECTED; + const StatusParagraphs::const_iterator it = status_db.find_installed(spec); + if (it == status_db.end()) + { + return RemovePlanAction{spec, RemovePlanType::NOT_INSTALLED, request_type}; + } + return RemovePlanAction{spec, RemovePlanType::REMOVE, request_type}; + } + }; + + const std::vector& installed_ports = get_installed_ports(status_db); + const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); + return Graphs::topological_sort(specs, RemoveAdjacencyProvider{status_db, installed_ports, specs_as_set}); + } + + std::vector create_export_plan(const VcpkgPaths& paths, + const std::vector& specs, + const StatusParagraphs& status_db) + { + struct ExportAdjacencyProvider final : Graphs::AdjacencyProvider + { + const VcpkgPaths& paths; + const StatusParagraphs& status_db; + const std::unordered_set& specs_as_set; + + ExportAdjacencyProvider(const VcpkgPaths& p, + const StatusParagraphs& s, + const std::unordered_set& specs_as_set) + : paths(p), status_db(s), specs_as_set(specs_as_set) + { + } + + std::vector adjacency_list(const ExportPlanAction& plan) const override + { + return plan.any_paragraph.dependencies(plan.spec.triplet()); + } + + ExportPlanAction load_vertex_data(const PackageSpec& spec) const override + { + const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() + ? RequestType::USER_REQUESTED + : RequestType::AUTO_SELECTED; + + Expected maybe_bpgh = Paragraphs::try_load_cached_control_package(paths, spec); + if (auto bcf = maybe_bpgh.get()) + return ExportPlanAction{spec, AnyParagraph{nullopt, std::move(*bcf), nullopt}, request_type}; + + auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); + if (auto scf = maybe_scf.get()) + return ExportPlanAction{spec, {nullopt, nullopt, *scf->get()->core_paragraph}, request_type}; + else + print_error_message(maybe_scf.error()); + + Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); + } + }; + + const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); + std::vector toposort = + Graphs::topological_sort(specs, ExportAdjacencyProvider{paths, status_db, specs_as_set}); + return toposort; + } + + enum class MarkPlusResult + { + FEATURE_NOT_FOUND, + SUCCESS, + }; + + MarkPlusResult mark_plus(const std::string& feature, + Cluster& cluster, + ClusterGraph& pkg_to_cluster, + GraphPlan& graph_plan); + void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + + MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) + { + if (feature.empty()) + { + // Indicates that core was not specified in the reference + return mark_plus("core", cluster, graph, graph_plan); + } + + auto it = cluster.edges.find(feature); + if (it == cluster.edges.end()) return MarkPlusResult::FEATURE_NOT_FOUND; + + if (cluster.edges[feature].plus) return MarkPlusResult::SUCCESS; + + if (cluster.original_features.find(feature) == cluster.original_features.end()) + { + cluster.transient_uninstalled = true; + } + + if (!cluster.transient_uninstalled) + { + return MarkPlusResult::SUCCESS; + } + cluster.edges[feature].plus = true; + + if (!cluster.original_features.empty()) + { + mark_minus(cluster, graph, graph_plan); + } + + graph_plan.install_graph.add_vertex({&cluster}); + auto& tracked = cluster.to_install_features; + tracked.insert(feature); + + if (feature != "core") + { + // All features implicitly depend on core + auto res = mark_plus("core", cluster, graph, graph_plan); + + // Should be impossible for "core" to not exist + Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS); + } + + for (auto&& depend : cluster.edges[feature].build_edges) + { + auto& depend_cluster = graph.get(depend.spec()); + auto res = mark_plus(depend.feature(), depend_cluster, graph, graph_plan); + + Checks::check_exit(VCPKG_LINE_INFO, + res == MarkPlusResult::SUCCESS, + "Error: Unable to satisfy dependency %s of %s", + depend, + FeatureSpec(cluster.spec, feature)); + + if (&depend_cluster == &cluster) continue; + graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); + } + + return MarkPlusResult::SUCCESS; + } + + void mark_minus(Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) + { + if (cluster.will_remove) return; + cluster.will_remove = true; + + graph_plan.remove_graph.add_vertex({&cluster}); + for (auto&& pair : cluster.edges) + { + auto& remove_edges_edges = pair.second.remove_edges; + for (auto&& depend : remove_edges_edges) + { + auto& depend_cluster = graph.get(depend.spec()); + graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); + mark_minus(depend_cluster, graph, graph_plan); + } + } + + cluster.transient_uninstalled = true; + for (auto&& original_feature : cluster.original_features) + { + auto res = mark_plus(original_feature, cluster, graph, graph_plan); + if (res != MarkPlusResult::SUCCESS) + { + System::println(System::Color::warning, + "Warning: could not reinstall feature %s", + FeatureSpec{cluster.spec, original_feature}); + } + } + } + + static ClusterGraph create_feature_install_graph(const std::unordered_map& map, + const StatusParagraphs& status_db) + { + std::unordered_map ptr_map; + for (auto&& p : map) + ptr_map.emplace(p.first, &p.second); + ClusterGraph graph(std::move(ptr_map)); + + auto installed_ports = get_installed_ports(status_db); + + for (auto&& status_paragraph : installed_ports) + { + Cluster& cluster = graph.get(status_paragraph->package.spec); + + cluster.transient_uninstalled = false; + + cluster.status_paragraphs.emplace_back(status_paragraph); + + auto& status_paragraph_feature = status_paragraph->package.feature; + // In this case, empty string indicates the "core" paragraph for a package. + if (status_paragraph_feature.empty()) + { + cluster.original_features.insert("core"); + } + else + { + cluster.original_features.insert(status_paragraph_feature); + } + } + + for (auto&& status_paragraph : installed_ports) + { + auto& spec = status_paragraph->package.spec; + auto& status_paragraph_feature = status_paragraph->package.feature; + auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, + status_paragraph->package.spec.triplet()); + + for (auto&& dependency : reverse_edges) + { + auto& dep_cluster = graph.get(dependency.spec()); + + auto depends_name = dependency.feature(); + if (depends_name.empty()) depends_name = "core"; + + auto& target_node = dep_cluster.edges[depends_name]; + target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); + } + } + return graph; + } + + std::vector create_feature_install_plan(const std::unordered_map& map, + const std::vector& specs, + const StatusParagraphs& status_db) + { + ClusterGraph graph = create_feature_install_graph(map, status_db); + + GraphPlan graph_plan; + for (auto&& spec : specs) + { + Cluster& spec_cluster = graph.get(spec.spec()); + spec_cluster.request_type = RequestType::USER_REQUESTED; + auto res = mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + + Checks::check_exit( + VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); + + graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster}); + } + + Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); + auto remove_vertex_list = graph_plan.remove_graph.vertex_list(); + auto remove_toposort = Graphs::topological_sort(remove_vertex_list, adjacency_remove_graph); + + Graphs::GraphAdjacencyProvider adjacency_install_graph(graph_plan.install_graph.adjacency_list()); + auto insert_vertex_list = graph_plan.install_graph.vertex_list(); + auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph); + + std::vector plan; + + for (auto&& p_cluster : remove_toposort) + { + auto scf = *p_cluster->source_control_file.get(); + auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, p_cluster->spec.triplet()) + .value_or_exit(VCPKG_LINE_INFO); + plan.emplace_back(RemovePlanAction{ + std::move(spec), + RemovePlanType::REMOVE, + p_cluster->request_type, + }); + } + + for (auto&& p_cluster : insert_toposort) + { + if (p_cluster->transient_uninstalled) + { + // If it will be transiently uninstalled, we need to issue a full installation command + auto pscf = p_cluster->source_control_file.value_or_exit(VCPKG_LINE_INFO); + Checks::check_exit(VCPKG_LINE_INFO, pscf != nullptr); + plan.emplace_back(InstallPlanAction{ + p_cluster->spec, + *pscf, + p_cluster->to_install_features, + p_cluster->request_type, + }); + } + else + { + // If the package isn't transitively installed, still include it if the user explicitly requested it + if (p_cluster->request_type != RequestType::USER_REQUESTED) continue; + plan.emplace_back(InstallPlanAction{ + p_cluster->spec, + p_cluster->original_features, + p_cluster->request_type, + }); + } + } + + return plan; + } +} diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp new file mode 100644 index 000000000..de6464c87 --- /dev/null +++ b/toolsrc/src/vcpkg/export.cpp @@ -0,0 +1,528 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace vcpkg::Export +{ + using Dependencies::ExportPlanAction; + using Dependencies::ExportPlanType; + using Dependencies::RequestType; + using Install::InstallDir; + + static std::string create_nuspec_file_contents(const std::string& raw_exported_dir, + const std::string& targets_redirect_path, + const std::string& nuget_id, + const std::string& nupkg_version) + { + static constexpr auto CONTENT_TEMPLATE = R"( + + + @NUGET_ID@ + @VERSION@ + vcpkg + + Vcpkg NuGet export + + + + + + + + + +)"; + + std::string nuspec_file_content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id); + nuspec_file_content = std::regex_replace(nuspec_file_content, std::regex("@VERSION@"), nupkg_version); + nuspec_file_content = + std::regex_replace(nuspec_file_content, std::regex("@RAW_EXPORTED_DIR@"), raw_exported_dir); + nuspec_file_content = + std::regex_replace(nuspec_file_content, std::regex("@TARGETS_REDIRECT_PATH@"), targets_redirect_path); + return nuspec_file_content; + } + + static std::string create_targets_redirect(const std::string& target_path) noexcept + { + return Strings::format(R"###( + + + +)###", + target_path, + target_path); + } + + static void print_plan(const std::map>& group_by_plan_type) + { + static constexpr std::array ORDER = {ExportPlanType::ALREADY_BUILT, + ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT}; + + for (const ExportPlanType plan_type : ORDER) + { + const auto it = group_by_plan_type.find(plan_type); + if (it == group_by_plan_type.cend()) + { + continue; + } + + std::vector cont = it->second; + std::sort(cont.begin(), cont.end(), &ExportPlanAction::compare_by_name); + const std::string as_string = Strings::join("\n", cont, [](const ExportPlanAction* p) { + return Dependencies::to_output_string(p->request_type, p->spec.to_string()); + }); + + switch (plan_type) + { + case ExportPlanType::ALREADY_BUILT: + System::println("The following packages are already built and will be exported:\n%s", as_string); + continue; + case ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT: + System::println("The following packages need to be built:\n%s", as_string); + continue; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + } + + static std::string create_export_id() + { + const tm date_time = System::get_current_date_time(); + + // Format is: YYYYmmdd-HHMMSS + // 15 characters + 1 null terminating character will be written for a total of 16 chars + char mbstr[16]; + const size_t bytes_written = std::strftime(mbstr, sizeof(mbstr), "%Y%m%d-%H%M%S", &date_time); + Checks::check_exit(VCPKG_LINE_INFO, + bytes_written == 15, + "Expected 15 bytes to be written, but %u were written", + bytes_written); + const std::string date_time_as_string(mbstr); + return ("vcpkg-export-" + date_time_as_string); + } + + static fs::path do_nuget_export(const VcpkgPaths& paths, + const std::string& nuget_id, + const std::string& nuget_version, + const fs::path& raw_exported_dir, + const fs::path& output_dir) + { + Files::Filesystem& fs = paths.get_filesystem(); + const fs::path& nuget_exe = paths.get_nuget_exe(); + + // This file will be placed in "build\native" in the nuget package. Therefore, go up two dirs. + const std::string targets_redirect_content = + create_targets_redirect("../../scripts/buildsystems/msbuild/vcpkg.targets"); + const fs::path targets_redirect = paths.buildsystems / "tmp" / "vcpkg.export.nuget.targets"; + + std::error_code ec; + fs.create_directories(paths.buildsystems / "tmp", ec); + + fs.write_contents(targets_redirect, targets_redirect_content); + + const std::string nuspec_file_content = + create_nuspec_file_contents(raw_exported_dir.string(), targets_redirect.string(), nuget_id, nuget_version); + const fs::path nuspec_file_path = paths.buildsystems / "tmp" / "vcpkg.export.nuspec"; + fs.write_contents(nuspec_file_path, nuspec_file_content); + + // -NoDefaultExcludes is needed for ".vcpkg-root" + const std::wstring cmd_line = + Strings::wformat(LR"("%s" pack -OutputDirectory "%s" "%s" -NoDefaultExcludes > nul)", + nuget_exe.native(), + output_dir.native(), + nuspec_file_path.native()); + + const int exit_code = System::cmd_execute_clean(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: NuGet package creation failed"); + + const fs::path output_path = output_dir / (nuget_id + ".nupkg"); + return output_path; + } + + struct ArchiveFormat final + { + enum class BackingEnum + { + ZIP = 1, + SEVEN_ZIP, + }; + + constexpr ArchiveFormat() = delete; + + constexpr ArchiveFormat(BackingEnum backing_enum, const wchar_t* extension, const wchar_t* cmake_option) + : backing_enum(backing_enum), m_extension(extension), m_cmake_option(cmake_option) + { + } + + constexpr operator BackingEnum() const { return backing_enum; } + constexpr CWStringView extension() const { return this->m_extension; } + constexpr CWStringView cmake_option() const { return this->m_cmake_option; } + + private: + BackingEnum backing_enum; + const wchar_t* m_extension; + const wchar_t* m_cmake_option; + }; + + namespace ArchiveFormatC + { + constexpr const ArchiveFormat ZIP(ArchiveFormat::BackingEnum::ZIP, L"zip", L"zip"); + constexpr const ArchiveFormat SEVEN_ZIP(ArchiveFormat::BackingEnum::SEVEN_ZIP, L"7z", L"7zip"); + } + + static fs::path do_archive_export(const VcpkgPaths& paths, + const fs::path& raw_exported_dir, + const fs::path& output_dir, + const ArchiveFormat& format) + { + const fs::path& cmake_exe = paths.get_cmake_exe(); + + const std::wstring exported_dir_filename = raw_exported_dir.filename().native(); + const std::wstring exported_archive_filename = + Strings::wformat(L"%s.%s", exported_dir_filename, format.extension()); + const fs::path exported_archive_path = (output_dir / exported_archive_filename); + + // -NoDefaultExcludes is needed for ".vcpkg-root" + const std::wstring cmd_line = Strings::wformat(LR"("%s" -E tar "cf" "%s" --format=%s -- "%s")", + cmake_exe.native(), + exported_archive_path.native(), + format.cmake_option(), + raw_exported_dir.native()); + + const int exit_code = System::cmd_execute_clean(cmd_line); + Checks::check_exit( + VCPKG_LINE_INFO, exit_code == 0, "Error: %s creation failed", exported_archive_path.generic_string()); + return exported_archive_path; + } + + static Optional maybe_lookup(std::unordered_map const& m, + std::string const& key) + { + const auto it = m.find(key); + if (it != m.end()) return it->second; + return nullopt; + } + + void export_integration_files(const fs::path& raw_exported_dir_path, const VcpkgPaths& paths) + { + const std::vector integration_files_relative_to_root = { + {".vcpkg-root"}, + {fs::path{"scripts"} / "buildsystems" / "msbuild" / "applocal.ps1"}, + {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"}, + {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"}, + {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"}, + {fs::path{"scripts"} / "getWindowsSDK.ps1"}, + {fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"}, + {fs::path{"scripts"} / "getProgramFiles32bit.ps1"}, + }; + + for (const fs::path& file : integration_files_relative_to_root) + { + const fs::path source = paths.root / file; + fs::path destination = raw_exported_dir_path / file; + Files::Filesystem& fs = paths.get_filesystem(); + std::error_code ec; + fs.create_directories(destination.parent_path(), ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec); + fs.copy_file(source, destination, fs::copy_options::overwrite_existing, ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec); + } + } + + struct ExportArguments + { + bool dry_run; + bool raw; + bool nuget; + bool ifw; + bool zip; + bool seven_zip; + + Optional maybe_nuget_id; + Optional maybe_nuget_version; + + IFW::Options ifw_options; + std::vector specs; + }; + + static ExportArguments handle_export_command_arguments(const VcpkgCmdArguments& args, + const Triplet& default_triplet) + { + ExportArguments ret; + + static const std::string OPTION_DRY_RUN = "--dry-run"; + static const std::string OPTION_RAW = "--raw"; + static const std::string OPTION_NUGET = "--nuget"; + static const std::string OPTION_IFW = "--ifw"; + static const std::string OPTION_ZIP = "--zip"; + static const std::string OPTION_SEVEN_ZIP = "--7zip"; + static const std::string OPTION_NUGET_ID = "--nuget-id"; + static const std::string OPTION_NUGET_VERSION = "--nuget-version"; + static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url"; + static const std::string OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path"; + static const std::string OPTION_IFW_REPOSITORY_DIR_PATH = "--ifw-repository-directory-path"; + static const std::string OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path"; + static const std::string OPTION_IFW_INSTALLER_FILE_PATH = "--ifw-installer-file-path"; + + // input sanitization + static const std::string EXAMPLE = Help::create_example_string("export zlib zlib:x64-windows boost --nuget"); + args.check_min_arg_count(1, EXAMPLE); + + ret.specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); + }); + + const auto options = args.check_and_get_optional_command_arguments( + { + OPTION_DRY_RUN, + OPTION_RAW, + OPTION_NUGET, + OPTION_IFW, + OPTION_ZIP, + OPTION_SEVEN_ZIP, + }, + { + OPTION_NUGET_ID, + OPTION_NUGET_VERSION, + OPTION_IFW_REPOSITORY_URL, + OPTION_IFW_PACKAGES_DIR_PATH, + OPTION_IFW_REPOSITORY_DIR_PATH, + OPTION_IFW_CONFIG_FILE_PATH, + OPTION_IFW_INSTALLER_FILE_PATH, + }); + ret.dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); + ret.raw = options.switches.find(OPTION_RAW) != options.switches.cend(); + ret.nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); + ret.ifw = options.switches.find(OPTION_IFW) != options.switches.cend(); + ret.zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); + ret.seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend(); + + if (!ret.raw && !ret.nuget && !ret.ifw && !ret.zip && !ret.seven_zip && !ret.dry_run) + { + System::println(System::Color::error, + "Must provide at least one export type: --raw --nuget --ifw --zip --7zip"); + System::print(EXAMPLE); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + struct OptionPair + { + const std::string& name; + Optional& out_opt; + }; + const auto options_implies = + [&](const std::string& main_opt_name, bool main_opt, Span implying_opts) { + if (main_opt) + { + for (auto&& opt : implying_opts) + opt.out_opt = maybe_lookup(options.settings, opt.name); + } + else + { + for (auto&& opt : implying_opts) + Checks::check_exit(VCPKG_LINE_INFO, + !maybe_lookup(options.settings, opt.name), + "%s is only valid with %s", + opt.name, + main_opt_name); + } + }; + + options_implies(OPTION_NUGET, + ret.nuget, + { + {OPTION_NUGET_ID, ret.maybe_nuget_id}, + {OPTION_NUGET_VERSION, ret.maybe_nuget_version}, + }); + + options_implies(OPTION_IFW, + ret.ifw, + { + {OPTION_IFW_REPOSITORY_URL, ret.ifw_options.maybe_repository_url}, + {OPTION_IFW_PACKAGES_DIR_PATH, ret.ifw_options.maybe_packages_dir_path}, + {OPTION_IFW_REPOSITORY_DIR_PATH, ret.ifw_options.maybe_repository_dir_path}, + {OPTION_IFW_CONFIG_FILE_PATH, ret.ifw_options.maybe_config_file_path}, + {OPTION_IFW_INSTALLER_FILE_PATH, ret.ifw_options.maybe_installer_file_path}, + }); + return ret; + } + + static void print_next_step_info(const fs::path& prefix) + { + const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; + const CMakeVariable cmake_variable = CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); + System::println("\n" + "To use the exported libraries in CMake projects use:" + "\n" + " %s" + "\n", + Strings::to_utf8(cmake_variable.s)); + }; + + static void handle_raw_based_export(Span export_plan, + const ExportArguments& opts, + const std::string& export_id, + const VcpkgPaths& paths) + { + Files::Filesystem& fs = paths.get_filesystem(); + const fs::path export_to_path = paths.root; + const fs::path raw_exported_dir_path = export_to_path / export_id; + std::error_code ec; + fs.remove_all(raw_exported_dir_path, ec); + fs.create_directory(raw_exported_dir_path, ec); + + // execute the plan + for (const ExportPlanAction& action : export_plan) + { + if (action.plan_type != ExportPlanType::ALREADY_BUILT) + { + Checks::unreachable(VCPKG_LINE_INFO); + } + + const std::string display_name = action.spec.to_string(); + System::println("Exporting package %s... ", display_name); + + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + const InstallDir dirs = InstallDir::from_destination_root( + raw_exported_dir_path / "installed", + action.spec.triplet().to_string(), + raw_exported_dir_path / "installed" / "vcpkg" / "info" / (binary_paragraph.fullstem() + ".list")); + + Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); + System::println(System::Color::success, "Exporting package %s... done", display_name); + } + + // Copy files needed for integration + export_integration_files(raw_exported_dir_path, paths); + + if (opts.raw) + { + System::println( + System::Color::success, R"(Files exported at: "%s")", raw_exported_dir_path.generic_string()); + print_next_step_info(export_to_path); + } + + if (opts.nuget) + { + System::println("Creating nuget package... "); + + const std::string nuget_id = opts.maybe_nuget_id.value_or(raw_exported_dir_path.filename().string()); + const std::string nuget_version = opts.maybe_nuget_version.value_or("1.0.0"); + const fs::path output_path = + do_nuget_export(paths, nuget_id, nuget_version, raw_exported_dir_path, export_to_path); + System::println(System::Color::success, "Creating nuget package... done"); + System::println(System::Color::success, "NuGet package exported at: %s", output_path.generic_string()); + + System::println(R"( +With a project open, go to Tools->NuGet Package Manager->Package Manager Console and paste: + Install-Package %s -Source "%s" +)" + "\n", + nuget_id, + output_path.parent_path().u8string()); + } + + if (opts.zip) + { + System::println("Creating zip archive... "); + const fs::path output_path = + do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::ZIP); + System::println(System::Color::success, "Creating zip archive... done"); + System::println(System::Color::success, "Zip archive exported at: %s", output_path.generic_string()); + print_next_step_info("[...]"); + } + + if (opts.seven_zip) + { + System::println("Creating 7zip archive... "); + const fs::path output_path = + do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::SEVEN_ZIP); + System::println(System::Color::success, "Creating 7zip archive... done"); + System::println(System::Color::success, "7zip archive exported at: %s", output_path.generic_string()); + print_next_step_info("[...]"); + } + + if (!opts.raw) + { + fs.remove_all(raw_exported_dir_path, ec); + } + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + const auto opts = handle_export_command_arguments(args, default_triplet); + for (auto&& spec : opts.specs) + Input::check_triplet(spec.triplet(), paths); + + // create the plan + const StatusParagraphs status_db = database_load_check(paths); + std::vector export_plan = Dependencies::create_export_plan(paths, opts.specs, status_db); + Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty"); + + std::map> group_by_plan_type; + Util::group_by(export_plan, &group_by_plan_type, [](const ExportPlanAction& p) { return p.plan_type; }); + print_plan(group_by_plan_type); + + const bool has_non_user_requested_packages = + Util::find_if(export_plan, [](const ExportPlanAction& package) -> bool { + return package.request_type != RequestType::USER_REQUESTED; + }) != export_plan.cend(); + + if (has_non_user_requested_packages) + { + System::println(System::Color::warning, + "Additional packages (*) need to be exported to complete this operation."); + } + + const auto it = group_by_plan_type.find(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT); + if (it != group_by_plan_type.cend() && !it->second.empty()) + { + System::println(System::Color::error, "There are packages that have not been built."); + + // No need to show all of them, just the user-requested ones. Dependency resolution will handle the rest. + std::vector unbuilt = it->second; + Util::erase_remove_if( + unbuilt, [](const ExportPlanAction* a) { return a->request_type != RequestType::USER_REQUESTED; }); + + const auto s = Strings::join(" ", unbuilt, [](const ExportPlanAction* a) { return a->spec.to_string(); }); + System::println("To build them, run:\n" + " vcpkg install %s", + s); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + if (opts.dry_run) + { + Checks::exit_success(VCPKG_LINE_INFO); + } + + std::string export_id = create_export_id(); + + if (opts.raw || opts.nuget || opts.zip || opts.seven_zip) + { + handle_raw_based_export(export_plan, opts, export_id, paths); + } + + if (opts.ifw) + { + IFW::do_export(export_plan, export_id, opts.ifw_options, paths); + + print_next_step_info("@RootDir@/src/vcpkg"); + } + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/globalstate.cpp b/toolsrc/src/vcpkg/globalstate.cpp new file mode 100644 index 000000000..de564d357 --- /dev/null +++ b/toolsrc/src/vcpkg/globalstate.cpp @@ -0,0 +1,13 @@ +#include "pch.h" + +#include + +namespace vcpkg +{ + Util::LockGuarded GlobalState::timer; + std::atomic GlobalState::debugging = false; + std::atomic GlobalState::feature_packages = false; + + std::atomic GlobalState::g_init_console_cp = 0; + std::atomic GlobalState::g_init_console_output_cp = 0; +} diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp new file mode 100644 index 000000000..7867f71d2 --- /dev/null +++ b/toolsrc/src/vcpkg/help.cpp @@ -0,0 +1,131 @@ +#include "pch.h" + +#include +#include + +namespace vcpkg::Help +{ + void help_topics() + { + System::println("Available help topics:\n" + " triplet\n" + " integrate\n" + " export"); + } + + void help_topic_valid_triplet(const VcpkgPaths& paths) + { + System::println("Available architecture triplets:"); + for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.triplets)) + { + System::println(" %s", path.stem().filename().string()); + } + } + + void help_topic_export() + { + System::println("Summary:\n" + " vcpkg export [options] ...\n" + "\n" + "Options:\n" + " --7zip Export to a 7zip (.7z) file\n" + " --dry-run Do not actually export\n" + " --nuget Export a NuGet package\n" + " --nuget-id= Specify the id for the exported NuGet package\n" + " --nuget-version= Specify the version for the exported NuGet package\n" + " --raw Export to an uncompressed directory\n" + " --zip Export to a zip file"); + } + + void print_usage() + { + System::println( + "Commands:\n" + " vcpkg search [pat] Search for packages available to be built\n" + " vcpkg install ... Install a package\n" + " vcpkg remove ... Uninstall a package\n" + " vcpkg remove --outdated Uninstall all out-of-date packages\n" + " vcpkg list List installed packages\n" + " vcpkg update Display list of packages for updating\n" + " vcpkg hash [alg] Hash a file by specific algorithm, default SHA512\n" + " vcpkg help topics Display the list of help topics\n" + " vcpkg help Display help for a specific topic\n" + "\n" + "%s" // Integration help + "\n" + " vcpkg export ... [opt]... Exports a package\n" + " vcpkg edit Open up a port for editing (uses %%EDITOR%%, default 'code')\n" + " vcpkg import Import a pre-built library\n" + " vcpkg create \n" + " [archivename] Create a new package\n" + " vcpkg owns Search for files in installed packages\n" + " vcpkg cache List cached compiled packages\n" + " vcpkg version Display version information\n" + " vcpkg contact Display contact information to send feedback\n" + "\n" + //"internal commands:\n" + //" --check-build-deps \n" + //" --create-binary-control \n" + //"\n" + "Options:\n" + " --triplet Specify the target architecture triplet.\n" + " (default: %%VCPKG_DEFAULT_TRIPLET%%, see 'vcpkg help triplet')\n" + "\n" + " --vcpkg-root Specify the vcpkg root directory\n" + " (default: %%VCPKG_ROOT%%)\n" + "\n" + "For more help (including examples) see the accompanying README.md.", + Commands::Integrate::INTEGRATE_COMMAND_HELPSTRING); + } + + std::string create_example_string(const std::string& command_and_arguments) + { + std::string cs = Strings::format("Example:\n" + " vcpkg %s\n", + command_and_arguments); + return cs; + } + + void print_example(const std::string& command_and_arguments) + { + System::println(create_example_string(command_and_arguments)); + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + args.check_max_arg_count(1); + args.check_and_get_optional_command_arguments({}); + + if (args.command_arguments.empty()) + { + print_usage(); + Checks::exit_success(VCPKG_LINE_INFO); + } + const auto& topic = args.command_arguments[0]; + if (topic == "triplet" || topic == "triplets" || topic == "triple") + { + help_topic_valid_triplet(paths); + } + else if (topic == "export") + { + help_topic_export(); + } + else if (topic == "integrate") + { + System::print("Commands:\n" + "%s", + Commands::Integrate::INTEGRATE_COMMAND_HELPSTRING); + } + else if (topic == "topics") + { + help_topics(); + } + else + { + System::println(System::Color::error, "Error: unknown topic %s", topic); + help_topics(); + Checks::exit_fail(VCPKG_LINE_INFO); + } + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/input.cpp b/toolsrc/src/vcpkg/input.cpp new file mode 100644 index 000000000..aee0fac7f --- /dev/null +++ b/toolsrc/src/vcpkg/input.cpp @@ -0,0 +1,55 @@ +#include "pch.h" + +#include +#include +#include +#include +#include + +namespace vcpkg::Input +{ + PackageSpec check_and_get_package_spec(const std::string& package_spec_as_string, + const Triplet& default_triplet, + CStringView example_text) + { + const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); + auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet); + if (const auto spec = expected_spec.get()) + { + return PackageSpec{spec->package_spec}; + } + + // Intentionally show the lowercased string + System::println(System::Color::error, "Error: %s: %s", vcpkg::to_string(expected_spec.error()), as_lowercase); + System::print(example_text); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + void check_triplet(const Triplet& t, const VcpkgPaths& paths) + { + if (!paths.is_valid_triplet(t)) + { + System::println(System::Color::error, "Error: invalid triplet: %s", t); + Metrics::g_metrics.lock()->track_property("error", "invalid triplet: " + t.to_string()); + Help::help_topic_valid_triplet(paths); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } + + FullPackageSpec check_and_get_full_package_spec(const std::string& full_package_spec_as_string, + const Triplet& default_triplet, + CStringView example_text) + { + const std::string as_lowercase = Strings::ascii_to_lowercase(full_package_spec_as_string); + auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet); + if (const auto spec = expected_spec.get()) + { + return *spec; + } + + // Intentionally show the lowercased string + System::println(System::Color::error, "Error: %s: %s", vcpkg::to_string(expected_spec.error()), as_lowercase); + System::print(example_text); + Checks::exit_fail(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp new file mode 100644 index 000000000..74bea0d5f --- /dev/null +++ b/toolsrc/src/vcpkg/install.cpp @@ -0,0 +1,615 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Install +{ + using namespace Dependencies; + + InstallDir InstallDir::from_destination_root(const fs::path& destination_root, + const std::string& destination_subdirectory, + const fs::path& listfile) + { + InstallDir dirs; + dirs.m_destination = destination_root / destination_subdirectory; + dirs.m_destination_subdirectory = destination_subdirectory; + dirs.m_listfile = listfile; + return dirs; + } + + const fs::path& InstallDir::destination() const { return this->m_destination; } + + const std::string& InstallDir::destination_subdirectory() const { return this->m_destination_subdirectory; } + + const fs::path& InstallDir::listfile() const { return this->m_listfile; } + + void install_files_and_write_listfile(Files::Filesystem& fs, + const fs::path& source_dir, + const InstallDir& destination_dir) + { + std::vector output; + std::error_code ec; + + const size_t prefix_length = source_dir.native().size(); + const fs::path& destination = destination_dir.destination(); + const std::string& destination_subdirectory = destination_dir.destination_subdirectory(); + const fs::path& listfile = destination_dir.listfile(); + + Checks::check_exit( + VCPKG_LINE_INFO, fs.exists(source_dir), "Source directory %s does not exist", source_dir.generic_string()); + fs.create_directories(destination, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create destination directory %s", destination.generic_string()); + const fs::path listfile_parent = listfile.parent_path(); + fs.create_directories(listfile_parent, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create directory for listfile %s", listfile.generic_string()); + + output.push_back(Strings::format(R"(%s/)", destination_subdirectory)); + auto files = fs.get_files_recursive(source_dir); + for (auto&& file : files) + { + const auto status = fs.status(file, ec); + if (ec) + { + System::println(System::Color::error, "failed: %s: %s", file.u8string(), ec.message()); + continue; + } + + const std::string filename = file.filename().generic_string(); + if (fs::is_regular_file(status) && + (Strings::case_insensitive_ascii_compare(filename.c_str(), "CONTROL") || + Strings::case_insensitive_ascii_compare(filename.c_str(), "BUILD_INFO"))) + { + // Do not copy the control file + continue; + } + + const std::string suffix = file.generic_u8string().substr(prefix_length + 1); + const fs::path target = destination / suffix; + + if (fs::is_directory(status)) + { + fs.create_directory(target, ec); + if (ec) + { + System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); + } + + // Trailing backslash for directories + output.push_back(Strings::format(R"(%s/%s/)", destination_subdirectory, suffix)); + continue; + } + + if (fs::is_regular_file(status)) + { + if (fs.exists(target)) + { + System::println(System::Color::warning, + "File %s was already present and will be overwritten", + target.u8string(), + ec.message()); + } + fs.copy_file(file, target, fs::copy_options::overwrite_existing, ec); + if (ec) + { + System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); + } + output.push_back(Strings::format(R"(%s/%s)", destination_subdirectory, suffix)); + continue; + } + + if (!fs::status_known(status)) + { + System::println(System::Color::error, "failed: %s: unknown status", file.u8string()); + continue; + } + + System::println(System::Color::error, "failed: %s: cannot handle file type", file.u8string()); + } + + std::sort(output.begin(), output.end()); + + fs.write_lines(listfile, output); + } + + static void remove_first_n_chars(std::vector* strings, const size_t n) + { + for (std::string& s : *strings) + { + s.erase(0, n); + } + }; + + static std::vector extract_files_in_triplet( + const std::vector& pgh_and_files, const Triplet& triplet) + { + std::vector output; + for (const StatusParagraphAndAssociatedFiles& t : pgh_and_files) + { + if (t.pgh.package.spec.triplet() != triplet) + { + continue; + } + + output.insert(output.end(), t.files.begin(), t.files.end()); + } + + std::sort(output.begin(), output.end()); + return output; + } + + static SortedVector build_list_of_package_files(const Files::Filesystem& fs, + const fs::path& package_dir) + { + const std::vector package_file_paths = fs.get_files_recursive(package_dir); + const size_t package_remove_char_count = package_dir.generic_string().size() + 1; // +1 for the slash + auto package_files = Util::fmap(package_file_paths, [package_remove_char_count](const fs::path& path) { + std::string as_string = path.generic_string(); + as_string.erase(0, package_remove_char_count); + return std::move(as_string); + }); + + return SortedVector(std::move(package_files)); + } + + static SortedVector build_list_of_installed_files( + const std::vector& pgh_and_files, const Triplet& triplet) + { + std::vector installed_files = extract_files_in_triplet(pgh_and_files, triplet); + const size_t installed_remove_char_count = triplet.canonical_name().size() + 1; // +1 for the slash + remove_first_n_chars(&installed_files, installed_remove_char_count); + + return SortedVector(std::move(installed_files)); + } + + InstallResult install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db) + { + const fs::path package_dir = paths.package_dir(bcf.core_paragraph.spec); + const Triplet& triplet = bcf.core_paragraph.spec.triplet(); + const std::vector pgh_and_files = get_installed_files(paths, *status_db); + + const SortedVector package_files = + build_list_of_package_files(paths.get_filesystem(), package_dir); + const SortedVector installed_files = build_list_of_installed_files(pgh_and_files, triplet); + + std::vector intersection; + std::set_intersection(package_files.begin(), + package_files.end(), + installed_files.begin(), + installed_files.end(), + std::back_inserter(intersection)); + + if (!intersection.empty()) + { + const fs::path triplet_install_path = paths.installed / triplet.canonical_name(); + System::println(System::Color::error, + "The following files are already installed in %s and are in conflict with %s", + triplet_install_path.generic_string(), + bcf.core_paragraph.spec); + System::print("\n "); + System::println(Strings::join("\n ", intersection)); + System::println(); + return InstallResult::FILE_CONFLICTS; + } + + StatusParagraph source_paragraph; + source_paragraph.package = bcf.core_paragraph; + source_paragraph.want = Want::INSTALL; + source_paragraph.state = InstallState::HALF_INSTALLED; + + write_update(paths, source_paragraph); + status_db->insert(std::make_unique(source_paragraph)); + + std::vector features_spghs; + for (auto&& feature : bcf.features) + { + features_spghs.emplace_back(); + + StatusParagraph& feature_paragraph = features_spghs.back(); + feature_paragraph.package = feature; + feature_paragraph.want = Want::INSTALL; + feature_paragraph.state = InstallState::HALF_INSTALLED; + + write_update(paths, feature_paragraph); + status_db->insert(std::make_unique(feature_paragraph)); + } + + const InstallDir install_dir = InstallDir::from_destination_root( + paths.installed, triplet.to_string(), paths.listfile_path(bcf.core_paragraph)); + + install_files_and_write_listfile(paths.get_filesystem(), package_dir, install_dir); + + source_paragraph.state = InstallState::INSTALLED; + write_update(paths, source_paragraph); + status_db->insert(std::make_unique(source_paragraph)); + + for (auto&& feature_paragraph : features_spghs) + { + feature_paragraph.state = InstallState::INSTALLED; + write_update(paths, feature_paragraph); + status_db->insert(std::make_unique(feature_paragraph)); + } + + return InstallResult::SUCCESS; + } + + using Build::BuildResult; + + BuildResult perform_install_plan_action(const VcpkgPaths& paths, + const InstallPlanAction& action, + const Build::BuildPackageOptions& build_package_options, + StatusParagraphs& status_db) + { + const InstallPlanType& plan_type = action.plan_type; + const std::string display_name = action.spec.to_string(); + const std::string display_name_with_features = + GlobalState::feature_packages ? action.displayname() : display_name; + + const bool is_user_requested = action.request_type == RequestType::USER_REQUESTED; + const bool use_head_version = to_bool(build_package_options.use_head_version); + + if (plan_type == InstallPlanType::ALREADY_INSTALLED) + { + if (use_head_version && is_user_requested) + System::println( + System::Color::warning, "Package %s is already installed -- not building from HEAD", display_name); + else + System::println(System::Color::success, "Package %s is already installed", display_name); + return BuildResult::SUCCEEDED; + } + + if (plan_type == InstallPlanType::BUILD_AND_INSTALL) + { + if (use_head_version) + System::println("Building package %s from HEAD... ", display_name_with_features); + else + System::println("Building package %s... ", display_name_with_features); + + const auto result = [&]() -> Build::ExtendedBuildResult { + if (GlobalState::feature_packages) + { + const Build::BuildPackageConfig build_config{ + *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), + action.spec.triplet(), + paths.port_dir(action.spec), + build_package_options, + action.feature_list}; + return Build::build_package(paths, build_config, status_db); + } + else + { + const Build::BuildPackageConfig build_config{ + action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO), + action.spec.triplet(), + paths.port_dir(action.spec), + build_package_options}; + return Build::build_package(paths, build_config, status_db); + } + }(); + + if (result.code != Build::BuildResult::SUCCEEDED) + { + System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); + return result.code; + } + + System::println("Building package %s... done", display_name_with_features); + + const BinaryControlFile bcf = + Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); + System::println("Installing package %s... ", display_name_with_features); + const auto install_result = install_package(paths, bcf, &status_db); + switch (install_result) + { + case InstallResult::SUCCESS: + System::println(System::Color::success, "Installing package %s... done", display_name); + return BuildResult::SUCCEEDED; + case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + + if (plan_type == InstallPlanType::INSTALL) + { + if (use_head_version && is_user_requested) + { + System::println( + System::Color::warning, "Package %s is already built -- not building from HEAD", display_name); + } + System::println("Installing package %s... ", display_name); + const auto install_result = install_package( + paths, action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO), &status_db); + switch (install_result) + { + case InstallResult::SUCCESS: + System::println(System::Color::success, "Installing package %s... done", display_name); + return BuildResult::SUCCEEDED; + case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + + Checks::unreachable(VCPKG_LINE_INFO); + } + + static void print_plan(const std::vector& action_plan, bool is_recursive) + { + std::vector remove_plans; + std::vector rebuilt_plans; + std::vector only_install_plans; + std::vector new_plans; + std::vector already_installed_plans; + + const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { + if (auto iplan = package.install_plan.get()) + return iplan->request_type != RequestType::USER_REQUESTED; + else + return false; + }) != action_plan.cend(); + + for (auto&& action : action_plan) + { + if (auto install_action = action.install_plan.get()) + { + // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at + // all. + auto it = Util::find_if( + remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); + if (it != remove_plans.end()) + { + rebuilt_plans.emplace_back(install_action); + } + else + { + switch (install_action->plan_type) + { + case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break; + case InstallPlanType::ALREADY_INSTALLED: + if (install_action->request_type == RequestType::USER_REQUESTED) + already_installed_plans.emplace_back(install_action); + break; + case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + } + else if (auto remove_action = action.remove_plan.get()) + { + remove_plans.emplace_back(remove_action); + } + } + + std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name); + std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name); + + if (already_installed_plans.size() > 0) + { + const std::string already_string = + Strings::join("\n", already_installed_plans, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname()); + }); + System::println("The following packages are already installed:\n%s", already_string); + } + + if (rebuilt_plans.size() > 0) + { + const std::string rebuilt_string = Strings::join("\n", rebuilt_plans, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname()); + }); + System::println("The following packages will be rebuilt:\n%s", rebuilt_string); + } + + if (new_plans.size() > 0) + { + const std::string new_string = Strings::join("\n", new_plans, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname()); + }); + System::println("The following packages will be built and installed:\n%s", new_string); + } + + if (only_install_plans.size() > 0) + { + const std::string only_install_string = + Strings::join("\n", only_install_plans, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname()); + }); + System::println("The following packages will be directly installed:\n%s", only_install_string); + } + + if (has_non_user_requested_packages) + System::println("Additional packages (*) will be installed to complete this operation."); + + if (remove_plans.size() > 0 && !is_recursive) + { + System::println(System::Color::warning, + "If you are sure you want to rebuild the above packages, run the command with the " + "--recurse option"); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } + + void perform_and_exit_ex(const std::vector& action_plan, + const Build::BuildPackageOptions& install_plan_options, + const KeepGoing keep_going, + const PrintSummary print_summary, + const VcpkgPaths& paths, + StatusParagraphs& status_db) + { + std::vector results; + std::vector timing; + const auto timer = Chrono::ElapsedTime::create_started(); + size_t counter = 0; + const size_t package_count = action_plan.size(); + + for (const auto& action : action_plan) + { + const auto build_timer = Chrono::ElapsedTime::create_started(); + counter++; + + const std::string display_name = action.spec().to_string(); + System::println("Starting package %d/%d: %s", counter, package_count, display_name); + + timing.push_back("0"); + results.push_back(BuildResult::NULLVALUE); + + if (const auto install_action = action.install_plan.get()) + { + const BuildResult result = + perform_install_plan_action(paths, *install_action, install_plan_options, status_db); + if (result != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO) + { + System::println(Build::create_user_troubleshooting_message(install_action->spec)); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + results.back() = result; + } + else if (const auto remove_action = action.remove_plan.get()) + { + Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages); + Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db); + } + else + { + Checks::unreachable(VCPKG_LINE_INFO); + } + + timing.back() = build_timer.to_string(); + System::println("Elapsed time for package %s: %s", display_name, build_timer.to_string()); + } + + System::println("Total time taken: %s", timer.to_string()); + + if (print_summary == PrintSummary::YES) + { + for (size_t i = 0; i < results.size(); i++) + { + System::println("%s: %s: %s", action_plan[i].spec(), Build::to_string(results[i]), timing[i]); + } + + std::map summary; + for (const BuildResult& v : Build::BUILD_RESULT_VALUES) + { + summary[v] = 0; + } + + for (const BuildResult& r : results) + { + summary[r]++; + } + + System::println("\n\nSUMMARY"); + for (const std::pair& entry : summary) + { + System::println(" %s: %d", Build::to_string(entry.first), entry.second); + } + } + + Checks::exit_success(VCPKG_LINE_INFO); + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + static const std::string OPTION_DRY_RUN = "--dry-run"; + static const std::string OPTION_USE_HEAD_VERSION = "--head"; + static const std::string OPTION_NO_DOWNLOADS = "--no-downloads"; + static const std::string OPTION_RECURSE = "--recurse"; + static const std::string OPTION_KEEP_GOING = "--keep-going"; + + // input sanitization + static const std::string EXAMPLE = Help::create_example_string("install zlib zlib:x64-windows curl boost"); + args.check_min_arg_count(1, EXAMPLE); + + const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + return Input::check_and_get_full_package_spec(arg, default_triplet, EXAMPLE); + }); + + for (auto&& spec : specs) + { + Input::check_triplet(spec.package_spec.triplet(), paths); + if (!spec.features.empty() && !GlobalState::feature_packages) + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "Feature packages are experimentally available under the --featurepackages flag."); + } + } + + const std::unordered_set options = args.check_and_get_optional_command_arguments( + {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE, OPTION_KEEP_GOING}); + const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend(); + const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend(); + const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); + const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); + const KeepGoing keep_going = to_keep_going(options.find(OPTION_KEEP_GOING) != options.cend()); + + // create the plan + StatusParagraphs status_db = database_load_check(paths); + + const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), + Build::to_allow_downloads(!no_downloads)}; + + std::vector action_plan; + + if (GlobalState::feature_packages) + { + std::unordered_map scf_map; + auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + for (auto&& port : all_ports) + { + scf_map[port->core_paragraph->name] = std::move(*port); + } + action_plan = create_feature_install_plan(scf_map, FullPackageSpec::to_feature_specs(specs), status_db); + } + else + { + Dependencies::PathsPortFile paths_port_file(paths); + auto install_plan = Dependencies::create_install_plan( + paths_port_file, Util::fmap(specs, [](auto&& spec) { return spec.package_spec; }), status_db); + + action_plan = Util::fmap( + install_plan, [](InstallPlanAction& install_action) { return AnyAction(std::move(install_action)); }); + } + + // install plan will be empty if it is already installed - need to change this at status paragraph part + Checks::check_exit(VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty"); + + // log the plan + const std::string specs_string = Strings::join(",", action_plan, [](const AnyAction& action) { + if (auto iaction = action.install_plan.get()) + return iaction->spec.to_string(); + else if (auto raction = action.remove_plan.get()) + return "R$" + raction->spec.to_string(); + Checks::unreachable(VCPKG_LINE_INFO); + }); + + Metrics::g_metrics.lock()->track_property("installplan", specs_string); + + print_plan(action_plan, is_recursive); + + if (dry_run) + { + Checks::exit_success(VCPKG_LINE_INFO); + } + + perform_and_exit_ex(action_plan, install_plan_options, keep_going, PrintSummary::NO, paths, status_db); + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp new file mode 100644 index 000000000..84c1ee208 --- /dev/null +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -0,0 +1,398 @@ +#include "pch.h" + +#include + +#include +#include +#include + +#pragma comment(lib, "version") +#pragma comment(lib, "winhttp") + +namespace vcpkg::Metrics +{ + Util::LockGuarded g_metrics; + + static std::string get_current_date_time() + { + struct tm newtime; + std::array date; + date.fill(0); + + struct _timeb timebuffer; + + _ftime_s(&timebuffer); + time_t now = timebuffer.time; + const int milli = timebuffer.millitm; + + const errno_t err = gmtime_s(&newtime, &now); + if (err) + { + return Strings::EMPTY; + } + + strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S", &newtime); + return std::string(&date[0]) + "." + std::to_string(milli) + "Z"; + } + + static std::string generate_random_UUID() + { + int part_sizes[] = {8, 4, 4, 4, 12}; + char uuid[37]; + memset(uuid, 0, sizeof(uuid)); + int num; + srand(static_cast(time(nullptr))); + int index = 0; + for (int part = 0; part < 5; part++) + { + if (part > 0) + { + uuid[index] = '-'; + index++; + } + + // Generating UUID format version 4 + // http://en.wikipedia.org/wiki/Universally_unique_identifier + for (int i = 0; i < part_sizes[part]; i++, index++) + { + if (part == 2 && i == 0) + { + num = 4; + } + else if (part == 4 && i == 0) + { + num = (rand() % 4) + 8; + } + else + { + num = rand() % 16; + } + + if (num < 10) + { + uuid[index] = static_cast('0' + num); + } + else + { + uuid[index] = static_cast('a' + (num - 10)); + } + } + } + + return uuid; + } + + static const std::string& get_session_id() + { + static const std::string ID = generate_random_UUID(); + return ID; + } + + static std::string to_json_string(const std::string& str) + { + std::string encoded = "\""; + for (auto&& ch : str) + { + if (ch == '\\') + { + encoded.append("\\\\"); + } + else if (ch == '"') + { + encoded.append("\\\""); + } + else if (ch < 0x20 || ch >= 0x80) + { + // Note: this treats incoming Strings as Latin-1 + static constexpr const char HEX[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + encoded.append("\\u00"); + encoded.push_back(HEX[ch / 16]); + encoded.push_back(HEX[ch % 16]); + } + else + { + encoded.push_back(ch); + } + } + encoded.push_back('"'); + return encoded; + } + + static std::string get_os_version_string() + { + std::wstring path; + path.resize(MAX_PATH); + const auto n = GetSystemDirectoryW(&path[0], static_cast(path.size())); + path.resize(n); + path += L"\\kernel32.dll"; + + const auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr); + if (versz == 0) return Strings::EMPTY; + + std::vector verbuf; + verbuf.resize(versz); + + if (!GetFileVersionInfoW(path.c_str(), 0, static_cast(verbuf.size()), &verbuf[0])) return Strings::EMPTY; + + void* rootblock; + UINT rootblocksize; + if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return Strings::EMPTY; + + auto rootblock_ffi = static_cast(rootblock); + + return Strings::format("%d.%d.%d", + static_cast(HIWORD(rootblock_ffi->dwProductVersionMS)), + static_cast(LOWORD(rootblock_ffi->dwProductVersionMS)), + static_cast(HIWORD(rootblock_ffi->dwProductVersionLS))); + } + + struct MetricMessage + { + std::string user_id = generate_random_UUID(); + std::string user_timestamp; + std::string timestamp = get_current_date_time(); + std::string properties; + std::string measurements; + + void track_property(const std::string& name, const std::string& value) + { + if (properties.size() != 0) properties.push_back(','); + properties.append(to_json_string(name)); + properties.push_back(':'); + properties.append(to_json_string(value)); + } + + void track_metric(const std::string& name, double value) + { + if (measurements.size() != 0) measurements.push_back(','); + measurements.append(to_json_string(name)); + measurements.push_back(':'); + measurements.append(std::to_string(value)); + } + + std::string format_event_data_template() const + { + const std::string& session_id = get_session_id(); + return Strings::format(R"([{ + "ver": 1, + "name": "Microsoft.ApplicationInsights.Event", + "time": "%s", + "sampleRate": 100.000000, + "seq": "0:0", + "iKey": "b4e88960-4393-4dd9-ab8e-97e8fe6d7603", + "flags": 0.000000, + "tags": { + "ai.device.os": "Windows", + "ai.device.osVersion": "%s", + "ai.session.id": "%s", + "ai.user.id": "%s", + "ai.user.accountAcquisitionDate": "%s" + }, + "data": { + "baseType": "EventData", + "baseData": { + "ver": 2, + "name": "commandline_test7", + "properties": { %s }, + "measurements": { %s } + } + } +}])", + timestamp, + get_os_version_string(), + session_id, + user_id, + user_timestamp, + properties, + measurements); + } + }; + + static MetricMessage g_metricmessage; + static bool g_should_send_metrics = +#if defined(NDEBUG) && (DISABLE_METRICS == 0) + true +#else + false +#endif + ; + static bool g_should_print_metrics = false; + + bool get_compiled_metrics_enabled() { return DISABLE_METRICS == 0; } + + std::wstring get_SQM_user() + { + auto hkcu_sqmclient = + System::get_registry_string(HKEY_CURRENT_USER, LR"(Software\Microsoft\SQMClient)", L"UserId"); + return hkcu_sqmclient.value_or(L"{}"); + } + + void Metrics::set_user_information(const std::string& user_id, const std::string& first_use_time) + { + g_metricmessage.user_id = user_id; + g_metricmessage.user_timestamp = first_use_time; + } + + void Metrics::init_user_information(std::string& user_id, std::string& first_use_time) + { + user_id = generate_random_UUID(); + first_use_time = get_current_date_time(); + } + + void Metrics::set_send_metrics(bool should_send_metrics) { g_should_send_metrics = should_send_metrics; } + + void Metrics::set_print_metrics(bool should_print_metrics) { g_should_print_metrics = should_print_metrics; } + + void Metrics::track_metric(const std::string& name, double value) { g_metricmessage.track_metric(name, value); } + + void Metrics::track_property(const std::string& name, const std::wstring& value) + { + // Note: this is not valid UTF-16 -> UTF-8, it just yields a close enough approximation for our purposes. + std::string converted_value; + converted_value.resize(value.size()); + std::transform( + value.begin(), value.end(), converted_value.begin(), [](wchar_t ch) { return static_cast(ch); }); + + g_metricmessage.track_property(name, converted_value); + } + + void Metrics::track_property(const std::string& name, const std::string& value) + { + g_metricmessage.track_property(name, value); + } + + void Metrics::upload(const std::string& payload) + { + HINTERNET connect = nullptr, request = nullptr; + BOOL results = FALSE; + + const HINTERNET session = WinHttpOpen( + L"vcpkg/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); + if (session) connect = WinHttpConnect(session, L"dc.services.visualstudio.com", INTERNET_DEFAULT_HTTPS_PORT, 0); + + if (connect) + request = WinHttpOpenRequest(connect, + L"POST", + L"/v2/track", + nullptr, + WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, + WINHTTP_FLAG_SECURE); + + if (request) + { + if (MAXDWORD <= payload.size()) abort(); + std::wstring hdrs = L"Content-Type: application/json\r\n"; + std::string& p = const_cast(payload); + results = WinHttpSendRequest(request, + hdrs.c_str(), + static_cast(hdrs.size()), + static_cast(&p[0]), + static_cast(payload.size()), + static_cast(payload.size()), + 0); + } + + if (results) + { + results = WinHttpReceiveResponse(request, nullptr); + } + + DWORD http_code = 0, junk = sizeof(DWORD); + + if (results) + { + results = WinHttpQueryHeaders(request, + WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, + nullptr, + &http_code, + &junk, + WINHTTP_NO_HEADER_INDEX); + } + + std::vector response_buffer; + if (results) + { + DWORD available_data = 0, read_data = 0, total_data = 0; + while ((results = WinHttpQueryDataAvailable(request, &available_data)) == TRUE && available_data > 0) + { + response_buffer.resize(response_buffer.size() + available_data); + + results = WinHttpReadData(request, &response_buffer.data()[total_data], available_data, &read_data); + + if (!results) + { + break; + } + + total_data += read_data; + + response_buffer.resize(total_data); + } + } + + if (!results) + { +#ifndef NDEBUG + __debugbreak(); + auto err = GetLastError(); + std::cerr << "[DEBUG] failed to connect to server: " << err << "\n"; +#endif + } + + if (request) WinHttpCloseHandle(request); + if (connect) WinHttpCloseHandle(connect); + if (session) WinHttpCloseHandle(session); + } + + static fs::path get_bindir() + { + wchar_t buf[_MAX_PATH]; + const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); + if (bytes == 0) std::abort(); + return fs::path(buf, buf + bytes); + } + + void Metrics::flush() + { + const std::string payload = g_metricmessage.format_event_data_template(); + if (g_should_print_metrics) std::cerr << payload << "\n"; + if (!g_should_send_metrics) return; + + // upload(payload); + + wchar_t temp_folder[MAX_PATH]; + GetTempPathW(MAX_PATH, temp_folder); + + const fs::path temp_folder_path = temp_folder; + const fs::path temp_folder_path_exe = temp_folder_path / "vcpkgmetricsuploader.exe"; + + auto& fs = Files::get_real_filesystem(); + + if (true) + { + const fs::path exe_path = [&fs]() -> fs::path { + auto vcpkgdir = get_bindir().parent_path(); + auto path = vcpkgdir / "vcpkgmetricsuploader.exe"; + if (fs.exists(path)) return path; + + path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; + if (fs.exists(path)) return path; + + return Strings::WEMPTY; + }(); + + std::error_code ec; + fs.copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec); + if (ec) return; + } + + const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); + fs.write_contents(vcpkg_metrics_txt_path, payload); + + const std::wstring cmd_line = + Strings::wformat(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native()); + System::cmd_execute_clean(cmd_line); + } +} diff --git a/toolsrc/src/vcpkg/packagespec.cpp b/toolsrc/src/vcpkg/packagespec.cpp new file mode 100644 index 000000000..01a09618d --- /dev/null +++ b/toolsrc/src/vcpkg/packagespec.cpp @@ -0,0 +1,175 @@ +#include "pch.h" + +#include +#include +#include + +using vcpkg::Parse::parse_comma_list; + +namespace vcpkg +{ + static bool is_valid_package_spec_char(char c) + { + return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)) || (c == '[') || (c == ']'); + } + + std::string FeatureSpec::to_string() const + { + if (feature().empty()) return spec().to_string(); + return Strings::format("%s[%s]:%s", name(), feature(), triplet()); + } + + std::vector FeatureSpec::from_strings_and_triplet(const std::vector& depends, + const Triplet& triplet) + { + std::vector f_specs; + for (auto&& depend : depends) + { + auto maybe_spec = ParsedSpecifier::from_string(depend); + if (auto spec = maybe_spec.get()) + { + Checks::check_exit(VCPKG_LINE_INFO, + spec->triplet.empty(), + "error: triplets cannot currently be specified in this context: %s", + depend); + PackageSpec pspec = + PackageSpec::from_name_and_triplet(spec->name, triplet).value_or_exit(VCPKG_LINE_INFO); + + for (auto&& feature : spec->features) + f_specs.push_back(FeatureSpec{pspec, feature}); + + if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, Strings::EMPTY}); + } + else + { + Checks::exit_with_message(VCPKG_LINE_INFO, + "error while parsing feature list: %s: %s", + vcpkg::to_string(maybe_spec.error()), + depend); + } + } + return f_specs; + } + + std::vector FullPackageSpec::to_feature_specs(const std::vector& specs) + { + std::vector ret; + for (auto&& spec : specs) + { + ret.emplace_back(spec.package_spec, Strings::EMPTY); + for (auto&& feature : spec.features) + ret.emplace_back(spec.package_spec, feature); + } + return ret; + } + + ExpectedT FullPackageSpec::from_string(const std::string& spec_as_string, + const Triplet& default_triplet) + { + auto res = ParsedSpecifier::from_string(spec_as_string); + if (auto p = res.get()) + { + FullPackageSpec fspec; + Triplet t = p->triplet.empty() ? default_triplet : Triplet::from_canonical_name(p->triplet); + fspec.package_spec = PackageSpec::from_name_and_triplet(p->name, t).value_or_exit(VCPKG_LINE_INFO); + fspec.features = std::move(p->features); + return fspec; + } + return res.error(); + } + + ExpectedT PackageSpec::from_name_and_triplet(const std::string& name, + const Triplet& triplet) + { + if (Util::find_if_not(name, is_valid_package_spec_char) != name.end()) + { + return PackageSpecParseResult::INVALID_CHARACTERS; + } + + PackageSpec p; + p.m_name = name; + p.m_triplet = triplet; + return p; + } + + const std::string& PackageSpec::name() const { return this->m_name; } + + const Triplet& PackageSpec::triplet() const { return this->m_triplet; } + + std::string PackageSpec::dir() const { return Strings::format("%s_%s", this->m_name, this->m_triplet); } + + std::string PackageSpec::to_string() const { return Strings::format("%s:%s", this->name(), this->triplet()); } + + bool operator==(const PackageSpec& left, const PackageSpec& right) + { + return left.name() == right.name() && left.triplet() == right.triplet(); + } + + bool operator!=(const PackageSpec& left, const PackageSpec& right) { return !(left == right); } + + ExpectedT ParsedSpecifier::from_string(const std::string& input) + { + auto pos = input.find(':'); + auto pos_l_bracket = input.find('['); + auto pos_r_bracket = input.find(']'); + + ParsedSpecifier f; + if (pos == std::string::npos && pos_l_bracket == std::string::npos) + { + f.name = input; + return f; + } + else if (pos == std::string::npos) + { + if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) + { + return PackageSpecParseResult::INVALID_CHARACTERS; + } + const std::string name = input.substr(0, pos_l_bracket); + f.name = name; + f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); + return f; + } + else if (pos_l_bracket == std::string::npos && pos_r_bracket == std::string::npos) + { + const std::string name = input.substr(0, pos); + f.triplet = input.substr(pos + 1); + f.name = name; + } + else + { + if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) + { + return PackageSpecParseResult::INVALID_CHARACTERS; + } + const std::string name = input.substr(0, pos_l_bracket); + f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); + f.triplet = input.substr(pos + 1); + f.name = name; + } + + auto pos2 = input.find(':', pos + 1); + if (pos2 != std::string::npos) + { + return PackageSpecParseResult::TOO_MANY_COLONS; + } + return f; + } + + ExpectedT Features::from_string(const std::string& name) + { + auto maybe_spec = ParsedSpecifier::from_string(name); + if (auto spec = maybe_spec.get()) + { + Checks::check_exit( + VCPKG_LINE_INFO, spec->triplet.empty(), "error: triplet not allowed in specifier: %s", name); + + Features f; + f.name = spec->name; + f.features = spec->features; + return f; + } + + return maybe_spec.error(); + } +} diff --git a/toolsrc/src/vcpkg/packagespecparseresult.cpp b/toolsrc/src/vcpkg/packagespecparseresult.cpp new file mode 100644 index 000000000..b12bd12d0 --- /dev/null +++ b/toolsrc/src/vcpkg/packagespecparseresult.cpp @@ -0,0 +1,21 @@ +#include "pch.h" + +#include + +#include + +namespace vcpkg +{ + CStringView to_string(PackageSpecParseResult ev) noexcept + { + switch (ev) + { + case PackageSpecParseResult::SUCCESS: return "OK"; + case PackageSpecParseResult::TOO_MANY_COLONS: return "Too many colons"; + case PackageSpecParseResult::INVALID_CHARACTERS: + return "Contains invalid characters. Only alphanumeric lowercase ASCII characters and dashes are " + "allowed"; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } +} diff --git a/toolsrc/src/vcpkg/paragraphparseresult.cpp b/toolsrc/src/vcpkg/paragraphparseresult.cpp new file mode 100644 index 000000000..920a4b16b --- /dev/null +++ b/toolsrc/src/vcpkg/paragraphparseresult.cpp @@ -0,0 +1,34 @@ +#include "pch.h" + +#include +#include + +namespace vcpkg +{ + const char* ParagraphParseResultCategoryImpl::name() const noexcept { return "ParagraphParseResult"; } + + std::string ParagraphParseResultCategoryImpl::message(int ev) const noexcept + { + switch (static_cast(ev)) + { + case ParagraphParseResult::SUCCESS: return "OK"; + case ParagraphParseResult::EXPECTED_ONE_PARAGRAPH: return "There should be exactly one paragraph"; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + + const std::error_category& paragraph_parse_result_category() + { + static ParagraphParseResultCategoryImpl instance; + return instance; + } + + std::error_code make_error_code(ParagraphParseResult e) + { + return std::error_code(static_cast(e), paragraph_parse_result_category()); + } + + ParagraphParseResult to_paragraph_parse_result(int i) { return static_cast(i); } + + ParagraphParseResult to_paragraph_parse_result(std::error_code ec) { return to_paragraph_parse_result(ec.value()); } +} diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp new file mode 100644 index 000000000..b93de190c --- /dev/null +++ b/toolsrc/src/vcpkg/paragraphs.cpp @@ -0,0 +1,304 @@ +#include "pch.h" + +#include +#include +#include +#include +#include + +using namespace vcpkg::Parse; + +namespace vcpkg::Paragraphs +{ + struct Parser + { + Parser(const char* c, const char* e) : cur(c), end(e) {} + + private: + const char* cur; + const char* const end; + + void peek(char& ch) const + { + if (cur == end) + ch = 0; + else + ch = *cur; + } + + void next(char& ch) + { + if (cur == end) + ch = 0; + else + { + ++cur; + peek(ch); + } + } + + void skip_comment(char& ch) + { + while (ch != '\r' && ch != '\n' && ch != '\0') + next(ch); + if (ch == '\r') next(ch); + if (ch == '\n') next(ch); + } + + void skip_spaces(char& ch) + { + while (ch == ' ' || ch == '\t') + next(ch); + } + + static bool is_alphanum(char ch) + { + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'); + } + + static bool is_comment(char ch) { return (ch == '#'); } + + static bool is_lineend(char ch) { return ch == '\r' || ch == '\n' || ch == 0; } + + void get_fieldvalue(char& ch, std::string& fieldvalue) + { + fieldvalue.clear(); + + auto beginning_of_line = cur; + do + { + // scan to end of current line (it is part of the field value) + while (!is_lineend(ch)) + next(ch); + + fieldvalue.append(beginning_of_line, cur); + + if (ch == '\r') next(ch); + if (ch == '\n') next(ch); + + if (is_alphanum(ch) || is_comment(ch)) + { + // Line begins a new field. + return; + } + + beginning_of_line = cur; + + // Line may continue the current field with data or terminate the paragraph, + // depending on first nonspace character. + skip_spaces(ch); + + if (is_lineend(ch)) + { + // Line was whitespace or empty. + // This terminates the field and the paragraph. + // We leave the blank line's whitespace consumed, because it doesn't matter. + return; + } + + // First nonspace is not a newline. This continues the current field value. + // We forcibly convert all newlines into single '\n' for ease of text handling later on. + fieldvalue.push_back('\n'); + } while (true); + } + + void get_fieldname(char& ch, std::string& fieldname) + { + auto begin_fieldname = cur; + while (is_alphanum(ch) || ch == '-') + next(ch); + Checks::check_exit(VCPKG_LINE_INFO, ch == ':', "Expected ':'"); + fieldname = std::string(begin_fieldname, cur); + + // skip ': ' + next(ch); + skip_spaces(ch); + } + + void get_paragraph(char& ch, std::unordered_map& fields) + { + fields.clear(); + std::string fieldname; + std::string fieldvalue; + do + { + if (is_comment(ch)) + { + skip_comment(ch); + continue; + } + + get_fieldname(ch, fieldname); + + auto it = fields.find(fieldname); + Checks::check_exit(VCPKG_LINE_INFO, it == fields.end(), "Duplicate field"); + + get_fieldvalue(ch, fieldvalue); + + fields.emplace(fieldname, fieldvalue); + } while (!is_lineend(ch)); + } + + public: + std::vector> get_paragraphs() + { + std::vector> paragraphs; + + char ch; + peek(ch); + + while (ch != 0) + { + if (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t') + { + next(ch); + continue; + } + + paragraphs.emplace_back(); + get_paragraph(ch, paragraphs.back()); + } + + return paragraphs; + } + }; + + Expected> get_single_paragraph(const Files::Filesystem& fs, + const fs::path& control_path) + { + const Expected contents = fs.read_contents(control_path); + if (auto spgh = contents.get()) + { + return parse_single_paragraph(*spgh); + } + + return contents.error(); + } + + Expected>> get_paragraphs(const Files::Filesystem& fs, + const fs::path& control_path) + { + const Expected contents = fs.read_contents(control_path); + if (auto spgh = contents.get()) + { + return parse_paragraphs(*spgh); + } + + return contents.error(); + } + + Expected> parse_single_paragraph(const std::string& str) + { + const std::vector> p = + Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); + + if (p.size() == 1) + { + return p.at(0); + } + + return std::error_code(ParagraphParseResult::EXPECTED_ONE_PARAGRAPH); + } + + Expected>> parse_paragraphs(const std::string& str) + { + return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); + } + + ParseExpected try_load_port(const Files::Filesystem& fs, const fs::path& path) + { + Expected>> pghs = get_paragraphs(fs, path / "CONTROL"); + if (auto vector_pghs = pghs.get()) + { + auto csf = SourceControlFile::parse_control_file(std::move(*vector_pghs)); + if (!GlobalState::feature_packages) + { + if (auto ptr = csf.get()) + { + Checks::check_exit(VCPKG_LINE_INFO, ptr->get() != nullptr); + ptr->get()->core_paragraph->default_features.clear(); + ptr->get()->feature_paragraphs.clear(); + } + } + return csf; + } + auto error_info = std::make_unique(); + error_info->name = path.filename().generic_u8string(); + error_info->error = pghs.error(); + return error_info; + } + + Expected try_load_cached_control_package(const VcpkgPaths& paths, const PackageSpec& spec) + { + Expected>> pghs = + get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL"); + + if (auto p = pghs.get()) + { + BinaryControlFile bcf; + bcf.core_paragraph = BinaryParagraph(p->front()); + p->erase(p->begin()); + + bcf.features = + Util::fmap(*p, [&](auto&& raw_feature) -> BinaryParagraph { return BinaryParagraph(raw_feature); }); + + return bcf; + } + + return pghs.error(); + } + + LoadResults try_load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) + { + LoadResults ret; + for (auto&& path : fs.get_files_non_recursive(ports_dir)) + { + auto maybe_spgh = try_load_port(fs, path); + if (const auto spgh = maybe_spgh.get()) + { + ret.paragraphs.emplace_back(std::move(*spgh)); + } + else + { + ret.errors.emplace_back(std::move(maybe_spgh).error()); + } + } + return ret; + } + + std::vector> load_all_ports(const Files::Filesystem& fs, + const fs::path& ports_dir) + { + auto results = try_load_all_ports(fs, ports_dir); + if (!results.errors.empty()) + { + if (GlobalState::debugging) + { + print_error_message(results.errors); + } + else + { + for (auto&& error : results.errors) + { + System::println( + System::Color::warning, "Warning: an error occurred while parsing '%s'", error->name); + } + System::println(System::Color::warning, + "Use '--debug' to get more information about the parse failures.\n"); + } + } + return std::move(results.paragraphs); + } + + std::map load_all_port_names_and_versions(const Files::Filesystem& fs, + const fs::path& ports_dir) + { + auto all_ports = load_all_ports(fs, ports_dir); + + std::map names_and_versions; + for (auto&& port : all_ports) + names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version); + + return names_and_versions; + } +} diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp new file mode 100644 index 000000000..116a7f5c8 --- /dev/null +++ b/toolsrc/src/vcpkg/parse.cpp @@ -0,0 +1,81 @@ +#include "pch.h" + +#include + +#include +#include + +namespace vcpkg::Parse +{ + static Optional remove_field(std::unordered_map* fields, + const std::string& fieldname) + { + auto it = fields->find(fieldname); + if (it == fields->end()) + { + return nullopt; + } + + const std::string value = std::move(it->second); + fields->erase(it); + return value; + } + + void ParagraphParser::required_field(const std::string& fieldname, std::string& out) + { + auto maybe_field = remove_field(&fields, fieldname); + if (const auto field = maybe_field.get()) + out = std::move(*field); + else + missing_fields.push_back(fieldname); + } + std::string ParagraphParser::optional_field(const std::string& fieldname) const + { + return remove_field(&fields, fieldname).value_or(Strings::EMPTY); + } + std::unique_ptr ParagraphParser::error_info(const std::string& name) const + { + if (!fields.empty() || !missing_fields.empty()) + { + auto err = std::make_unique(); + err->name = name; + err->extra_fields = Util::extract_keys(fields); + err->missing_fields = std::move(missing_fields); + return err; + } + return nullptr; + } + + std::vector parse_comma_list(const std::string& str) + { + if (str.empty()) + { + return {}; + } + + std::vector out; + + size_t cur = 0; + do + { + auto pos = str.find(',', cur); + if (pos == std::string::npos) + { + out.push_back(str.substr(cur)); + break; + } + out.push_back(str.substr(cur, pos - cur)); + + // skip comma and space + ++pos; + if (str[pos] == ' ') + { + ++pos; + } + + cur = pos; + } while (cur != std::string::npos); + + return out; + } +} diff --git a/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp b/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp new file mode 100644 index 000000000..2baaddb5e --- /dev/null +++ b/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp @@ -0,0 +1,70 @@ +#include "pch.h" + +#include +#include + +namespace vcpkg::PostBuildLint +{ + BuildType BuildType::value_of(const ConfigurationType& config, const Build::LinkageType& linkage) + { + if (config == ConfigurationType::DEBUG && linkage == Build::LinkageType::STATIC) + { + return BuildTypeC::DEBUG_STATIC; + } + + if (config == ConfigurationType::DEBUG && linkage == Build::LinkageType::DYNAMIC) + { + return BuildTypeC::DEBUG_DYNAMIC; + } + + if (config == ConfigurationType::RELEASE && linkage == Build::LinkageType::STATIC) + { + return BuildTypeC::RELEASE_STATIC; + } + + if (config == ConfigurationType::RELEASE && linkage == Build::LinkageType::DYNAMIC) + { + return BuildTypeC::RELEASE_DYNAMIC; + } + + Checks::unreachable(VCPKG_LINE_INFO); + } + + const ConfigurationType& BuildType::config() const { return this->m_config; } + + const Build::LinkageType& BuildType::linkage() const { return this->m_linkage; } + + const std::regex& BuildType::crt_regex() const + { + static const std::regex REGEX_DEBUG_STATIC(R"(/DEFAULTLIB:LIBCMTD)", std::regex_constants::icase); + static const std::regex REGEX_DEBUG_DYNAMIC(R"(/DEFAULTLIB:MSVCRTD)", std::regex_constants::icase); + static const std::regex REGEX_RELEASE_STATIC(R"(/DEFAULTLIB:LIBCMT[^D])", std::regex_constants::icase); + static const std::regex REGEX_RELEASE_DYNAMIC(R"(/DEFAULTLIB:MSVCRT[^D])", std::regex_constants::icase); + + switch (backing_enum) + { + case BuildTypeC::DEBUG_STATIC: return REGEX_DEBUG_STATIC; + case BuildTypeC::DEBUG_DYNAMIC: return REGEX_DEBUG_DYNAMIC; + case BuildTypeC::RELEASE_STATIC: return REGEX_RELEASE_STATIC; + case BuildTypeC::RELEASE_DYNAMIC: return REGEX_RELEASE_DYNAMIC; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + + const std::string& BuildType::to_string() const + { + static const std::string NAME_DEBUG_STATIC("Debug,Static"); + static const std::string NAME_DEBUG_DYNAMIC("Debug,Dynamic"); + static const std::string NAME_RELEASE_STATIC("Release,Static"); + static const std::string NAME_RELEASE_DYNAMIC("Release,Dynamic"); + + switch (backing_enum) + { + case BuildTypeC::DEBUG_STATIC: return NAME_DEBUG_STATIC; + case BuildTypeC::DEBUG_DYNAMIC: return NAME_DEBUG_DYNAMIC; + case BuildTypeC::RELEASE_STATIC: return NAME_RELEASE_STATIC; + case BuildTypeC::RELEASE_DYNAMIC: return NAME_RELEASE_DYNAMIC; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } +} diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp new file mode 100644 index 000000000..5f55249df --- /dev/null +++ b/toolsrc/src/vcpkg/postbuildlint.cpp @@ -0,0 +1,846 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using vcpkg::Build::BuildInfo; +using vcpkg::Build::BuildPolicy; +using vcpkg::Build::PreBuildInfo; + +namespace vcpkg::PostBuildLint +{ + static auto has_extension_pred(const Files::Filesystem& fs, const std::string& ext) + { + return [&fs, ext](const fs::path& path) { return !fs.is_directory(path) && path.extension() == ext; }; + } + + enum class LintStatus + { + SUCCESS = 0, + ERROR_DETECTED = 1 + }; + + struct OutdatedDynamicCrt + { + std::string name; + std::regex regex; + + OutdatedDynamicCrt(const std::string& name, const std::string& regex_as_string) + : name(name), regex(std::regex(regex_as_string, std::regex_constants::icase)) + { + } + }; + + Span get_outdated_dynamic_crts(CStringView toolset) + { + static const std::vector V_NO_MSVCRT = { + {"msvcp100.dll", R"(msvcp100\.dll)"}, + {"msvcp100d.dll", R"(msvcp100d\.dll)"}, + {"msvcp110.dll", R"(msvcp110\.dll)"}, + {"msvcp110_win.dll", R"(msvcp110_win\.dll)"}, + {"msvcp120.dll", R"(msvcp120\.dll)"}, + {"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"}, + {"msvcp60.dll", R"(msvcp60\.dll)"}, + {"msvcp60.dll", R"(msvcp60\.dll)"}, + + {"msvcr100.dll", R"(msvcr100\.dll)"}, + {"msvcr100d.dll", R"(msvcr100d\.dll)"}, + {"msvcr100_clr0400.dll", R"(msvcr100_clr0400\.dll)"}, + {"msvcr110.dll", R"(msvcr110\.dll)"}, + {"msvcr120.dll", R"(msvcr120\.dll)"}, + {"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"}, + {"msvcrt20.dll", R"(msvcrt20\.dll)"}, + {"msvcrt40.dll", R"(msvcrt40\.dll)"}}; + + return V_NO_MSVCRT; + } + + static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs, + const Build::BuildPolicies& policies, + const fs::path& package_dir) + { + if (policies.is_enabled(BuildPolicy::EMPTY_INCLUDE_FOLDER)) + { + return LintStatus::SUCCESS; + } + + const fs::path include_dir = package_dir / "include"; + if (!fs.exists(include_dir) || fs.is_empty(include_dir)) + { + System::println(System::Color::warning, + "The folder /include is empty. This indicates the library was not correctly installed."); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_for_files_in_debug_include_directory(const Files::Filesystem& fs, + const fs::path& package_dir) + { + const fs::path debug_include_dir = package_dir / "debug" / "include"; + + std::vector files_found = fs.get_files_recursive(debug_include_dir); + + Util::unstable_keep_if( + files_found, [&fs](const fs::path& path) { return !fs.is_directory(path) && path.extension() != ".ifc"; }); + + if (!files_found.empty()) + { + System::println(System::Color::warning, + "Include files should not be duplicated into the /debug/include directory. If this cannot " + "be disabled in the project cmake, use\n" + " file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include)"); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_for_files_in_debug_share_directory(const Files::Filesystem& fs, const fs::path& package_dir) + { + const fs::path debug_share = package_dir / "debug" / "share"; + + if (fs.exists(debug_share)) + { + System::println(System::Color::warning, + "/debug/share should not exist. Please reorganize any important files, then use\n" + " file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/share)"); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_folder_lib_cmake(const Files::Filesystem& fs, + const fs::path& package_dir, + const PackageSpec& spec) + { + const fs::path lib_cmake = package_dir / "lib" / "cmake"; + if (fs.exists(lib_cmake)) + { + System::println( + System::Color::warning, + "The /lib/cmake folder should be merged with /debug/lib/cmake and moved to /share/%s/cmake.", + spec.name()); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_for_misplaced_cmake_files(const Files::Filesystem& fs, + const fs::path& package_dir, + const PackageSpec& spec) + { + std::vector dirs = { + package_dir / "cmake", + package_dir / "debug" / "cmake", + package_dir / "lib" / "cmake", + package_dir / "debug" / "lib" / "cmake", + }; + + std::vector misplaced_cmake_files; + for (auto&& dir : dirs) + { + auto files = fs.get_files_recursive(dir); + for (auto&& file : files) + { + if (!fs.is_directory(file) && file.extension() == ".cmake") + misplaced_cmake_files.push_back(std::move(file)); + } + } + + if (!misplaced_cmake_files.empty()) + { + System::println( + System::Color::warning, + "The following cmake files were found outside /share/%s. Please place cmake files in /share/%s.", + spec.name(), + spec.name()); + Files::print_paths(misplaced_cmake_files); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_folder_debug_lib_cmake(const Files::Filesystem& fs, + const fs::path& package_dir, + const PackageSpec& spec) + { + const fs::path lib_cmake_debug = package_dir / "debug" / "lib" / "cmake"; + if (fs.exists(lib_cmake_debug)) + { + System::println(System::Color::warning, + "The /debug/lib/cmake folder should be merged with /lib/cmake into /share/%s", + spec.name()); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_for_dlls_in_lib_dir(const Files::Filesystem& fs, const fs::path& package_dir) + { + std::vector dlls = fs.get_files_recursive(package_dir / "lib"); + Util::unstable_keep_if(dlls, has_extension_pred(fs, ".dll")); + + if (!dlls.empty()) + { + System::println(System::Color::warning, + "\nThe following dlls were found in /lib or /debug/lib. Please move them to /bin or " + "/debug/bin, respectively."); + Files::print_paths(dlls); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_for_copyright_file(const Files::Filesystem& fs, + const PackageSpec& spec, + const VcpkgPaths& paths) + { + const fs::path packages_dir = paths.packages / spec.dir(); + const fs::path copyright_file = packages_dir / "share" / spec.name() / "copyright"; + if (fs.exists(copyright_file)) + { + return LintStatus::SUCCESS; + } + const fs::path current_buildtrees_dir = paths.buildtrees / spec.name(); + const fs::path current_buildtrees_dir_src = current_buildtrees_dir / "src"; + + std::vector potential_copyright_files; + // We only search in the root of each unpacked source archive to reduce false positives + auto src_dirs = fs.get_files_non_recursive(current_buildtrees_dir_src); + for (auto&& src_dir : src_dirs) + { + if (!fs.is_directory(src_dir)) continue; + + for (auto&& src_file : fs.get_files_non_recursive(src_dir)) + { + const std::string filename = src_file.filename().string(); + + if (filename == "LICENSE" || filename == "LICENSE.txt" || filename == "COPYING") + { + potential_copyright_files.push_back(src_file); + } + } + } + + System::println(System::Color::warning, + "The software license must be available at ${CURRENT_PACKAGES_DIR}/share/%s/copyright", + spec.name()); + if (potential_copyright_files.size() == + 1) // if there is only one candidate, provide the cmake lines needed to place it in the proper location + { + const fs::path found_file = potential_copyright_files[0]; + const fs::path relative_path = found_file.string().erase( + 0, current_buildtrees_dir.string().size() + 1); // The +1 is needed to remove the "/" + System::println( + "\n file(COPY ${CURRENT_BUILDTREES_DIR}/%s DESTINATION ${CURRENT_PACKAGES_DIR}/share/%s)\n" + " file(RENAME ${CURRENT_PACKAGES_DIR}/share/%s/%s ${CURRENT_PACKAGES_DIR}/share/%s/copyright)", + relative_path.generic_string(), + spec.name(), + spec.name(), + found_file.filename().generic_string(), + spec.name()); + } + else if (potential_copyright_files.size() > 1) + { + System::println(System::Color::warning, "The following files are potential copyright files:"); + Files::print_paths(potential_copyright_files); + } + return LintStatus::ERROR_DETECTED; + } + + static LintStatus check_for_exes(const Files::Filesystem& fs, const fs::path& package_dir) + { + std::vector exes = fs.get_files_recursive(package_dir / "bin"); + Util::unstable_keep_if(exes, has_extension_pred(fs, ".exe")); + + if (!exes.empty()) + { + System::println( + System::Color::warning, + "The following EXEs were found in /bin or /debug/bin. EXEs are not valid distribution targets."); + Files::print_paths(exes); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_exports_of_dlls(const std::vector& dlls, const fs::path& dumpbin_exe) + { + std::vector dlls_with_no_exports; + for (const fs::path& dll : dlls) + { + const std::wstring cmd_line = + Strings::wformat(LR"("%s" /exports "%s")", dumpbin_exe.native(), dll.native()); + System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, + ec_data.exit_code == 0, + "Running command:\n %s\n failed", + Strings::to_utf8(cmd_line)); + + if (ec_data.output.find("ordinal hint RVA name") == std::string::npos) + { + dlls_with_no_exports.push_back(dll); + } + } + + if (!dlls_with_no_exports.empty()) + { + System::println(System::Color::warning, "The following DLLs have no exports:"); + Files::print_paths(dlls_with_no_exports); + System::println(System::Color::warning, "DLLs without any exports are likely a bug in the build script."); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_uwp_bit_of_dlls(const std::string& expected_system_name, + const std::vector& dlls, + const fs::path dumpbin_exe) + { + if (expected_system_name != "WindowsStore") + { + return LintStatus::SUCCESS; + } + + std::vector dlls_with_improper_uwp_bit; + for (const fs::path& dll : dlls) + { + const std::wstring cmd_line = + Strings::wformat(LR"("%s" /headers "%s")", dumpbin_exe.native(), dll.native()); + System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, + ec_data.exit_code == 0, + "Running command:\n %s\n failed", + Strings::to_utf8(cmd_line)); + + if (ec_data.output.find("App Container") == std::string::npos) + { + dlls_with_improper_uwp_bit.push_back(dll); + } + } + + if (!dlls_with_improper_uwp_bit.empty()) + { + System::println(System::Color::warning, "The following DLLs do not have the App Container bit set:"); + Files::print_paths(dlls_with_improper_uwp_bit); + System::println(System::Color::warning, "This bit is required for Windows Store apps."); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + struct FileAndArch + { + fs::path file; + std::string actual_arch; + }; + + static std::string get_actual_architecture(const MachineType& machine_type) + { + switch (machine_type) + { + case MachineType::AMD64: + case MachineType::IA64: return "x64"; + case MachineType::I386: return "x86"; + case MachineType::ARM: + case MachineType::ARMNT: return "arm"; + default: return "Machine Type Code = " + std::to_string(static_cast(machine_type)); + } + } + + static void print_invalid_architecture_files(const std::string& expected_architecture, + std::vector binaries_with_invalid_architecture) + { + System::println(System::Color::warning, "The following files were built for an incorrect architecture:"); + System::println(); + for (const FileAndArch& b : binaries_with_invalid_architecture) + { + System::println(" %s", b.file.generic_string()); + System::println("Expected %s, but was: %s", expected_architecture, b.actual_arch); + System::println(); + } + } + + static LintStatus check_dll_architecture(const std::string& expected_architecture, + const std::vector& files) + { + std::vector binaries_with_invalid_architecture; + + for (const fs::path& file : files) + { + Checks::check_exit(VCPKG_LINE_INFO, + file.extension() == ".dll", + "The file extension was not .dll: %s", + file.generic_string()); + const CoffFileReader::DllInfo info = CoffFileReader::read_dll(file); + const std::string actual_architecture = get_actual_architecture(info.machine_type); + + if (expected_architecture != actual_architecture) + { + binaries_with_invalid_architecture.push_back({file, actual_architecture}); + } + } + + if (!binaries_with_invalid_architecture.empty()) + { + print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_lib_architecture(const std::string& expected_architecture, + const std::vector& files) + { + std::vector binaries_with_invalid_architecture; + + for (const fs::path& file : files) + { + Checks::check_exit(VCPKG_LINE_INFO, + file.extension() == ".lib", + "The file extension was not .lib: %s", + file.generic_string()); + CoffFileReader::LibInfo info = CoffFileReader::read_lib(file); + + // This is zero for folly's debug library + // TODO: Why? + if (info.machine_types.size() == 0) return LintStatus::SUCCESS; + + Checks::check_exit(VCPKG_LINE_INFO, + info.machine_types.size() == 1, + "Found more than 1 architecture in file %s", + file.generic_string()); + + const std::string actual_architecture = get_actual_architecture(info.machine_types.at(0)); + if (expected_architecture != actual_architecture) + { + binaries_with_invalid_architecture.push_back({file, actual_architecture}); + } + } + + if (!binaries_with_invalid_architecture.empty()) + { + print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_no_dlls_present(const std::vector& dlls) + { + if (dlls.empty()) + { + return LintStatus::SUCCESS; + } + + System::println(System::Color::warning, + "DLLs should not be present in a static build, but the following DLLs were found:"); + Files::print_paths(dlls); + return LintStatus::ERROR_DETECTED; + } + + static LintStatus check_matching_debug_and_release_binaries(const std::vector& debug_binaries, + const std::vector& release_binaries) + { + const size_t debug_count = debug_binaries.size(); + const size_t release_count = release_binaries.size(); + if (debug_count == release_count) + { + return LintStatus::SUCCESS; + } + + System::println(System::Color::warning, + "Mismatching number of debug and release binaries. Found %d for debug but %d for release.", + debug_count, + release_count); + System::println("Debug binaries"); + Files::print_paths(debug_binaries); + + System::println("Release binaries"); + Files::print_paths(release_binaries); + + if (debug_count == 0) + { + System::println(System::Color::warning, "Debug binaries were not found"); + } + if (release_count == 0) + { + System::println(System::Color::warning, "Release binaries were not found"); + } + + System::println(); + + return LintStatus::ERROR_DETECTED; + } + + static LintStatus check_lib_files_are_available_if_dlls_are_available(const Build::BuildPolicies& policies, + const size_t lib_count, + const size_t dll_count, + const fs::path& lib_dir) + { + if (policies.is_enabled(BuildPolicy::DLLS_WITHOUT_LIBS)) return LintStatus::SUCCESS; + + if (lib_count == 0 && dll_count != 0) + { + System::println(System::Color::warning, "Import libs were not present in %s", lib_dir.u8string()); + System::println(System::Color::warning, + "If this is intended, add the following line in the portfile:\n" + " SET(%s enabled)", + to_cmake_variable(BuildPolicy::DLLS_WITHOUT_LIBS)); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_bin_folders_are_not_present_in_static_build(const Files::Filesystem& fs, + const fs::path& package_dir) + { + const fs::path bin = package_dir / "bin"; + const fs::path debug_bin = package_dir / "debug" / "bin"; + + if (!fs.exists(bin) && !fs.exists(debug_bin)) + { + return LintStatus::SUCCESS; + } + + if (fs.exists(bin)) + { + System::println(System::Color::warning, + R"(There should be no bin\ directory in a static build, but %s is present.)", + bin.u8string()); + } + + if (fs.exists(debug_bin)) + { + System::println(System::Color::warning, + R"(There should be no debug\bin\ directory in a static build, but %s is present.)", + debug_bin.u8string()); + } + + System::println( + System::Color::warning, + R"(If the creation of bin\ and/or debug\bin\ cannot be disabled, use this in the portfile to remove them)" + "\n" + "\n" + R"###( if(VCPKG_LIBRARY_LINKAGE STREQUAL static))###" + "\n" + R"###( file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/bin ${CURRENT_PACKAGES_DIR}/debug/bin))###" + "\n" + R"###( endif())###" + "\n"); + + return LintStatus::ERROR_DETECTED; + } + + static LintStatus check_no_empty_folders(const Files::Filesystem& fs, const fs::path& dir) + { + std::vector empty_directories = fs.get_files_recursive(dir); + + Util::unstable_keep_if(empty_directories, [&fs](const fs::path& current) { + return fs.is_directory(current) && fs.is_empty(current); + }); + + if (!empty_directories.empty()) + { + System::println(System::Color::warning, "There should be no empty directories in %s", dir.generic_string()); + System::println("The following empty directories were found: "); + Files::print_paths(empty_directories); + System::println( + System::Color::warning, + "If a directory should be populated but is not, this might indicate an error in the portfile.\n" + "If the directories are not needed and their creation cannot be disabled, use something like this in " + "the portfile to remove them:\n" + "\n" + R"###( file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/a/dir ${CURRENT_PACKAGES_DIR}/some/other/dir))###" + "\n" + "\n"); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + struct BuildTypeAndFile + { + fs::path file; + BuildType build_type; + }; + + static LintStatus check_crt_linkage_of_libs(const BuildType& expected_build_type, + const std::vector& libs, + const fs::path dumpbin_exe) + { + std::vector bad_build_types(BuildTypeC::VALUES.cbegin(), BuildTypeC::VALUES.cend()); + bad_build_types.erase(std::remove(bad_build_types.begin(), bad_build_types.end(), expected_build_type), + bad_build_types.end()); + + std::vector libs_with_invalid_crt; + + for (const fs::path& lib : libs) + { + const std::wstring cmd_line = + Strings::wformat(LR"("%s" /directives "%s")", dumpbin_exe.native(), lib.native()); + System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, + ec_data.exit_code == 0, + "Running command:\n %s\n failed", + Strings::to_utf8(cmd_line)); + + for (const BuildType& bad_build_type : bad_build_types) + { + if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), bad_build_type.crt_regex())) + { + libs_with_invalid_crt.push_back({lib, bad_build_type}); + break; + } + } + } + + if (!libs_with_invalid_crt.empty()) + { + System::println(System::Color::warning, + "Expected %s crt linkage, but the following libs had invalid crt linkage:", + expected_build_type.to_string()); + System::println(); + for (const BuildTypeAndFile btf : libs_with_invalid_crt) + { + System::println(" %s: %s", btf.file.generic_string(), btf.build_type.to_string()); + } + System::println(); + + System::println(System::Color::warning, + "To inspect the lib files, use:\n dumpbin.exe /directives mylibfile.lib"); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + struct OutdatedDynamicCrtAndFile + { + fs::path file; + OutdatedDynamicCrt outdated_crt; + + OutdatedDynamicCrtAndFile() = delete; + }; + + static LintStatus check_outdated_crt_linkage_of_dlls(const std::vector& dlls, + const fs::path dumpbin_exe, + const BuildInfo& build_info) + { + if (build_info.policies.is_enabled(BuildPolicy::ALLOW_OBSOLETE_MSVCRT)) return LintStatus::SUCCESS; + + std::vector dlls_with_outdated_crt; + + for (const fs::path& dll : dlls) + { + const std::wstring cmd_line = + Strings::wformat(LR"("%s" /dependents "%s")", dumpbin_exe.native(), dll.native()); + System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, + ec_data.exit_code == 0, + "Running command:\n %s\n failed", + Strings::to_utf8(cmd_line)); + + for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts("v141")) + { + if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), outdated_crt.regex)) + { + dlls_with_outdated_crt.push_back({dll, outdated_crt}); + break; + } + } + } + + if (!dlls_with_outdated_crt.empty()) + { + System::println(System::Color::warning, "Detected outdated dynamic CRT in the following files:"); + System::println(); + for (const OutdatedDynamicCrtAndFile btf : dlls_with_outdated_crt) + { + System::println(" %s: %s", btf.file.generic_string(), btf.outdated_crt.name); + } + System::println(); + + System::println(System::Color::warning, + "To inspect the dll files, use:\n dumpbin.exe /dependents mydllfile.dll"); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static LintStatus check_no_files_in_dir(const Files::Filesystem& fs, const fs::path& dir) + { + std::vector misplaced_files = fs.get_files_non_recursive(dir); + Util::unstable_keep_if(misplaced_files, [&fs](const fs::path& path) { + const std::string filename = path.filename().generic_string(); + if (Strings::case_insensitive_ascii_compare(filename.c_str(), "CONTROL") || + Strings::case_insensitive_ascii_compare(filename.c_str(), "BUILD_INFO")) + return false; + return !fs.is_directory(path); + }); + + if (!misplaced_files.empty()) + { + System::println(System::Color::warning, "The following files are placed in\n%s: ", dir.u8string()); + Files::print_paths(misplaced_files); + System::println(System::Color::warning, "Files cannot be present in those directories.\n"); + return LintStatus::ERROR_DETECTED; + } + + return LintStatus::SUCCESS; + } + + static void operator+=(size_t& left, const LintStatus& right) { left += static_cast(right); } + + static size_t perform_all_checks_and_return_error_count(const PackageSpec& spec, + const VcpkgPaths& paths, + const PreBuildInfo& pre_build_info, + const BuildInfo& build_info) + { + const auto& fs = paths.get_filesystem(); + + // for dumpbin + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); + const fs::path package_dir = paths.package_dir(spec); + + size_t error_count = 0; + + if (build_info.policies.is_enabled(BuildPolicy::EMPTY_PACKAGE)) + { + return error_count; + } + + error_count += check_for_files_in_include_directory(fs, build_info.policies, package_dir); + error_count += check_for_files_in_debug_include_directory(fs, package_dir); + error_count += check_for_files_in_debug_share_directory(fs, package_dir); + error_count += check_folder_lib_cmake(fs, package_dir, spec); + error_count += check_for_misplaced_cmake_files(fs, package_dir, spec); + error_count += check_folder_debug_lib_cmake(fs, package_dir, spec); + error_count += check_for_dlls_in_lib_dir(fs, package_dir); + error_count += check_for_dlls_in_lib_dir(fs, package_dir / "debug"); + error_count += check_for_copyright_file(fs, spec, paths); + error_count += check_for_exes(fs, package_dir); + error_count += check_for_exes(fs, package_dir / "debug"); + + const fs::path debug_lib_dir = package_dir / "debug" / "lib"; + const fs::path release_lib_dir = package_dir / "lib"; + const fs::path debug_bin_dir = package_dir / "debug" / "bin"; + const fs::path release_bin_dir = package_dir / "bin"; + + std::vector debug_libs = fs.get_files_recursive(debug_lib_dir); + Util::unstable_keep_if(debug_libs, has_extension_pred(fs, ".lib")); + std::vector release_libs = fs.get_files_recursive(release_lib_dir); + Util::unstable_keep_if(release_libs, has_extension_pred(fs, ".lib")); + + error_count += check_matching_debug_and_release_binaries(debug_libs, release_libs); + + { + std::vector libs; + libs.insert(libs.cend(), debug_libs.cbegin(), debug_libs.cend()); + libs.insert(libs.cend(), release_libs.cbegin(), release_libs.cend()); + + error_count += check_lib_architecture(pre_build_info.target_architecture, libs); + } + + std::vector debug_dlls = fs.get_files_recursive(debug_bin_dir); + Util::unstable_keep_if(debug_dlls, has_extension_pred(fs, ".dll")); + std::vector release_dlls = fs.get_files_recursive(release_bin_dir); + Util::unstable_keep_if(release_dlls, has_extension_pred(fs, ".dll")); + + switch (build_info.library_linkage) + { + case Build::LinkageType::DYNAMIC: + { + error_count += check_matching_debug_and_release_binaries(debug_dlls, release_dlls); + + error_count += check_lib_files_are_available_if_dlls_are_available( + build_info.policies, debug_libs.size(), debug_dlls.size(), debug_lib_dir); + error_count += check_lib_files_are_available_if_dlls_are_available( + build_info.policies, release_libs.size(), release_dlls.size(), release_lib_dir); + + std::vector dlls; + dlls.insert(dlls.cend(), debug_dlls.cbegin(), debug_dlls.cend()); + dlls.insert(dlls.cend(), release_dlls.cbegin(), release_dlls.cend()); + + error_count += check_exports_of_dlls(dlls, toolset.dumpbin); + error_count += check_uwp_bit_of_dlls(pre_build_info.cmake_system_name, dlls, toolset.dumpbin); + error_count += check_dll_architecture(pre_build_info.target_architecture, dlls); + + error_count += check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info); + break; + } + case Build::LinkageType::STATIC: + { + auto dlls = release_dlls; + dlls.insert(dlls.end(), debug_dlls.begin(), debug_dlls.end()); + error_count += check_no_dlls_present(dlls); + + error_count += check_bin_folders_are_not_present_in_static_build(fs, package_dir); + + if (!build_info.policies.is_enabled(BuildPolicy::ONLY_RELEASE_CRT)) + { + error_count += + check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::DEBUG, build_info.crt_linkage), + debug_libs, + toolset.dumpbin); + } + error_count += + check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::RELEASE, build_info.crt_linkage), + release_libs, + toolset.dumpbin); + break; + } + default: Checks::unreachable(VCPKG_LINE_INFO); + } + + error_count += check_no_empty_folders(fs, package_dir); + error_count += check_no_files_in_dir(fs, package_dir); + error_count += check_no_files_in_dir(fs, package_dir / "debug"); + + return error_count; + } + + size_t perform_all_checks(const PackageSpec& spec, + const VcpkgPaths& paths, + const PreBuildInfo& pre_build_info, + const BuildInfo& build_info) + { + System::println("-- Performing post-build validation"); + const size_t error_count = perform_all_checks_and_return_error_count(spec, paths, pre_build_info, build_info); + + if (error_count != 0) + { + const fs::path portfile = paths.ports / spec.name() / "portfile.cmake"; + System::println(System::Color::error, + "Found %u error(s). Please correct the portfile:\n %s", + error_count, + portfile.string()); + } + + System::println("-- Performing post-build validation done"); + + return error_count; + } +} diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp new file mode 100644 index 000000000..3751566f7 --- /dev/null +++ b/toolsrc/src/vcpkg/remove.cpp @@ -0,0 +1,251 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Remove +{ + using Dependencies::RemovePlanAction; + using Dependencies::RemovePlanType; + using Dependencies::RequestType; + using Update::OutdatedPackage; + + void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db) + { + auto& fs = paths.get_filesystem(); + auto spghs = status_db->find_all(spec.name(), spec.triplet()); + const auto core_pkg = **status_db->find(spec.name(), spec.triplet(), Strings::EMPTY); + + for (auto&& spgh : spghs) + { + StatusParagraph& pkg = **spgh; + if (pkg.state != InstallState::INSTALLED) continue; + pkg.want = Want::PURGE; + pkg.state = InstallState::HALF_INSTALLED; + write_update(paths, pkg); + } + + auto maybe_lines = fs.read_lines(paths.listfile_path(core_pkg.package)); + + if (const auto lines = maybe_lines.get()) + { + std::vector dirs_touched; + for (auto&& suffix : *lines) + { + if (!suffix.empty() && suffix.back() == '\r') suffix.pop_back(); + + std::error_code ec; + + auto target = paths.installed / suffix; + + const auto status = fs.status(target, ec); + if (ec) + { + System::println(System::Color::error, "failed: %s", ec.message()); + continue; + } + + if (fs::is_directory(status)) + { + dirs_touched.push_back(target); + } + else if (fs::is_regular_file(status)) + { + fs.remove(target, ec); + if (ec) + { + System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); + } + } + else if (!fs::status_known(status)) + { + System::println(System::Color::warning, "Warning: unknown status: %s", target.u8string()); + } + else + { + System::println(System::Color::warning, "Warning: %s: cannot handle file type", target.u8string()); + } + } + + auto b = dirs_touched.rbegin(); + const auto e = dirs_touched.rend(); + for (; b != e; ++b) + { + if (fs.is_empty(*b)) + { + std::error_code ec; + fs.remove(*b, ec); + if (ec) + { + System::println(System::Color::error, "failed: %s", ec.message()); + } + } + } + + fs.remove(paths.listfile_path(core_pkg.package)); + } + + for (auto&& spgh : spghs) + { + StatusParagraph& pkg = **spgh; + if (pkg.state != InstallState::HALF_INSTALLED) continue; + pkg.state = InstallState::NOT_INSTALLED; + write_update(paths, pkg); + } + } + + static void print_plan(const std::map>& group_by_plan_type) + { + static constexpr std::array ORDER = {RemovePlanType::NOT_INSTALLED, RemovePlanType::REMOVE}; + + for (const RemovePlanType plan_type : ORDER) + { + const auto it = group_by_plan_type.find(plan_type); + if (it == group_by_plan_type.cend()) + { + continue; + } + + std::vector cont = it->second; + std::sort(cont.begin(), cont.end(), &RemovePlanAction::compare_by_name); + const std::string as_string = Strings::join("\n", cont, [](const RemovePlanAction* p) { + return Dependencies::to_output_string(p->request_type, p->spec.to_string()); + }); + + switch (plan_type) + { + case RemovePlanType::NOT_INSTALLED: + System::println("The following packages are not installed, so not removed:\n%s", as_string); + continue; + case RemovePlanType::REMOVE: + System::println("The following packages will be removed:\n%s", as_string); + continue; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + } + + void perform_remove_plan_action(const VcpkgPaths& paths, + const RemovePlanAction& action, + const Purge purge, + StatusParagraphs& status_db) + { + const std::string display_name = action.spec.to_string(); + + switch (action.plan_type) + { + case RemovePlanType::NOT_INSTALLED: + System::println(System::Color::success, "Package %s is not installed", display_name); + break; + case RemovePlanType::REMOVE: + System::println("Removing package %s... ", display_name); + remove_package(paths, action.spec, &status_db); + System::println(System::Color::success, "Removing package %s... done", display_name); + break; + case RemovePlanType::UNKNOWN: + default: Checks::unreachable(VCPKG_LINE_INFO); + } + + if (purge == Purge::YES) + { + System::println("Purging package %s... ", display_name); + Files::Filesystem& fs = paths.get_filesystem(); + std::error_code ec; + fs.remove_all(paths.packages / action.spec.dir(), ec); + System::println(System::Color::success, "Purging package %s... done", display_name); + } + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + static const std::string OPTION_PURGE = "--purge"; + static const std::string OPTION_NO_PURGE = "--no-purge"; + static const std::string OPTION_RECURSE = "--recurse"; + static const std::string OPTION_DRY_RUN = "--dry-run"; + static const std::string OPTION_OUTDATED = "--outdated"; + static const std::string EXAMPLE = Help::create_example_string("remove zlib zlib:x64-windows curl boost"); + const std::unordered_set options = args.check_and_get_optional_command_arguments( + {OPTION_PURGE, OPTION_NO_PURGE, OPTION_RECURSE, OPTION_DRY_RUN, OPTION_OUTDATED}); + + StatusParagraphs status_db = database_load_check(paths); + std::vector specs; + if (options.find(OPTION_OUTDATED) != options.cend()) + { + args.check_exact_arg_count(0, EXAMPLE); + specs = Util::fmap(Update::find_outdated_packages(paths, status_db), + [](auto&& outdated) { return outdated.spec; }); + + if (specs.empty()) + { + System::println(System::Color::success, "There are no outdated packages."); + Checks::exit_success(VCPKG_LINE_INFO); + } + } + else + { + args.check_min_arg_count(1, EXAMPLE); + specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); + }); + + for (auto&& spec : specs) + Input::check_triplet(spec.triplet(), paths); + } + + const bool no_purge_was_passed = options.find(OPTION_NO_PURGE) != options.end(); + const bool purge_was_passed = options.find(OPTION_PURGE) != options.end(); + if (purge_was_passed && no_purge_was_passed) + { + System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); + System::print(EXAMPLE); + Checks::exit_fail(VCPKG_LINE_INFO); + } + const Purge purge = to_purge(purge_was_passed || !no_purge_was_passed); + const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); + const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend(); + + const std::vector remove_plan = Dependencies::create_remove_plan(specs, status_db); + Checks::check_exit(VCPKG_LINE_INFO, !remove_plan.empty(), "Remove plan cannot be empty"); + + std::map> group_by_plan_type; + Util::group_by(remove_plan, &group_by_plan_type, [](const RemovePlanAction& p) { return p.plan_type; }); + print_plan(group_by_plan_type); + + const bool has_non_user_requested_packages = + Util::find_if(remove_plan, [](const RemovePlanAction& package) -> bool { + return package.request_type != RequestType::USER_REQUESTED; + }) != remove_plan.cend(); + + if (has_non_user_requested_packages) + { + System::println(System::Color::warning, + "Additional packages (*) need to be removed to complete this operation."); + + if (!is_recursive) + { + System::println(System::Color::warning, + "If you are sure you want to remove them, run the command with the --recurse option"); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } + + if (dry_run) + { + Checks::exit_success(VCPKG_LINE_INFO); + } + + for (const RemovePlanAction& action : remove_plan) + { + perform_remove_plan_action(paths, action, purge, status_db); + } + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp new file mode 100644 index 000000000..d766dcb72 --- /dev/null +++ b/toolsrc/src/vcpkg/sourceparagraph.cpp @@ -0,0 +1,264 @@ +#include "pch.h" + +#include +#include +#include + +#include +#include +#include +#include + +namespace vcpkg +{ + using namespace vcpkg::Parse; + + namespace SourceParagraphFields + { + static const std::string BUILD_DEPENDS = "Build-Depends"; + static const std::string DEFAULTFEATURES = "Default-Features"; + static const std::string DESCRIPTION = "Description"; + static const std::string FEATURE = "Feature"; + static const std::string MAINTAINER = "Maintainer"; + static const std::string SOURCE = "Source"; + static const std::string SUPPORTS = "Supports"; + static const std::string VERSION = "Version"; + } + + static Span get_list_of_valid_fields() + { + static const std::string valid_fields[] = { + SourceParagraphFields::SOURCE, + SourceParagraphFields::VERSION, + SourceParagraphFields::DESCRIPTION, + SourceParagraphFields::MAINTAINER, + SourceParagraphFields::BUILD_DEPENDS, + }; + + return valid_fields; + } + + void print_error_message(Span> error_info_list) + { + Checks::check_exit(VCPKG_LINE_INFO, error_info_list.size() > 0); + + for (auto&& error_info : error_info_list) + { + Checks::check_exit(VCPKG_LINE_INFO, error_info != nullptr); + if (error_info->error) + { + System::println( + System::Color::error, "Error: while loading %s: %s", error_info->name, error_info->error.message()); + } + } + + bool have_remaining_fields = false; + for (auto&& error_info : error_info_list) + { + if (!error_info->extra_fields.empty()) + { + System::println(System::Color::error, + "Error: There are invalid fields in the control file of %s", + error_info->name); + System::println("The following fields were not expected:\n\n %s\n", + Strings::join("\n ", error_info->extra_fields)); + have_remaining_fields = true; + } + } + + if (have_remaining_fields) + { + System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", + Strings::join("\n ", get_list_of_valid_fields())); + System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); + } + + for (auto&& error_info : error_info_list) + { + if (!error_info->missing_fields.empty()) + { + System::println(System::Color::error, + "Error: There are missing fields in the control file of %s", + error_info->name); + System::println("The following fields were missing:\n\n %s\n", + Strings::join("\n ", error_info->missing_fields)); + } + } + } + + static ParseExpected parse_source_paragraph(RawParagraph&& fields) + { + ParagraphParser parser(std::move(fields)); + + auto spgh = std::make_unique(); + + parser.required_field(SourceParagraphFields::SOURCE, spgh->name); + parser.required_field(SourceParagraphFields::VERSION, spgh->version); + + spgh->description = parser.optional_field(SourceParagraphFields::DESCRIPTION); + spgh->maintainer = parser.optional_field(SourceParagraphFields::MAINTAINER); + spgh->depends = expand_qualified_dependencies( + parse_comma_list(parser.optional_field(SourceParagraphFields::BUILD_DEPENDS))); + spgh->supports = parse_comma_list(parser.optional_field(SourceParagraphFields::SUPPORTS)); + spgh->default_features = parse_comma_list(parser.optional_field(SourceParagraphFields::DEFAULTFEATURES)); + + auto err = parser.error_info(spgh->name); + if (err) + return std::move(err); + else + return std::move(spgh); + } + + static ParseExpected parse_feature_paragraph(RawParagraph&& fields) + { + ParagraphParser parser(std::move(fields)); + + auto fpgh = std::make_unique(); + + parser.required_field(SourceParagraphFields::FEATURE, fpgh->name); + parser.required_field(SourceParagraphFields::DESCRIPTION, fpgh->description); + + fpgh->depends = expand_qualified_dependencies( + parse_comma_list(parser.optional_field(SourceParagraphFields::BUILD_DEPENDS))); + + auto err = parser.error_info(fpgh->name); + if (err) + return std::move(err); + else + return std::move(fpgh); + } + + ParseExpected SourceControlFile::parse_control_file( + std::vector>&& control_paragraphs) + { + if (control_paragraphs.size() == 0) + { + return std::make_unique(); + } + + auto control_file = std::make_unique(); + + auto maybe_source = parse_source_paragraph(std::move(control_paragraphs.front())); + if (const auto source = maybe_source.get()) + control_file->core_paragraph = std::move(*source); + else + return std::move(maybe_source).error(); + + control_paragraphs.erase(control_paragraphs.begin()); + + for (auto&& feature_pgh : control_paragraphs) + { + auto maybe_feature = parse_feature_paragraph(std::move(feature_pgh)); + if (const auto feature = maybe_feature.get()) + control_file->feature_paragraphs.emplace_back(std::move(*feature)); + else + return std::move(maybe_feature).error(); + } + + return std::move(control_file); + } + + Dependency Dependency::parse_dependency(std::string name, std::string qualifier) + { + Dependency dep; + dep.qualifier = qualifier; + if (auto maybe_features = Features::from_string(name)) + dep.depend = *maybe_features.get(); + else + Checks::exit_with_message( + VCPKG_LINE_INFO, "error while parsing dependency: %s: %s", to_string(maybe_features.error()), name); + return dep; + } + + std::string Dependency::name() const + { + if (this->depend.features.empty()) return this->depend.name; + + const std::string features = Strings::join(",", this->depend.features); + return Strings::format("%s[%s]", this->depend.name, features); + } + + std::vector vcpkg::expand_qualified_dependencies(const std::vector& depends) + { + return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency { + auto pos = depend_string.find(' '); + if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, Strings::EMPTY); + // expect of the form "\w+ \[\w+\]" + Dependency dep; + + dep.depend.name = depend_string.substr(0, pos); + if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')') + { + // Error, but for now just slurp the entire string. + return Dependency::parse_dependency(depend_string, Strings::EMPTY); + } + dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3); + return dep; + }); + } + + std::vector filter_dependencies(const std::vector& deps, const Triplet& t) + { + std::vector ret; + for (auto&& dep : deps) + { + if (dep.qualifier.empty() || t.canonical_name().find(dep.qualifier) != std::string::npos) + { + ret.emplace_back(dep.name()); + } + } + return ret; + } + + std::vector filter_dependencies_to_specs(const std::vector& deps, const Triplet& t) + { + return FeatureSpec::from_strings_and_triplet(filter_dependencies(deps, t), t); + } + + std::string to_string(const Dependency& dep) { return dep.name(); } + + ExpectedT> Supports::parse(const std::vector& strs) + { + Supports ret; + std::vector unrecognized; + + for (auto&& str : strs) + { + if (str == "x64") + ret.architectures.push_back(Architecture::X64); + else if (str == "x86") + ret.architectures.push_back(Architecture::X86); + else if (str == "arm") + ret.architectures.push_back(Architecture::ARM); + else if (str == "windows") + ret.platforms.push_back(Platform::WINDOWS); + else if (str == "uwp") + ret.platforms.push_back(Platform::UWP); + else if (str == "v140") + ret.toolsets.push_back(ToolsetVersion::V140); + else if (str == "v141") + ret.toolsets.push_back(ToolsetVersion::V141); + else if (str == "crt-static") + ret.crt_linkages.push_back(Linkage::STATIC); + else if (str == "crt-dynamic") + ret.crt_linkages.push_back(Linkage::DYNAMIC); + else + unrecognized.push_back(str); + } + + if (unrecognized.empty()) + return std::move(ret); + else + return std::move(unrecognized); + } + + bool Supports::is_supported(Architecture arch, Platform plat, Linkage crt, ToolsetVersion tools) + { + const auto is_in_or_empty = [](auto v, auto&& c) -> bool { return c.empty() || c.end() != Util::find(c, v); }; + if (!is_in_or_empty(arch, architectures)) return false; + if (!is_in_or_empty(plat, platforms)) return false; + if (!is_in_or_empty(crt, crt_linkages)) return false; + if (!is_in_or_empty(tools, toolsets)) return false; + return true; + } +} diff --git a/toolsrc/src/vcpkg/statusparagraph.cpp b/toolsrc/src/vcpkg/statusparagraph.cpp new file mode 100644 index 000000000..5f00825e1 --- /dev/null +++ b/toolsrc/src/vcpkg/statusparagraph.cpp @@ -0,0 +1,86 @@ +#include "pch.h" + +#include + +using namespace vcpkg::Parse; + +namespace vcpkg +{ + namespace BinaryParagraphRequiredField + { + static const std::string STATUS = "Status"; + } + + StatusParagraph::StatusParagraph() : want(Want::ERROR_STATE), state(InstallState::ERROR_STATE) {} + + void serialize(const StatusParagraph& pgh, std::string& out_str) + { + serialize(pgh.package, out_str); + out_str.append("Status: ") + .append(to_string(pgh.want)) + .append(" ok ") + .append(to_string(pgh.state)) + .push_back('\n'); + } + + StatusParagraph::StatusParagraph(std::unordered_map&& fields) + { + auto status_it = fields.find(BinaryParagraphRequiredField::STATUS); + Checks::check_exit(VCPKG_LINE_INFO, status_it != fields.end(), "Expected 'Status' field in status paragraph"); + std::string status_field = std::move(status_it->second); + fields.erase(status_it); + + this->package = BinaryParagraph(std::move(fields)); + + auto b = status_field.begin(); + const auto mark = b; + const auto e = status_field.end(); + + // Todo: improve error handling + while (b != e && *b != ' ') + ++b; + + want = [](const std::string& text) { + if (text == "unknown") return Want::UNKNOWN; + if (text == "install") return Want::INSTALL; + if (text == "hold") return Want::HOLD; + if (text == "deinstall") return Want::DEINSTALL; + if (text == "purge") return Want::PURGE; + return Want::ERROR_STATE; + }(std::string(mark, b)); + + if (std::distance(b, e) < 4) return; + b += 4; + + state = [](const std::string& text) { + if (text == "not-installed") return InstallState::NOT_INSTALLED; + if (text == "installed") return InstallState::INSTALLED; + if (text == "half-installed") return InstallState::HALF_INSTALLED; + return InstallState::ERROR_STATE; + }(std::string(b, e)); + } + + std::string to_string(InstallState f) + { + switch (f) + { + case InstallState::HALF_INSTALLED: return "half-installed"; + case InstallState::INSTALLED: return "installed"; + case InstallState::NOT_INSTALLED: return "not-installed"; + default: return "error"; + } + } + + std::string to_string(Want f) + { + switch (f) + { + case Want::DEINSTALL: return "deinstall"; + case Want::HOLD: return "hold"; + case Want::INSTALL: return "install"; + case Want::PURGE: return "purge"; + case Want::UNKNOWN: return "unknown"; + default: return "error"; + } + } +} diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp new file mode 100644 index 000000000..647ed6d3f --- /dev/null +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -0,0 +1,89 @@ +#include "pch.h" + +#include +#include + +namespace vcpkg +{ + StatusParagraphs::StatusParagraphs() = default; + + StatusParagraphs::StatusParagraphs(std::vector>&& ps) + : paragraphs(std::move(ps)){}; + + StatusParagraphs::const_iterator StatusParagraphs::find(const std::string& name, const Triplet& triplet) const + { + return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { + const PackageSpec& spec = pgh->package.spec; + return spec.name() == name && spec.triplet() == triplet; + }); + } + + StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, const Triplet& triplet) + { + return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { + const PackageSpec& spec = pgh->package.spec; + return spec.name() == name && spec.triplet() == triplet; + }); + } + + std::vector*> StatusParagraphs::find_all(const std::string& name, + const Triplet& triplet) + { + std::vector*> spghs; + for (auto&& p : *this) + { + if (p->package.spec.name() == name && p->package.spec.triplet() == triplet) + { + spghs.emplace_back(&p); + } + } + return spghs; + } + + StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, + const Triplet& triplet, + const std::string& feature) + { + return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { + const PackageSpec& spec = pgh->package.spec; + return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature; + }); + } + + StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name, + const Triplet& triplet) const + { + const const_iterator it = find(name, triplet); + if (it != end() && (*it)->want == Want::INSTALL && (*it)->state == InstallState::INSTALLED) + { + return it; + } + + return end(); + } + + StatusParagraphs::iterator StatusParagraphs::insert(std::unique_ptr pgh) + { + Checks::check_exit(VCPKG_LINE_INFO, pgh != nullptr, "Inserted null paragraph"); + const PackageSpec& spec = pgh->package.spec; + const auto ptr = find(spec.name(), spec.triplet(), pgh->package.feature); + if (ptr == end()) + { + paragraphs.push_back(std::move(pgh)); + return paragraphs.rbegin(); + } + + // consume data from provided pgh. + **ptr = std::move(*pgh); + return ptr; + } + + void serialize(const StatusParagraphs& pghs, std::string& out_str) + { + for (auto& pgh : pghs.paragraphs) + { + serialize(*pgh, out_str); + out_str.push_back('\n'); + } + } +} diff --git a/toolsrc/src/vcpkg/triplet.cpp b/toolsrc/src/vcpkg/triplet.cpp new file mode 100644 index 000000000..8a84ee2b2 --- /dev/null +++ b/toolsrc/src/vcpkg/triplet.cpp @@ -0,0 +1,55 @@ +#include "pch.h" + +#include +#include +#include + +namespace vcpkg +{ + struct TripletInstance + { + TripletInstance(std::string&& s) : value(std::move(s)), hash(std::hash()(value)) {} + + const std::string value; + const size_t hash = 0; + + bool operator==(const TripletInstance& o) const { return o.value == value; } + }; + const TripletInstance Triplet::DEFAULT_INSTANCE({}); +} + +template<> +struct std::hash +{ + size_t operator()(const vcpkg::TripletInstance& t) const { return t.hash; } +}; + +namespace vcpkg +{ + static std::unordered_set g_triplet_instances; + + const Triplet Triplet::X86_WINDOWS = from_canonical_name("x86-windows"); + const Triplet Triplet::X64_WINDOWS = from_canonical_name("x64-windows"); + const Triplet Triplet::X86_UWP = from_canonical_name("x86-uwp"); + const Triplet Triplet::X64_UWP = from_canonical_name("x64-uwp"); + const Triplet Triplet::ARM_UWP = from_canonical_name("arm-uwp"); + + bool Triplet::operator==(const Triplet& other) const { return this->m_instance == other.m_instance; } + + bool operator!=(const Triplet& left, const Triplet& right) { return !(left == right); } + + Triplet Triplet::from_canonical_name(const std::string& triplet_as_string) + { + std::string s(Strings::ascii_to_lowercase(triplet_as_string)); + const auto it = std::find(s.cbegin(), s.cend(), '-'); + Checks::check_exit(VCPKG_LINE_INFO, it != s.cend(), "Invalid triplet: %s", triplet_as_string); + + const auto p = g_triplet_instances.emplace(std::move(s)); + return &*p.first; + } + + const std::string& Triplet::canonical_name() const { return this->m_instance->value; } + + const std::string& Triplet::to_string() const { return this->canonical_name(); } + size_t Triplet::hash_code() const { return m_instance->hash; } +} diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp new file mode 100644 index 000000000..168949bc1 --- /dev/null +++ b/toolsrc/src/vcpkg/update.cpp @@ -0,0 +1,75 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Update +{ + bool OutdatedPackage::compare_by_name(const OutdatedPackage& left, const OutdatedPackage& right) + { + return left.spec.name() < right.spec.name(); + } + + std::vector find_outdated_packages(const VcpkgPaths& paths, const StatusParagraphs& status_db) + { + const std::map src_names_to_versions = + Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports); + const std::vector installed_packages = get_installed_ports(status_db); + + std::vector output; + for (const StatusParagraph* pgh : installed_packages) + { + const auto it = src_names_to_versions.find(pgh->package.spec.name()); + if (it == src_names_to_versions.end()) + { + // Package was not installed from portfile + continue; + } + if (it->second != pgh->package.version) + { + output.push_back({pgh->package.spec, VersionDiff(pgh->package.version, it->second)}); + } + } + + return output; + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + args.check_exact_arg_count(0); + args.check_and_get_optional_command_arguments({}); + System::println("Using local portfile versions. To update the local portfiles, use `git pull`."); + + const StatusParagraphs status_db = database_load_check(paths); + + const auto outdated_packages = + SortedVector(find_outdated_packages(paths, status_db), &OutdatedPackage::compare_by_name); + + if (outdated_packages.empty()) + { + System::println("No packages need updating."); + } + else + { + std::string install_line; + System::println("The following packages differ from their port versions:"); + for (auto&& package : outdated_packages) + { + install_line += package.spec.to_string(); + install_line += " "; + System::println(" %-32s %s", package.spec, package.version_diff.to_string()); + } + System::println("\n" + "To update these packages, run\n" + " .\\vcpkg remove --outdated\n" + " .\\vcpkg install " + + install_line); + } + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp new file mode 100644 index 000000000..522961693 --- /dev/null +++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp @@ -0,0 +1,284 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include + +namespace vcpkg +{ + static void parse_value(const std::string* arg_begin, + const std::string* arg_end, + const std::string& option_name, + std::unique_ptr& option_field) + { + if (arg_begin == arg_end) + { + System::println(System::Color::error, "Error: expected value after %s", option_name); + Metrics::g_metrics.lock()->track_property("error", "error option name"); + Help::print_usage(); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + if (option_field != nullptr) + { + System::println(System::Color::error, "Error: %s specified multiple times", option_name); + Metrics::g_metrics.lock()->track_property("error", "error option specified multiple times"); + Help::print_usage(); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + option_field = std::make_unique(*arg_begin); + } + + static void parse_switch(bool new_setting, const std::string& option_name, Optional& option_field) + { + if (option_field && option_field != new_setting) + { + System::println(System::Color::error, "Error: conflicting values specified for --%s", option_name); + Metrics::g_metrics.lock()->track_property("error", "error conflicting switches"); + Help::print_usage(); + Checks::exit_fail(VCPKG_LINE_INFO); + } + option_field = new_setting; + } + + VcpkgCmdArguments VcpkgCmdArguments::create_from_command_line(const int argc, const wchar_t* const* const argv) + { + std::vector v; + for (int i = 1; i < argc; ++i) + { + v.push_back(Strings::to_utf8(argv[i])); + } + + return VcpkgCmdArguments::create_from_arg_sequence(v.data(), v.data() + v.size()); + } + + VcpkgCmdArguments VcpkgCmdArguments::create_from_arg_sequence(const std::string* arg_begin, + const std::string* arg_end) + { + VcpkgCmdArguments args; + + for (; arg_begin != arg_end; ++arg_begin) + { + std::string arg = *arg_begin; + + if (arg.empty()) + { + continue; + } + + if (arg[0] == '-' && arg[1] != '-') + { + Metrics::g_metrics.lock()->track_property("error", "error short options are not supported"); + Checks::exit_with_message(VCPKG_LINE_INFO, "Error: short options are not supported: %s", arg); + } + + if (arg[0] == '-' && arg[1] == '-') + { + // make argument case insensitive + auto& f = std::use_facet>(std::locale()); + f.tolower(&arg[0], &arg[0] + arg.size()); + // command switch + if (arg == "--vcpkg-root") + { + ++arg_begin; + parse_value(arg_begin, arg_end, "--vcpkg-root", args.vcpkg_root_dir); + continue; + } + if (arg == "--triplet") + { + ++arg_begin; + parse_value(arg_begin, arg_end, "--triplet", args.triplet); + continue; + } + if (arg == "--debug") + { + parse_switch(true, "debug", args.debug); + continue; + } + if (arg == "--sendmetrics") + { + parse_switch(true, "sendmetrics", args.sendmetrics); + continue; + } + if (arg == "--printmetrics") + { + parse_switch(true, "printmetrics", args.printmetrics); + continue; + } + if (arg == "--no-sendmetrics") + { + parse_switch(false, "sendmetrics", args.sendmetrics); + continue; + } + if (arg == "--no-printmetrics") + { + parse_switch(false, "printmetrics", args.printmetrics); + continue; + } + if (arg == "--featurepackages") + { + GlobalState::feature_packages = true; + continue; + } + + const auto eq_pos = arg.find('='); + if (eq_pos != std::string::npos) + { + args.optional_command_arguments.emplace(arg.substr(0, eq_pos), arg.substr(eq_pos + 1)); + } + else + { + args.optional_command_arguments.emplace(arg, nullopt); + } + continue; + } + + if (args.command.empty()) + { + args.command = arg; + } + else + { + args.command_arguments.push_back(arg); + } + } + + return args; + } + + ParsedArguments VcpkgCmdArguments::check_and_get_optional_command_arguments( + const std::vector& valid_switches, const std::vector& valid_settings) const + { + bool failed = false; + ParsedArguments output; + + auto options_copy = this->optional_command_arguments; + for (const std::string& option : valid_switches) + { + const auto it = options_copy.find(option); + if (it != options_copy.end()) + { + if (it->second.has_value()) + { + // Having a string value indicates it was passed like '--a=xyz' + System::println(System::Color::error, "The option '%s' does not accept an argument.", option); + failed = true; + } + else + { + output.switches.insert(option); + options_copy.erase(it); + } + } + } + + for (const std::string& option : valid_settings) + { + const auto it = options_copy.find(option); + if (it != options_copy.end()) + { + if (!it->second.has_value()) + { + // Not having a string value indicates it was passed like '--a' + System::println(System::Color::error, "The option '%s' must be passed an argument.", option); + failed = true; + } + else + { + output.settings.emplace(option, it->second.value_or_exit(VCPKG_LINE_INFO)); + options_copy.erase(it); + } + } + } + + if (!options_copy.empty()) + { + System::println(System::Color::error, "Unknown option(s) for command '%s':", this->command); + for (auto&& option : options_copy) + { + System::println(" %s", option.first); + } + System::println("\nValid options are:", this->command); + for (auto&& option : valid_switches) + { + System::println(" %s", option); + } + for (auto&& option : valid_settings) + { + System::println(" %s=...", option); + } + System::println(" --triplet "); + System::println(" --vcpkg-root "); + + Checks::exit_fail(VCPKG_LINE_INFO); + } + if (failed) Checks::exit_fail(VCPKG_LINE_INFO); + + return output; + } + + void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count) const + { + return check_max_arg_count(expected_arg_count, Strings::EMPTY); + } + + void VcpkgCmdArguments::check_min_arg_count(const size_t expected_arg_count) const + { + return check_min_arg_count(expected_arg_count, Strings::EMPTY); + } + + void VcpkgCmdArguments::check_exact_arg_count(const size_t expected_arg_count) const + { + return check_exact_arg_count(expected_arg_count, Strings::EMPTY); + } + + void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count, const std::string& example_text) const + { + const size_t actual_arg_count = command_arguments.size(); + if (actual_arg_count > expected_arg_count) + { + System::println(System::Color::error, + "Error: `%s` requires at most %u arguments, but %u were provided", + this->command, + expected_arg_count, + actual_arg_count); + System::print(example_text); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } + + void VcpkgCmdArguments::check_min_arg_count(const size_t expected_arg_count, const std::string& example_text) const + { + const size_t actual_arg_count = command_arguments.size(); + if (actual_arg_count < expected_arg_count) + { + System::println(System::Color::error, + "Error: `%s` requires at least %u arguments, but %u were provided", + this->command, + expected_arg_count, + actual_arg_count); + System::print(example_text); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } + + void VcpkgCmdArguments::check_exact_arg_count(const size_t expected_arg_count, + const std::string& example_text) const + { + const size_t actual_arg_count = command_arguments.size(); + if (actual_arg_count != expected_arg_count) + { + System::println(System::Color::error, + "Error: `%s` requires %u arguments, but %u were provided", + this->command, + expected_arg_count, + actual_arg_count); + System::print(example_text); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } +} diff --git a/toolsrc/src/vcpkg/vcpkglib.cpp b/toolsrc/src/vcpkg/vcpkglib.cpp new file mode 100644 index 000000000..23c774210 --- /dev/null +++ b/toolsrc/src/vcpkg/vcpkglib.cpp @@ -0,0 +1,247 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include + +namespace vcpkg +{ + static StatusParagraphs load_current_database(Files::Filesystem& fs, + const fs::path& vcpkg_dir_status_file, + const fs::path& vcpkg_dir_status_file_old) + { + if (!fs.exists(vcpkg_dir_status_file)) + { + if (!fs.exists(vcpkg_dir_status_file_old)) + { + // no status file, use empty db + return StatusParagraphs(); + } + + fs.rename(vcpkg_dir_status_file_old, vcpkg_dir_status_file); + } + + auto pghs = Paragraphs::get_paragraphs(fs, vcpkg_dir_status_file).value_or_exit(VCPKG_LINE_INFO); + + std::vector> status_pghs; + for (auto&& p : pghs) + { + status_pghs.push_back(std::make_unique(std::move(p))); + } + + return StatusParagraphs(std::move(status_pghs)); + } + + StatusParagraphs database_load_check(const VcpkgPaths& paths) + { + auto& fs = paths.get_filesystem(); + + const auto updates_dir = paths.vcpkg_dir_updates; + + std::error_code ec; + fs.create_directory(paths.installed, ec); + fs.create_directory(paths.vcpkg_dir, ec); + fs.create_directory(paths.vcpkg_dir_info, ec); + fs.create_directory(updates_dir, ec); + + const fs::path& status_file = paths.vcpkg_dir_status_file; + const fs::path status_file_old = status_file.parent_path() / "status-old"; + const fs::path status_file_new = status_file.parent_path() / "status-new"; + + StatusParagraphs current_status_db = load_current_database(fs, status_file, status_file_old); + + auto update_files = fs.get_files_non_recursive(updates_dir); + if (update_files.empty()) + { + // updates directory is empty, control file is up-to-date. + return current_status_db; + } + for (auto&& file : update_files) + { + if (!fs.is_regular_file(file)) continue; + if (file.filename() == "incomplete") continue; + + auto pghs = Paragraphs::get_paragraphs(fs, file).value_or_exit(VCPKG_LINE_INFO); + for (auto&& p : pghs) + { + current_status_db.insert(std::make_unique(std::move(p))); + } + } + + fs.write_contents(status_file_new, Strings::serialize(current_status_db)); + + fs.rename(status_file_new, status_file); + + for (auto&& file : update_files) + { + if (!fs.is_regular_file(file)) continue; + + fs.remove(file); + } + + return current_status_db; + } + + void write_update(const VcpkgPaths& paths, const StatusParagraph& p) + { + static int update_id = 0; + auto& fs = paths.get_filesystem(); + + const auto my_update_id = update_id++; + const auto tmp_update_filename = paths.vcpkg_dir_updates / "incomplete"; + const auto update_filename = paths.vcpkg_dir_updates / std::to_string(my_update_id); + + fs.write_contents(tmp_update_filename, Strings::serialize(p)); + fs.rename(tmp_update_filename, update_filename); + } + + static void upgrade_to_slash_terminated_sorted_format(Files::Filesystem& fs, + std::vector* lines, + const fs::path& listfile_path) + { + static bool was_tracked = false; + + if (lines->empty()) + { + return; + } + + if (lines->at(0).back() == '/') + { + return; // File already in the new format + } + + if (!was_tracked) + { + was_tracked = true; + Metrics::g_metrics.lock()->track_property("listfile", "update to new format"); + } + + // The files are sorted such that directories are placed just before the files they contain + // (They are not necessarily sorted alphabetically, e.g. libflac) + // Therefore we can detect the entries that represent directories by comparing every element with the next one + // and checking if the next has a slash immediately after the current one's length + for (size_t i = 0; i < lines->size() - 1; i++) + { + std::string& current_string = lines->at(i); + const std::string& next_string = lines->at(i + 1); + + const size_t potential_slash_char_index = current_string.length(); + // Make sure the index exists first + if (next_string.size() > potential_slash_char_index && next_string.at(potential_slash_char_index) == '/') + { + current_string += '/'; // Mark as a directory + } + } + + // After suffixing the directories with a slash, we can now sort. + // We cannot sort before adding the suffixes because the following (actual example): + /* + x86-windows/include/FLAC <<<<<< This would be separated from its group due to sorting + x86-windows/include/FLAC/all.h + x86-windows/include/FLAC/assert.h + x86-windows/include/FLAC/callback.h + x86-windows/include/FLAC++ + x86-windows/include/FLAC++/all.h + x86-windows/include/FLAC++/decoder.h + x86-windows/include/FLAC++/encoder.h + * + x86-windows/include/FLAC/ <<<<<< This will now be kept with its group when sorting + x86-windows/include/FLAC/all.h + x86-windows/include/FLAC/assert.h + x86-windows/include/FLAC/callback.h + x86-windows/include/FLAC++/ + x86-windows/include/FLAC++/all.h + x86-windows/include/FLAC++/decoder.h + x86-windows/include/FLAC++/encoder.h + */ + // Note that after sorting, the FLAC++/ group will be placed before the FLAC/ group + // The new format is lexicographically sorted + std::sort(lines->begin(), lines->end()); + + // Replace the listfile on disk + const fs::path updated_listfile_path = listfile_path.generic_string() + "_updated"; + fs.write_lines(updated_listfile_path, *lines); + fs.rename(updated_listfile_path, listfile_path); + } + + std::vector get_installed_ports(const StatusParagraphs& status_db) + { + std::vector installed_packages; + for (auto&& pgh : status_db) + { + if (pgh->state != InstallState::INSTALLED || pgh->want != Want::INSTALL) continue; + installed_packages.push_back(pgh.get()); + } + + return installed_packages; + } + + std::vector get_installed_files(const VcpkgPaths& paths, + const StatusParagraphs& status_db) + { + auto& fs = paths.get_filesystem(); + + std::vector installed_files; + + for (const std::unique_ptr& pgh : status_db) + { + if (pgh->state != InstallState::INSTALLED || !pgh->package.feature.empty()) + { + continue; + } + + const fs::path listfile_path = paths.listfile_path(pgh->package); + std::vector installed_files_of_current_pgh = + fs.read_lines(listfile_path).value_or_exit(VCPKG_LINE_INFO); + Strings::trim_all_and_remove_whitespace_strings(&installed_files_of_current_pgh); + upgrade_to_slash_terminated_sorted_format(fs, &installed_files_of_current_pgh, listfile_path); + + // Remove the directories + Util::erase_remove_if(installed_files_of_current_pgh, + [](const std::string& file) { return file.back() == '/'; }); + + StatusParagraphAndAssociatedFiles pgh_and_files = { + *pgh, SortedVector(std::move(installed_files_of_current_pgh))}; + installed_files.push_back(std::move(pgh_and_files)); + } + + return installed_files; + } + + CMakeVariable::CMakeVariable(const CWStringView varname, const wchar_t* varvalue) + : s(Strings::wformat(LR"("-D%s=%s")", varname, varvalue)) + { + } + CMakeVariable::CMakeVariable(const CWStringView varname, const std::string& varvalue) + : CMakeVariable(varname, Strings::to_utf16(varvalue).c_str()) + { + } + CMakeVariable::CMakeVariable(const CWStringView varname, const std::wstring& varvalue) + : CMakeVariable(varname, varvalue.c_str()) + { + } + CMakeVariable::CMakeVariable(const CWStringView varname, const fs::path& path) + : CMakeVariable(varname, path.generic_wstring()) + { + } + + std::wstring make_cmake_cmd(const fs::path& cmake_exe, + const fs::path& cmake_script, + const std::vector& pass_variables) + { + const std::wstring cmd_cmake_pass_variables = Strings::join(L" ", pass_variables, [](auto&& v) { return v.s; }); + return Strings::wformat( + LR"("%s" %s -P "%s")", cmake_exe.native(), cmd_cmake_pass_variables, cmake_script.generic_wstring()); + } + + std::string shorten_text(const std::string& desc, size_t length) + { + Checks::check_exit(VCPKG_LINE_INFO, length >= 3); + auto simple_desc = std::regex_replace(desc, std::regex("\\s+"), " "); + return simple_desc.size() <= length ? simple_desc : simple_desc.substr(0, length - 3) + "..."; + } +} diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp new file mode 100644 index 000000000..e1a4acd69 --- /dev/null +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -0,0 +1,519 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace vcpkg +{ + static constexpr CWStringView V_120 = L"v120"; + static constexpr CWStringView V_140 = L"v140"; + static constexpr CWStringView V_141 = L"v141"; + + static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd, + const std::array& expected_version) + { + static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###"); + + const auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s)", version_cmd)); + if (rc.exit_code != 0) + { + return false; + } + + std::match_results match; + const auto found = std::regex_search(rc.output, match, RE); + if (!found) + { + return false; + } + + const int d1 = atoi(match[1].str().c_str()); + const int d2 = atoi(match[2].str().c_str()); + const int d3 = atoi(match[3].str().c_str()); + if (d1 > expected_version[0] || (d1 == expected_version[0] && d2 > expected_version[1]) || + (d1 == expected_version[0] && d2 == expected_version[1] && d3 >= expected_version[2])) + { + // satisfactory version found + return true; + } + + return false; + } + + static Optional find_if_has_equal_or_greater_version(const std::vector& candidate_paths, + const std::wstring& version_check_arguments, + const std::array& expected_version) + { + auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { + const std::wstring cmd = Strings::wformat(LR"("%s" %s)", p.native(), version_check_arguments); + return exists_and_has_equal_or_greater_version(cmd, expected_version); + }); + + if (it != candidate_paths.cend()) + { + return std::move(*it); + } + + return nullopt; + } + + static fs::path fetch_dependency(const fs::path& scripts_folder, + const std::wstring& tool_name, + const fs::path& expected_downloaded_path, + const std::array& version) + { + const std::string tool_name_utf8 = Strings::to_utf8(tool_name); + const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); + System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", + tool_name_utf8, + version_as_string, + tool_name_utf8, + version_as_string); + const fs::path script = scripts_folder / "fetchDependency.ps1"; + const auto install_cmd = + System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name)); + const System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd); + if (rc.exit_code) + { + System::println(System::Color::error, + "Launching powershell failed or was denied when trying to fetch %s version %s.\n" + "(No sufficient installed version was found)", + tool_name_utf8, + version_as_string); + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_property("error", "powershell install failed"); + locked_metrics->track_property("dependency", tool_name); + } + Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); + } + + const fs::path actual_downloaded_path = Strings::trimmed(rc.output); + std::error_code ec; + const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + eq && !ec, + "Expected dependency downloaded path to be %s, but was %s", + expected_downloaded_path.u8string(), + actual_downloaded_path.u8string()); + return actual_downloaded_path; + } + + static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + { + static constexpr std::array EXPECTED_VERSION = {3, 9, 3}; + static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; + + const fs::path downloaded_copy = downloads_folder / "cmake-3.9.3-win32-x86" / "bin" / "cmake.exe"; + const std::vector from_path = Files::find_from_PATH(L"cmake"); + + std::vector candidate_paths; + candidate_paths.push_back(downloaded_copy); + candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + candidate_paths.push_back(System::get_program_files_platform_bitness() / "CMake" / "bin" / "cmake.exe"); + candidate_paths.push_back(System::get_program_files_32_bit() / "CMake" / "bin"); + + const Optional path = + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_dependency(scripts_folder, L"cmake", downloaded_copy, EXPECTED_VERSION); + } + + fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + { + static constexpr std::array EXPECTED_VERSION = {4, 3, 0}; + static const std::wstring VERSION_CHECK_ARGUMENTS = Strings::WEMPTY; + + const fs::path downloaded_copy = downloads_folder / "nuget-4.3.0" / "nuget.exe"; + const std::vector from_path = Files::find_from_PATH(L"nuget"); + + std::vector candidate_paths; + candidate_paths.push_back(downloaded_copy); + candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + + auto path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_dependency(scripts_folder, L"nuget", downloaded_copy, EXPECTED_VERSION); + } + + fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + { + static constexpr std::array EXPECTED_VERSION = {2, 14, 1}; + static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; + + const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.1-32-bit" / "cmd" / "git.exe"; + const std::vector from_path = Files::find_from_PATH(L"git"); + + std::vector candidate_paths; + candidate_paths.push_back(downloaded_copy); + candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + candidate_paths.push_back(System::get_program_files_platform_bitness() / "git" / "cmd" / "git.exe"); + candidate_paths.push_back(System::get_program_files_32_bit() / "git" / "cmd" / "git.exe"); + + const Optional path = + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_dependency(scripts_folder, L"git", downloaded_copy, EXPECTED_VERSION); + } + + static fs::path get_ifw_installerbase_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + { + static constexpr std::array EXPECTED_VERSION = {3, 1, 81}; + static const std::wstring VERSION_CHECK_ARGUMENTS = L"--framework-version"; + + const fs::path downloaded_copy = + downloads_folder / "QtInstallerFramework-win-x86" / "bin" / "installerbase.exe"; + + std::vector candidate_paths; + candidate_paths.push_back(downloaded_copy); + // TODO: Uncomment later + // const std::vector from_path = Files::find_from_PATH(L"installerbase"); + // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / + // "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe"); + // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / + // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); + + const Optional path = + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_dependency(scripts_folder, L"installerbase", downloaded_copy, EXPECTED_VERSION); + } + + Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir) + { + std::error_code ec; + const fs::path canonical_vcpkg_root_dir = fs::stdfs::canonical(vcpkg_root_dir, ec); + if (ec) + { + return ec; + } + + VcpkgPaths paths; + paths.root = canonical_vcpkg_root_dir; + + if (paths.root.empty()) + { + Metrics::g_metrics.lock()->track_property("error", "Invalid vcpkg root directory"); + Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid vcpkg root directory: %s", paths.root.string()); + } + + paths.packages = paths.root / "packages"; + paths.buildtrees = paths.root / "buildtrees"; + paths.downloads = paths.root / "downloads"; + paths.ports = paths.root / "ports"; + paths.installed = paths.root / "installed"; + paths.triplets = paths.root / "triplets"; + paths.scripts = paths.root / "scripts"; + + paths.buildsystems = paths.scripts / "buildsystems"; + paths.buildsystems_msbuild_targets = paths.buildsystems / "msbuild" / "vcpkg.targets"; + + paths.vcpkg_dir = paths.installed / "vcpkg"; + paths.vcpkg_dir_status_file = paths.vcpkg_dir / "status"; + paths.vcpkg_dir_info = paths.vcpkg_dir / "info"; + paths.vcpkg_dir_updates = paths.vcpkg_dir / "updates"; + + paths.ports_cmake = paths.scripts / "ports.cmake"; + + return paths; + } + + fs::path VcpkgPaths::package_dir(const PackageSpec& spec) const { return this->packages / spec.dir(); } + + fs::path VcpkgPaths::port_dir(const PackageSpec& spec) const { return this->ports / spec.name(); } + fs::path VcpkgPaths::port_dir(const std::string& name) const { return this->ports / name; } + + fs::path VcpkgPaths::build_info_file_path(const PackageSpec& spec) const + { + return this->package_dir(spec) / "BUILD_INFO"; + } + + fs::path VcpkgPaths::listfile_path(const BinaryParagraph& pgh) const + { + return this->vcpkg_dir_info / (pgh.fullstem() + ".list"); + } + + bool VcpkgPaths::is_valid_triplet(const Triplet& t) const + { + for (auto&& path : get_filesystem().get_files_non_recursive(this->triplets)) + { + const std::string triplet_file_name = path.stem().generic_u8string(); + if (t.canonical_name() == triplet_file_name) // TODO: fuzzy compare + { + // t.value = triplet_file_name; // NOTE: uncomment when implementing fuzzy compare + return true; + } + } + return false; + } + + const fs::path& VcpkgPaths::get_cmake_exe() const + { + return this->cmake_exe.get_lazy([this]() { return get_cmake_path(this->downloads, this->scripts); }); + } + + const fs::path& VcpkgPaths::get_git_exe() const + { + return this->git_exe.get_lazy([this]() { return get_git_path(this->downloads, this->scripts); }); + } + + const fs::path& VcpkgPaths::get_nuget_exe() const + { + return this->nuget_exe.get_lazy([this]() { return get_nuget_path(this->downloads, this->scripts); }); + } + + const fs::path& VcpkgPaths::get_ifw_installerbase_exe() const + { + return this->ifw_installerbase_exe.get_lazy( + [this]() { return get_ifw_installerbase_path(this->downloads, this->scripts); }); + } + + const fs::path& VcpkgPaths::get_ifw_binarycreator_exe() const + { + return this->ifw_binarycreator_exe.get_lazy( + [this]() { return get_ifw_installerbase_exe().parent_path() / "binarycreator.exe"; }); + } + + const fs::path& VcpkgPaths::get_ifw_repogen_exe() const + { + return this->ifw_repogen_exe.get_lazy( + [this]() { return get_ifw_installerbase_exe().parent_path() / "repogen.exe"; }); + } + + struct VisualStudioInstance + { + fs::path root_path; + std::string version; + std::string release_type; + std::string preference_weight; // Mostly unused, just for verification that order is as intended + + std::string major_version() const { return version.substr(0, 2); } + }; + + static std::vector get_visual_studio_instances(const VcpkgPaths& paths) + { + const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; + const std::wstring cmd = System::create_powershell_script_cmd(script); + const System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); + Checks::check_exit( + VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect Visual Studio instances"); + + const std::vector instances_as_strings = Strings::split(ec_data.output, "\n"); + std::vector output; + for (const std::string& instance_as_string : instances_as_strings) + { + const std::vector split = Strings::split(instance_as_string, "::"); + output.push_back({split.at(3), split.at(2), split.at(1), split.at(0)}); + } + + return output; + } + + static std::vector find_toolset_instances(const VcpkgPaths& paths) + { + using CPU = System::CPUArchitecture; + + const auto& fs = paths.get_filesystem(); + + // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. + std::vector paths_examined; + + std::vector found_toolsets; + + const std::vector vs_instances = get_visual_studio_instances(paths); + const bool v140_is_available = Util::find_if(vs_instances, [&](const VisualStudioInstance& vs_instance) { + return vs_instance.major_version() == "14"; + }) != vs_instances.cend(); + + for (const VisualStudioInstance& vs_instance : vs_instances) + { + const std::string major_version = vs_instance.major_version(); + if (major_version == "15") + { + const fs::path vc_dir = vs_instance.root_path / "VC"; + + // Skip any instances that do not have vcvarsall. + const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build"; + const fs::path vcvarsall_bat = vcvarsall_dir / "vcvarsall.bat"; + paths_examined.push_back(vcvarsall_bat); + if (!fs.exists(vcvarsall_bat)) continue; + + // Get all supported architectures + std::vector supported_architectures; + if (fs.exists(vcvarsall_dir / "vcvars32.bat")) + supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); + if (fs.exists(vcvarsall_dir / "vcvars64.bat")) + supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) + supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) + supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) + supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) + supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + + // Locate the "best" MSVC toolchain version + const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; + std::vector msvc_subdirectories = fs.get_files_non_recursive(msvc_path); + Util::unstable_keep_if(msvc_subdirectories, + [&fs](const fs::path& path) { return fs.is_directory(path); }); + + // Sort them so that latest comes first + std::sort( + msvc_subdirectories.begin(), + msvc_subdirectories.end(), + [](const fs::path& left, const fs::path& right) { return left.filename() > right.filename(); }); + + for (const fs::path& subdir : msvc_subdirectories) + { + const fs::path dumpbin_path = subdir / "bin" / "HostX86" / "x86" / "dumpbin.exe"; + paths_examined.push_back(dumpbin_path); + if (fs.exists(dumpbin_path)) + { + found_toolsets.push_back(Toolset{ + vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}); + + if (v140_is_available) + { + found_toolsets.push_back(Toolset{vs_instance.root_path, + dumpbin_path, + vcvarsall_bat, + {L"-vcvars_ver=14.0"}, + V_140, + supported_architectures}); + } + + break; + } + } + + continue; + } + + if (major_version == "14") + { + const fs::path vcvarsall_bat = vs_instance.root_path / "VC" / "vcvarsall.bat"; + + paths_examined.push_back(vcvarsall_bat); + if (fs.exists(vcvarsall_bat)) + { + const fs::path vs2015_dumpbin_exe = vs_instance.root_path / "VC" / "bin" / "dumpbin.exe"; + paths_examined.push_back(vs2015_dumpbin_exe); + + const fs::path vs2015_bin_dir = vcvarsall_bat.parent_path() / "bin"; + std::vector supported_architectures; + if (fs.exists(vs2015_bin_dir / "vcvars32.bat")) + supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); + if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat")) + supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); + if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) + supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) + supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); + if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) + supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) + supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + + if (fs.exists(vs2015_dumpbin_exe)) + { + found_toolsets.push_back({vs_instance.root_path, + vs2015_dumpbin_exe, + vcvarsall_bat, + {}, + V_140, + supported_architectures}); + } + } + } + } + + if (found_toolsets.empty()) + { + System::println(System::Color::error, "Could not locate a complete toolset."); + System::println("The following paths were examined:"); + for (const fs::path& path : paths_examined) + { + System::println(" %s", path.u8string()); + } + Checks::exit_fail(VCPKG_LINE_INFO); + } + + return found_toolsets; + } + + const Toolset& VcpkgPaths::get_toolset(const Optional& toolset_version, + const Optional& visual_studio_path) const + { + // Invariant: toolsets are non-empty and sorted with newest at back() + const std::vector& vs_toolsets = + this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); + + std::vector candidates = Util::element_pointers(vs_toolsets); + const auto tsv = toolset_version.get(); + const auto vsp = visual_studio_path.get(); + + if (tsv && vsp) + { + const std::wstring w_toolset_version = Strings::to_utf16(*tsv); + const fs::path vs_root_path = *vsp; + Util::stable_keep_if(candidates, [&](const Toolset* t) { + return w_toolset_version == t->version && vs_root_path == t->visual_studio_root_path; + }); + Checks::check_exit(VCPKG_LINE_INFO, + !candidates.empty(), + "Could not find Visual Studio instace at %s with %s toolset.", + vs_root_path.generic_string(), + *tsv); + + Checks::check_exit(VCPKG_LINE_INFO, candidates.size() == 1); + return *candidates.back(); + } + + if (tsv) + { + const std::wstring w_toolset_version = Strings::to_utf16(*tsv); + Util::stable_keep_if(candidates, [&](const Toolset* t) { return w_toolset_version == t->version; }); + Checks::check_exit( + VCPKG_LINE_INFO, !candidates.empty(), "Could not find Visual Studio instace with %s toolset.", *tsv); + } + + if (vsp) + { + const fs::path vs_root_path = *vsp; + Util::stable_keep_if(candidates, + [&](const Toolset* t) { return vs_root_path == t->visual_studio_root_path; }); + Checks::check_exit(VCPKG_LINE_INFO, + !candidates.empty(), + "Could not find Visual Studio instace at %s.", + vs_root_path.generic_string()); + } + + return *candidates.front(); + } + + Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); } +} diff --git a/toolsrc/src/vcpkg/versiont.cpp b/toolsrc/src/vcpkg/versiont.cpp new file mode 100644 index 000000000..1c52d674a --- /dev/null +++ b/toolsrc/src/vcpkg/versiont.cpp @@ -0,0 +1,19 @@ +#include "pch.h" + +#include +#include + +namespace vcpkg +{ + VersionT::VersionT() : value("0.0.0") {} + VersionT::VersionT(const std::string& value) : value(value) {} + std::string VersionT::to_string() const { return value; } + bool operator==(const VersionT& left, const VersionT& right) { return left.value == right.value; } + bool operator!=(const VersionT& left, const VersionT& right) { return left.value != right.value; } + std::string to_printf_arg(const VersionT& version) { return version.value; } + + VersionDiff::VersionDiff() : left(), right() {} + VersionDiff::VersionDiff(const VersionT& left, const VersionT& right) : left(left), right(right) {} + + std::string VersionDiff::to_string() const { return Strings::format("%s -> %s", left.value, right.value); } +} diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp deleted file mode 100644 index 9be20629d..000000000 --- a/toolsrc/src/vcpkg_Build.cpp +++ /dev/null @@ -1,406 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "PostBuildLint.h" -#include "metrics.h" -#include "vcpkg_Build.h" -#include "vcpkg_Checks.h" -#include "vcpkg_Chrono.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Enums.h" -#include "vcpkg_GlobalState.h" -#include "vcpkg_System.h" -#include "vcpkg_optional.h" -#include "vcpkglib.h" - -namespace vcpkg::Build -{ - Optional to_linkage_type(const std::string& str) - { - if (str == "dynamic") return LinkageType::DYNAMIC; - if (str == "static") return LinkageType::STATIC; - return nullopt; - } - - namespace BuildInfoRequiredField - { - static const std::string CRT_LINKAGE = "CRTLinkage"; - static const std::string LIBRARY_LINKAGE = "LibraryLinkage"; - } - - CWStringView to_vcvarsall_target(const std::string& cmake_system_name) - { - if (cmake_system_name == Strings::EMPTY) return Strings::WEMPTY; - if (cmake_system_name == "Windows") return Strings::WEMPTY; - if (cmake_system_name == "WindowsStore") return L"store"; - - Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported vcvarsall target %s", cmake_system_name); - } - - CWStringView to_vcvarsall_toolchain(const std::string& target_architecture, const Toolset& toolset) - { - auto maybe_target_arch = System::to_cpu_architecture(target_architecture); - Checks::check_exit( - VCPKG_LINE_INFO, maybe_target_arch.has_value(), "Invalid architecture string: %s", target_architecture); - auto target_arch = maybe_target_arch.value_or_exit(VCPKG_LINE_INFO); - auto host_architectures = System::get_supported_host_architectures(); - - for (auto&& host : host_architectures) - { - auto it = Util::find_if(toolset.supported_architectures, [&](const ToolsetArchOption& opt) { - return host == opt.host_arch && target_arch == opt.target_arch; - }); - if (it != toolset.supported_architectures.end()) return it->name; - } - - Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported toolchain combination %s", target_architecture); - } - - std::wstring make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset) - { - const wchar_t* tonull = L" >nul"; - if (GlobalState::debugging) - { - tonull = Strings::WEMPTY; - } - - const auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset); - const auto target = to_vcvarsall_target(pre_build_info.cmake_system_name); - - return Strings::wformat(LR"("%s" %s %s %s %s 2>&1)", - toolset.vcvarsall.native(), - Strings::join(L" ", toolset.vcvarsall_options), - arch, - target, - tonull); - } - - static void create_binary_feature_control_file(const SourceParagraph& source_paragraph, - const FeatureParagraph& feature_paragraph, - const Triplet& triplet, - BinaryControlFile& bcf) - { - BinaryParagraph bpgh(source_paragraph, feature_paragraph, triplet); - bcf.features.emplace_back(std::move(bpgh)); - } - - static void create_binary_control_file(const SourceParagraph& source_paragraph, - const Triplet& triplet, - const BuildInfo& build_info, - BinaryControlFile& bcf) - { - BinaryParagraph bpgh(source_paragraph, triplet); - if (const auto p_ver = build_info.version.get()) - { - bpgh.version = *p_ver; - } - bcf.core_paragraph = std::move(bpgh); - } - - static void write_binary_control_file(const VcpkgPaths& paths, BinaryControlFile bcf) - { - std::string start = Strings::serialize(bcf.core_paragraph); - for (auto&& feature : bcf.features) - { - start += "\n" + Strings::serialize(feature); - } - const fs::path binary_control_file = paths.packages / bcf.core_paragraph.dir() / "CONTROL"; - paths.get_filesystem().write_contents(binary_control_file, start); - } - - ExtendedBuildResult build_package(const VcpkgPaths& paths, - const BuildPackageConfig& config, - const StatusParagraphs& status_db) - { - const PackageSpec spec = - PackageSpec::from_name_and_triplet(config.src.name, config.triplet).value_or_exit(VCPKG_LINE_INFO); - - const Triplet& triplet = config.triplet; - { - std::vector missing_specs; - for (auto&& dep : filter_dependencies(config.src.depends, triplet)) - { - if (status_db.find_installed(dep, triplet) == status_db.end()) - { - missing_specs.push_back( - PackageSpec::from_name_and_triplet(dep, triplet).value_or_exit(VCPKG_LINE_INFO)); - } - } - // Fail the build if any dependencies were missing - if (!missing_specs.empty()) - { - return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(missing_specs)}; - } - } - - const fs::path& cmake_exe_path = paths.get_cmake_exe(); - const fs::path& git_exe_path = paths.get_git_exe(); - - const fs::path ports_cmake_script_path = paths.ports_cmake; - const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); - const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); - const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); - - std::string features; - if (GlobalState::feature_packages) - { - if (config.feature_list) - { - for (auto&& feature : *config.feature_list) - { - features.append(feature + ";"); - } - if (features.size() > 0) - { - features.pop_back(); - } - } - } - - const std::wstring cmd_launch_cmake = make_cmake_cmd( - cmake_exe_path, - ports_cmake_script_path, - { - {L"CMD", L"BUILD"}, - {L"PORT", config.src.name}, - {L"CURRENT_PORT_DIR", config.port_dir / "/."}, - {L"TARGET_TRIPLET", triplet.canonical_name()}, - {L"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, - {L"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? L"1" : L"0"}, - {L"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? L"1" : L"0"}, - {L"GIT", git_exe_path}, - {L"FEATURES", features}, - }); - - const std::wstring command = Strings::wformat(LR"(%s && %s)", cmd_set_environment, cmd_launch_cmake); - - const ElapsedTime timer = ElapsedTime::create_started(); - - const int return_code = System::cmd_execute_clean(command); - const auto buildtimeus = timer.microseconds(); - const auto spec_string = spec.to_string(); - - { - auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_metric("buildtimeus-" + spec_string, buildtimeus); - if (return_code != 0) - { - locked_metrics->track_property("error", "build failed"); - locked_metrics->track_property("build_error", spec_string); - return {BuildResult::BUILD_FAILED, {}}; - } - } - - const BuildInfo build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); - const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); - - BinaryControlFile bcf; - - create_binary_control_file(config.src, triplet, build_info, bcf); - - if (error_count != 0) - { - return {BuildResult::POST_BUILD_CHECKS_FAILED, {}}; - } - if (GlobalState::feature_packages) - { - if (config.feature_list) - { - for (auto&& feature : *config.feature_list) - { - for (auto&& f_pgh : config.scf->feature_paragraphs) - { - if (f_pgh->name == feature) - create_binary_feature_control_file(*config.scf->core_paragraph, *f_pgh, triplet, bcf); - } - } - } - } - - write_binary_control_file(paths, bcf); - - // const fs::path port_buildtrees_dir = paths.buildtrees / spec.name; - // delete_directory(port_buildtrees_dir); - - return {BuildResult::SUCCEEDED, {}}; - } - - const std::string& to_string(const BuildResult build_result) - { - static const std::string NULLVALUE_STRING = Enums::nullvalue_to_string("vcpkg::Commands::Build::BuildResult"); - static const std::string SUCCEEDED_STRING = "SUCCEEDED"; - static const std::string BUILD_FAILED_STRING = "BUILD_FAILED"; - static const std::string FILE_CONFLICTS_STRING = "FILE_CONFLICTS"; - static const std::string POST_BUILD_CHECKS_FAILED_STRING = "POST_BUILD_CHECKS_FAILED"; - static const std::string CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING = "CASCADED_DUE_TO_MISSING_DEPENDENCIES"; - - switch (build_result) - { - case BuildResult::NULLVALUE: return NULLVALUE_STRING; - case BuildResult::SUCCEEDED: return SUCCEEDED_STRING; - case BuildResult::BUILD_FAILED: return BUILD_FAILED_STRING; - case BuildResult::POST_BUILD_CHECKS_FAILED: return POST_BUILD_CHECKS_FAILED_STRING; - case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: return CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING; - case BuildResult::FILE_CONFLICTS: return FILE_CONFLICTS_STRING; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - - std::string create_error_message(const BuildResult build_result, const PackageSpec& spec) - { - return Strings::format("Error: Building package %s failed with: %s", spec, Build::to_string(build_result)); - } - - std::string create_user_troubleshooting_message(const PackageSpec& spec) - { - return Strings::format("Please ensure you're using the latest portfiles with `.\\vcpkg update`, then\n" - "submit an issue at https://github.com/Microsoft/vcpkg/issues including:\n" - " Package: %s\n" - " Vcpkg version: %s\n" - "\n" - "Additionally, attach any relevant sections from the log files above.", - spec, - Commands::Version::version()); - } - - static BuildInfo inner_create_buildinfo(std::unordered_map pgh) - { - Parse::ParagraphParser parser(std::move(pgh)); - - BuildInfo build_info; - - { - std::string crt_linkage_as_string; - parser.required_field(BuildInfoRequiredField::CRT_LINKAGE, crt_linkage_as_string); - - auto crtlinkage = to_linkage_type(crt_linkage_as_string); - if (const auto p = crtlinkage.get()) - build_info.crt_linkage = *p; - else - Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid crt linkage type: [%s]", crt_linkage_as_string); - } - - { - std::string library_linkage_as_string; - parser.required_field(BuildInfoRequiredField::LIBRARY_LINKAGE, library_linkage_as_string); - auto liblinkage = to_linkage_type(library_linkage_as_string); - if (const auto p = liblinkage.get()) - build_info.library_linkage = *p; - else - Checks::exit_with_message( - VCPKG_LINE_INFO, "Invalid library linkage type: [%s]", library_linkage_as_string); - } - std::string version = parser.optional_field("Version"); - if (!version.empty()) build_info.version = std::move(version); - - std::map policies; - for (auto policy : G_ALL_POLICIES) - { - const auto setting = parser.optional_field(to_string(policy)); - if (setting.empty()) continue; - if (setting == "enabled") - policies.emplace(policy, true); - else if (setting == "disabled") - policies.emplace(policy, false); - else - Checks::exit_with_message( - VCPKG_LINE_INFO, "Unknown setting for policy '%s': %s", to_string(policy), setting); - } - - if (const auto err = parser.error_info("PostBuildInformation")) - { - print_error_message(err); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - build_info.policies = BuildPolicies(std::move(policies)); - - return build_info; - } - - BuildInfo read_build_info(const Files::Filesystem& fs, const fs::path& filepath) - { - const Expected> pghs = - Paragraphs::get_single_paragraph(fs, filepath); - Checks::check_exit(VCPKG_LINE_INFO, pghs.get() != nullptr, "Invalid BUILD_INFO file for package"); - return inner_create_buildinfo(*pghs.get()); - } - - PreBuildInfo PreBuildInfo::from_triplet_file(const VcpkgPaths& paths, const Triplet& triplet) - { - static constexpr CStringView FLAG_GUID = "c35112b6-d1ba-415b-aa5d-81de856ef8eb"; - - const fs::path& cmake_exe_path = paths.get_cmake_exe(); - const fs::path ports_cmake_script_path = paths.scripts / "get_triplet_environment.cmake"; - const fs::path triplet_file_path = paths.triplets / (triplet.canonical_name() + ".cmake"); - - const std::wstring cmd_launch_cmake = make_cmake_cmd(cmake_exe_path, - ports_cmake_script_path, - { - {L"CMAKE_TRIPLET_FILE", triplet_file_path}, - }); - - const std::wstring command = Strings::wformat(LR"(%s)", cmd_launch_cmake); - const auto ec_data = System::cmd_execute_and_capture_output(command); - Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0); - - const std::vector lines = Strings::split(ec_data.output, "\n"); - - PreBuildInfo pre_build_info; - - const auto e = lines.cend(); - auto cur = std::find(lines.cbegin(), e, FLAG_GUID); - if (cur != e) ++cur; - - for (; cur != e; ++cur) - { - auto&& line = *cur; - - const std::vector s = Strings::split(line, "="); - Checks::check_exit(VCPKG_LINE_INFO, - s.size() == 1 || s.size() == 2, - "Expected format is [VARIABLE_NAME=VARIABLE_VALUE], but was [%s]", - line); - - const bool variable_with_no_value = s.size() == 1; - const std::string variable_name = s.at(0); - const std::string variable_value = variable_with_no_value ? Strings::EMPTY : s.at(1); - - if (variable_name == "VCPKG_TARGET_ARCHITECTURE") - { - pre_build_info.target_architecture = variable_value; - continue; - } - - if (variable_name == "VCPKG_CMAKE_SYSTEM_NAME") - { - pre_build_info.cmake_system_name = variable_value; - continue; - } - - if (variable_name == "VCPKG_CMAKE_SYSTEM_VERSION") - { - pre_build_info.cmake_system_version = variable_value; - continue; - } - - if (variable_name == "VCPKG_PLATFORM_TOOLSET") - { - pre_build_info.platform_toolset = - variable_value.empty() ? nullopt : Optional{variable_value}; - continue; - } - - if (variable_name == "VCPKG_VISUAL_STUDIO_PATH") - { - pre_build_info.visual_studio_path = - variable_value.empty() ? nullopt : Optional{variable_value}; - continue; - } - - Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown variable name %s", line); - } - - return pre_build_info; - } -} diff --git a/toolsrc/src/vcpkg_Build_BuildPolicy.cpp b/toolsrc/src/vcpkg_Build_BuildPolicy.cpp deleted file mode 100644 index b3bb778dc..000000000 --- a/toolsrc/src/vcpkg_Build_BuildPolicy.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Build.h" -#include "vcpkg_Checks.h" -#include "vcpkg_Enums.h" - -namespace vcpkg::Build -{ - static const std::string NAME_EMPTY_PACKAGE = "PolicyEmptyPackage"; - static const std::string NAME_DLLS_WITHOUT_LIBS = "PolicyDLLsWithoutLIBs"; - static const std::string NAME_ONLY_RELEASE_CRT = "PolicyOnlyReleaseCRT"; - static const std::string NAME_EMPTY_INCLUDE_FOLDER = "PolicyEmptyIncludeFolder"; - static const std::string NAME_ALLOW_OBSOLETE_MSVCRT = "PolicyAllowObsoleteMsvcrt"; - - const std::string& to_string(BuildPolicy policy) - { - switch (policy) - { - case BuildPolicy::EMPTY_PACKAGE: return NAME_EMPTY_PACKAGE; - case BuildPolicy::DLLS_WITHOUT_LIBS: return NAME_DLLS_WITHOUT_LIBS; - case BuildPolicy::ONLY_RELEASE_CRT: return NAME_ONLY_RELEASE_CRT; - case BuildPolicy::EMPTY_INCLUDE_FOLDER: return NAME_EMPTY_INCLUDE_FOLDER; - case BuildPolicy::ALLOW_OBSOLETE_MSVCRT: return NAME_ALLOW_OBSOLETE_MSVCRT; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - - CStringView to_cmake_variable(BuildPolicy policy) - { - switch (policy) - { - case BuildPolicy::EMPTY_PACKAGE: return "VCPKG_POLICY_EMPTY_PACKAGE"; - case BuildPolicy::DLLS_WITHOUT_LIBS: return "VCPKG_POLICY_DLLS_WITHOUT_LIBS"; - case BuildPolicy::ONLY_RELEASE_CRT: return "VCPKG_POLICY_ONLY_RELEASE_CRT"; - case BuildPolicy::EMPTY_INCLUDE_FOLDER: return "VCPKG_POLICY_EMPTY_INCLUDE_FOLDER"; - case BuildPolicy::ALLOW_OBSOLETE_MSVCRT: return "VCPKG_POLICY_ALLOW_OBSOLETE_MSVCRT"; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } -} diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp deleted file mode 100644 index e7c9046a4..000000000 --- a/toolsrc/src/vcpkg_Checks.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "pch.h" - -#include "metrics.h" -#include "vcpkg_Checks.h" -#include "vcpkg_GlobalState.h" -#include "vcpkg_System.h" -#include "vcpkglib.h" - -namespace vcpkg::Checks -{ - [[noreturn]] static void cleanup_and_exit(const int exit_code) - { - const auto elapsed_us = GlobalState::timer.lock()->microseconds(); - - auto metrics = Metrics::g_metrics.lock(); - metrics->track_metric("elapsed_us", elapsed_us); - GlobalState::debugging = false; - metrics->flush(); - - SetConsoleCP(GlobalState::g_init_console_cp); - SetConsoleOutputCP(GlobalState::g_init_console_output_cp); - - fflush(nullptr); - - ::TerminateProcess(::GetCurrentProcess(), exit_code); - } - - static BOOL ctrl_handler(DWORD fdw_ctrl_type) - { - { - auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_property("CtrlHandler", std::to_string(fdw_ctrl_type)); - locked_metrics->track_property("error", "CtrlHandler was fired."); - } - cleanup_and_exit(EXIT_FAILURE); - } - - void register_console_ctrl_handler() - { - SetConsoleCtrlHandler(reinterpret_cast(ctrl_handler), TRUE); - } - - [[noreturn]] void unreachable(const LineInfo& line_info) - { - System::println(System::Color::error, "Error: Unreachable code was reached"); - System::println(System::Color::error, line_info.to_string()); // Always print line_info here -#ifndef NDEBUG - std::abort(); -#else - cleanup_and_exit(EXIT_FAILURE); -#endif - } - - [[noreturn]] void exit_with_code(const LineInfo& line_info, const int exit_code) - { - Debug::println(System::Color::error, line_info.to_string()); - cleanup_and_exit(exit_code); - } - - [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView error_message) - { - System::println(System::Color::error, error_message); - exit_fail(line_info); - } - - void check_exit(const LineInfo& line_info, bool expression) - { - if (!expression) - { - exit_with_message(line_info, Strings::EMPTY); - } - } - - void check_exit(const LineInfo& line_info, bool expression, const CStringView error_message) - { - if (!expression) - { - exit_with_message(line_info, error_message); - } - } -} diff --git a/toolsrc/src/vcpkg_Chrono.cpp b/toolsrc/src/vcpkg_Chrono.cpp deleted file mode 100644 index d96f30987..000000000 --- a/toolsrc/src/vcpkg_Chrono.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Checks.h" -#include "vcpkg_Chrono.h" - -namespace vcpkg -{ - static std::string format_time_userfriendly(const std::chrono::nanoseconds& nanos) - { - using std::chrono::duration_cast; - using std::chrono::hours; - using std::chrono::microseconds; - using std::chrono::milliseconds; - using std::chrono::minutes; - using std::chrono::nanoseconds; - using std::chrono::seconds; - - const double nanos_as_double = static_cast(nanos.count()); - - if (duration_cast(nanos) > hours()) - { - const auto t = nanos_as_double / duration_cast(hours(1)).count(); - return Strings::format("%.4g h", t); - } - - if (duration_cast(nanos) > minutes()) - { - const auto t = nanos_as_double / duration_cast(minutes(1)).count(); - return Strings::format("%.4g min", t); - } - - if (duration_cast(nanos) > seconds()) - { - const auto t = nanos_as_double / duration_cast(seconds(1)).count(); - return Strings::format("%.4g s", t); - } - - if (duration_cast(nanos) > milliseconds()) - { - const auto t = nanos_as_double / duration_cast(milliseconds(1)).count(); - return Strings::format("%.4g ms", t); - } - - if (duration_cast(nanos) > microseconds()) - { - const auto t = nanos_as_double / duration_cast(microseconds(1)).count(); - return Strings::format("%.4g us", t); - } - - return Strings::format("%.4g ns", nanos_as_double); - } - - ElapsedTime ElapsedTime::create_started() - { - ElapsedTime t; - t.m_start_tick = std::chrono::high_resolution_clock::now(); - return t; - } - - std::string ElapsedTime::to_string() const { return format_time_userfriendly(elapsed()); } -} diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp deleted file mode 100644 index 8dd60a2eb..000000000 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ /dev/null @@ -1,669 +0,0 @@ -#include "pch.h" - -#include "PackageSpec.h" -#include "Paragraphs.h" -#include "StatusParagraphs.h" -#include "VcpkgPaths.h" -#include "vcpkg_Dependencies.h" -#include "vcpkg_Files.h" -#include "vcpkg_Graphs.h" -#include "vcpkg_Strings.h" -#include "vcpkg_Util.h" -#include "vcpkglib.h" - -namespace vcpkg::Dependencies -{ - struct FeatureNodeEdges - { - std::vector remove_edges; - std::vector build_edges; - bool plus = false; - }; - - struct Cluster : Util::MoveOnlyBase - { - std::vector status_paragraphs; - Optional source_control_file; - PackageSpec spec; - std::unordered_map edges; - std::unordered_set to_install_features; - std::unordered_set original_features; - bool will_remove = false; - bool transient_uninstalled = true; - RequestType request_type = RequestType::AUTO_SELECTED; - }; - - struct ClusterPtr - { - Cluster* ptr; - - Cluster* operator->() const { return ptr; } - }; - - bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } -} - -template<> -struct std::hash -{ - size_t operator()(const vcpkg::Dependencies::ClusterPtr& value) const - { - return std::hash()(value.ptr->spec); - } -}; - -namespace vcpkg::Dependencies -{ - struct GraphPlan - { - Graphs::Graph remove_graph; - Graphs::Graph install_graph; - }; - - struct ClusterGraph : Util::MoveOnlyBase - { - explicit ClusterGraph(std::unordered_map&& ports) - : m_ports(std::move(ports)) - { - } - - Cluster& get(const PackageSpec& spec) - { - auto it = m_graph.find(spec); - if (it == m_graph.end()) - { - // Load on-demand from m_ports - auto it_ports = m_ports.find(spec.name()); - if (it_ports != m_ports.end()) - { - auto& clust = m_graph[spec]; - clust.spec = spec; - cluster_from_scf(*it_ports->second, clust); - return clust; - } - return m_graph[spec]; - } - return it->second; - } - - private: - void cluster_from_scf(const SourceControlFile& scf, Cluster& out_cluster) const - { - FeatureNodeEdges core_dependencies; - core_dependencies.build_edges = - filter_dependencies_to_specs(scf.core_paragraph->depends, out_cluster.spec.triplet()); - out_cluster.edges.emplace("core", std::move(core_dependencies)); - - for (const auto& feature : scf.feature_paragraphs) - { - FeatureNodeEdges added_edges; - added_edges.build_edges = filter_dependencies_to_specs(feature->depends, out_cluster.spec.triplet()); - out_cluster.edges.emplace(feature->name, std::move(added_edges)); - } - out_cluster.source_control_file = &scf; - } - - std::unordered_map m_graph; - std::unordered_map m_ports; - }; - - std::vector AnyParagraph::dependencies(const Triplet& triplet) const - { - auto to_package_specs = [&](const std::vector& dependencies_as_string) { - return Util::fmap(dependencies_as_string, [&](const std::string s) { - return PackageSpec::from_name_and_triplet(s, triplet).value_or_exit(VCPKG_LINE_INFO); - }); - }; - - if (auto p = this->status_paragraph.get()) - { - return to_package_specs(p->package.depends); - } - - if (auto p = this->binary_control_file.get()) - { - auto deps = Util::fmap_flatten(p->features, [](const BinaryParagraph& pgh) { return pgh.depends; }); - deps.insert(deps.end(), p->core_paragraph.depends.begin(), p->core_paragraph.depends.end()); - return to_package_specs(deps); - } - - if (auto p = this->source_paragraph.get()) - { - return to_package_specs(filter_dependencies(p->depends, triplet)); - } - - Checks::exit_with_message(VCPKG_LINE_INFO, - "Cannot get dependencies because there was none of: source/binary/status paragraphs"); - } - - std::string to_output_string(RequestType request_type, const CStringView s) - { - switch (request_type) - { - case RequestType::AUTO_SELECTED: return Strings::format(" * %s", s); - case RequestType::USER_REQUESTED: return Strings::format(" %s", s); - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - - InstallPlanAction::InstallPlanAction() : plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} - - InstallPlanAction::InstallPlanAction(const PackageSpec& spec, - const SourceControlFile& any_paragraph, - const std::unordered_set& features, - const RequestType& request_type) - : spec(spec), plan_type(InstallPlanType::BUILD_AND_INSTALL), request_type(request_type), feature_list(features) - { - this->any_paragraph.source_control_file = &any_paragraph; - } - - InstallPlanAction::InstallPlanAction(const PackageSpec& spec, - const std::unordered_set& features, - const RequestType& request_type) - : spec(spec), plan_type(InstallPlanType::ALREADY_INSTALLED), request_type(request_type), feature_list(features) - { - } - - InstallPlanAction::InstallPlanAction(const PackageSpec& spec, - const AnyParagraph& any_paragraph, - const RequestType& request_type) - : spec(spec), any_paragraph(any_paragraph), plan_type(InstallPlanType::UNKNOWN), request_type(request_type) - { - if (auto p = any_paragraph.status_paragraph.get()) - { - this->plan_type = InstallPlanType::ALREADY_INSTALLED; - return; - } - - if (auto p = any_paragraph.binary_control_file.get()) - { - this->plan_type = InstallPlanType::INSTALL; - return; - } - - if (auto p = any_paragraph.source_paragraph.get()) - { - this->plan_type = InstallPlanType::BUILD_AND_INSTALL; - return; - } - } - - std::string InstallPlanAction::displayname() const - { - if (this->feature_list.empty()) - { - return this->spec.to_string(); - } - - const std::string features = Strings::join(",", this->feature_list); - return Strings::format("%s[%s]:%s", this->spec.name(), features, this->spec.triplet()); - } - - bool InstallPlanAction::compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right) - { - return left->spec.name() < right->spec.name(); - } - - RemovePlanAction::RemovePlanAction() : plan_type(RemovePlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} - - RemovePlanAction::RemovePlanAction(const PackageSpec& spec, - const RemovePlanType& plan_type, - const RequestType& request_type) - : spec(spec), plan_type(plan_type), request_type(request_type) - { - } - - const PackageSpec& AnyAction::spec() const - { - if (const auto p = install_plan.get()) - { - return p->spec; - } - - if (const auto p = remove_plan.get()) - { - return p->spec; - } - - Checks::exit_with_message(VCPKG_LINE_INFO, "Null action"); - } - - bool ExportPlanAction::compare_by_name(const ExportPlanAction* left, const ExportPlanAction* right) - { - return left->spec.name() < right->spec.name(); - } - - ExportPlanAction::ExportPlanAction() : plan_type(ExportPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} - - ExportPlanAction::ExportPlanAction(const PackageSpec& spec, - const AnyParagraph& any_paragraph, - const RequestType& request_type) - : spec(spec), any_paragraph(any_paragraph), plan_type(ExportPlanType::UNKNOWN), request_type(request_type) - { - if (auto p = any_paragraph.binary_control_file.get()) - { - this->plan_type = ExportPlanType::ALREADY_BUILT; - return; - } - - if (auto p = any_paragraph.source_paragraph.get()) - { - this->plan_type = ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT; - return; - } - } - - bool RemovePlanAction::compare_by_name(const RemovePlanAction* left, const RemovePlanAction* right) - { - return left->spec.name() < right->spec.name(); - } - - MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map) {} - - const SourceControlFile& MapPortFile::get_control_file(const std::string& spec) const - { - auto scf = ports.find(spec); - if (scf == ports.end()) - { - Checks::exit_fail(VCPKG_LINE_INFO); - } - return scf->second; - } - - PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths) {} - - const SourceControlFile& PathsPortFile::get_control_file(const std::string& spec) const - { - auto cache_it = cache.find(spec); - if (cache_it != cache.end()) - { - return cache_it->second; - } - Parse::ParseExpected source_control_file = - Paragraphs::try_load_port(ports.get_filesystem(), ports.port_dir(spec)); - - if (auto scf = source_control_file.get()) - { - auto it = cache.emplace(spec, std::move(*scf->get())); - return it.first->second; - } - print_error_message(source_control_file.error()); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - std::vector create_install_plan(const PortFileProvider& port_file_provider, - const std::vector& specs, - const StatusParagraphs& status_db) - { - struct InstallAdjacencyProvider final : Graphs::AdjacencyProvider - { - const PortFileProvider& port_file_provider; - const StatusParagraphs& status_db; - const std::unordered_set& specs_as_set; - - InstallAdjacencyProvider(const PortFileProvider& port_file_provider, - const StatusParagraphs& s, - const std::unordered_set& specs_as_set) - : port_file_provider(port_file_provider), status_db(s), specs_as_set(specs_as_set) - { - } - - std::vector adjacency_list(const InstallPlanAction& plan) const override - { - if (plan.any_paragraph.status_paragraph.get()) return std::vector{}; - return plan.any_paragraph.dependencies(plan.spec.triplet()); - } - - InstallPlanAction load_vertex_data(const PackageSpec& spec) const override - { - const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() - ? RequestType::USER_REQUESTED - : RequestType::AUTO_SELECTED; - auto it = status_db.find_installed(spec); - if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type}; - return InstallPlanAction{ - spec, - {nullopt, nullopt, *port_file_provider.get_control_file(spec.name()).core_paragraph}, - request_type}; - } - }; - - const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); - std::vector toposort = - Graphs::topological_sort(specs, InstallAdjacencyProvider{port_file_provider, status_db, specs_as_set}); - Util::erase_remove_if(toposort, [](const InstallPlanAction& plan) { - return plan.request_type == RequestType::AUTO_SELECTED && - plan.plan_type == InstallPlanType::ALREADY_INSTALLED; - }); - - return toposort; - } - - std::vector create_remove_plan(const std::vector& specs, - const StatusParagraphs& status_db) - { - struct RemoveAdjacencyProvider final : Graphs::AdjacencyProvider - { - const StatusParagraphs& status_db; - const std::vector& installed_ports; - const std::unordered_set& specs_as_set; - - RemoveAdjacencyProvider(const StatusParagraphs& status_db, - const std::vector& installed_ports, - const std::unordered_set& specs_as_set) - : status_db(status_db), installed_ports(installed_ports), specs_as_set(specs_as_set) - { - } - - std::vector adjacency_list(const RemovePlanAction& plan) const override - { - if (plan.plan_type == RemovePlanType::NOT_INSTALLED) - { - return {}; - } - - const PackageSpec& spec = plan.spec; - std::vector dependents; - for (const StatusParagraph* an_installed_package : installed_ports) - { - if (an_installed_package->package.spec.triplet() != spec.triplet()) continue; - - const std::vector& deps = an_installed_package->package.depends; - if (std::find(deps.begin(), deps.end(), spec.name()) == deps.end()) continue; - - dependents.push_back(an_installed_package->package.spec); - } - - return dependents; - } - - RemovePlanAction load_vertex_data(const PackageSpec& spec) const override - { - const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() - ? RequestType::USER_REQUESTED - : RequestType::AUTO_SELECTED; - const StatusParagraphs::const_iterator it = status_db.find_installed(spec); - if (it == status_db.end()) - { - return RemovePlanAction{spec, RemovePlanType::NOT_INSTALLED, request_type}; - } - return RemovePlanAction{spec, RemovePlanType::REMOVE, request_type}; - } - }; - - const std::vector& installed_ports = get_installed_ports(status_db); - const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); - return Graphs::topological_sort(specs, RemoveAdjacencyProvider{status_db, installed_ports, specs_as_set}); - } - - std::vector create_export_plan(const VcpkgPaths& paths, - const std::vector& specs, - const StatusParagraphs& status_db) - { - struct ExportAdjacencyProvider final : Graphs::AdjacencyProvider - { - const VcpkgPaths& paths; - const StatusParagraphs& status_db; - const std::unordered_set& specs_as_set; - - ExportAdjacencyProvider(const VcpkgPaths& p, - const StatusParagraphs& s, - const std::unordered_set& specs_as_set) - : paths(p), status_db(s), specs_as_set(specs_as_set) - { - } - - std::vector adjacency_list(const ExportPlanAction& plan) const override - { - return plan.any_paragraph.dependencies(plan.spec.triplet()); - } - - ExportPlanAction load_vertex_data(const PackageSpec& spec) const override - { - const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() - ? RequestType::USER_REQUESTED - : RequestType::AUTO_SELECTED; - - Expected maybe_bpgh = Paragraphs::try_load_cached_control_package(paths, spec); - if (auto bcf = maybe_bpgh.get()) - return ExportPlanAction{spec, AnyParagraph{nullopt, std::move(*bcf), nullopt}, request_type}; - - auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); - if (auto scf = maybe_scf.get()) - return ExportPlanAction{spec, {nullopt, nullopt, *scf->get()->core_paragraph}, request_type}; - else - print_error_message(maybe_scf.error()); - - Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); - } - }; - - const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); - std::vector toposort = - Graphs::topological_sort(specs, ExportAdjacencyProvider{paths, status_db, specs_as_set}); - return toposort; - } - - enum class MarkPlusResult - { - FEATURE_NOT_FOUND, - SUCCESS, - }; - - MarkPlusResult mark_plus(const std::string& feature, - Cluster& cluster, - ClusterGraph& pkg_to_cluster, - GraphPlan& graph_plan); - void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); - - MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) - { - if (feature.empty()) - { - // Indicates that core was not specified in the reference - return mark_plus("core", cluster, graph, graph_plan); - } - - auto it = cluster.edges.find(feature); - if (it == cluster.edges.end()) return MarkPlusResult::FEATURE_NOT_FOUND; - - if (cluster.edges[feature].plus) return MarkPlusResult::SUCCESS; - - if (cluster.original_features.find(feature) == cluster.original_features.end()) - { - cluster.transient_uninstalled = true; - } - - if (!cluster.transient_uninstalled) - { - return MarkPlusResult::SUCCESS; - } - cluster.edges[feature].plus = true; - - if (!cluster.original_features.empty()) - { - mark_minus(cluster, graph, graph_plan); - } - - graph_plan.install_graph.add_vertex({&cluster}); - auto& tracked = cluster.to_install_features; - tracked.insert(feature); - - if (feature != "core") - { - // All features implicitly depend on core - auto res = mark_plus("core", cluster, graph, graph_plan); - - // Should be impossible for "core" to not exist - Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS); - } - - for (auto&& depend : cluster.edges[feature].build_edges) - { - auto& depend_cluster = graph.get(depend.spec()); - auto res = mark_plus(depend.feature(), depend_cluster, graph, graph_plan); - - Checks::check_exit(VCPKG_LINE_INFO, - res == MarkPlusResult::SUCCESS, - "Error: Unable to satisfy dependency %s of %s", - depend, - FeatureSpec(cluster.spec, feature)); - - if (&depend_cluster == &cluster) continue; - graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); - } - - return MarkPlusResult::SUCCESS; - } - - void mark_minus(Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) - { - if (cluster.will_remove) return; - cluster.will_remove = true; - - graph_plan.remove_graph.add_vertex({&cluster}); - for (auto&& pair : cluster.edges) - { - auto& remove_edges_edges = pair.second.remove_edges; - for (auto&& depend : remove_edges_edges) - { - auto& depend_cluster = graph.get(depend.spec()); - graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); - mark_minus(depend_cluster, graph, graph_plan); - } - } - - cluster.transient_uninstalled = true; - for (auto&& original_feature : cluster.original_features) - { - auto res = mark_plus(original_feature, cluster, graph, graph_plan); - if (res != MarkPlusResult::SUCCESS) - { - System::println(System::Color::warning, - "Warning: could not reinstall feature %s", - FeatureSpec{cluster.spec, original_feature}); - } - } - } - - static ClusterGraph create_feature_install_graph(const std::unordered_map& map, - const StatusParagraphs& status_db) - { - std::unordered_map ptr_map; - for (auto&& p : map) - ptr_map.emplace(p.first, &p.second); - ClusterGraph graph(std::move(ptr_map)); - - auto installed_ports = get_installed_ports(status_db); - - for (auto&& status_paragraph : installed_ports) - { - Cluster& cluster = graph.get(status_paragraph->package.spec); - - cluster.transient_uninstalled = false; - - cluster.status_paragraphs.emplace_back(status_paragraph); - - auto& status_paragraph_feature = status_paragraph->package.feature; - // In this case, empty string indicates the "core" paragraph for a package. - if (status_paragraph_feature.empty()) - { - cluster.original_features.insert("core"); - } - else - { - cluster.original_features.insert(status_paragraph_feature); - } - } - - for (auto&& status_paragraph : installed_ports) - { - auto& spec = status_paragraph->package.spec; - auto& status_paragraph_feature = status_paragraph->package.feature; - auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, - status_paragraph->package.spec.triplet()); - - for (auto&& dependency : reverse_edges) - { - auto& dep_cluster = graph.get(dependency.spec()); - - auto depends_name = dependency.feature(); - if (depends_name.empty()) depends_name = "core"; - - auto& target_node = dep_cluster.edges[depends_name]; - target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); - } - } - return graph; - } - - std::vector create_feature_install_plan(const std::unordered_map& map, - const std::vector& specs, - const StatusParagraphs& status_db) - { - ClusterGraph graph = create_feature_install_graph(map, status_db); - - GraphPlan graph_plan; - for (auto&& spec : specs) - { - Cluster& spec_cluster = graph.get(spec.spec()); - spec_cluster.request_type = RequestType::USER_REQUESTED; - auto res = mark_plus(spec.feature(), spec_cluster, graph, graph_plan); - - Checks::check_exit( - VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); - - graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster}); - } - - Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); - auto remove_vertex_list = graph_plan.remove_graph.vertex_list(); - auto remove_toposort = Graphs::topological_sort(remove_vertex_list, adjacency_remove_graph); - - Graphs::GraphAdjacencyProvider adjacency_install_graph(graph_plan.install_graph.adjacency_list()); - auto insert_vertex_list = graph_plan.install_graph.vertex_list(); - auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph); - - std::vector plan; - - for (auto&& p_cluster : remove_toposort) - { - auto scf = *p_cluster->source_control_file.get(); - auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, p_cluster->spec.triplet()) - .value_or_exit(VCPKG_LINE_INFO); - plan.emplace_back(RemovePlanAction{ - std::move(spec), - RemovePlanType::REMOVE, - p_cluster->request_type, - }); - } - - for (auto&& p_cluster : insert_toposort) - { - if (p_cluster->transient_uninstalled) - { - // If it will be transiently uninstalled, we need to issue a full installation command - auto pscf = p_cluster->source_control_file.value_or_exit(VCPKG_LINE_INFO); - Checks::check_exit(VCPKG_LINE_INFO, pscf != nullptr); - plan.emplace_back(InstallPlanAction{ - p_cluster->spec, - *pscf, - p_cluster->to_install_features, - p_cluster->request_type, - }); - } - else - { - // If the package isn't transitively installed, still include it if the user explicitly requested it - if (p_cluster->request_type != RequestType::USER_REQUESTED) continue; - plan.emplace_back(InstallPlanAction{ - p_cluster->spec, - p_cluster->original_features, - p_cluster->request_type, - }); - } - } - - return plan; - } -} diff --git a/toolsrc/src/vcpkg_Enums.cpp b/toolsrc/src/vcpkg_Enums.cpp deleted file mode 100644 index 51ba9d5dc..000000000 --- a/toolsrc/src/vcpkg_Enums.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Checks.h" -#include "vcpkg_Enums.h" - -namespace vcpkg::Enums -{ - std::string nullvalue_to_string(const CStringView enum_name) { return Strings::format("%s_NULLVALUE", enum_name); } - - [[noreturn]] void nullvalue_used(const LineInfo& line_info, const CStringView enum_name) - { - Checks::exit_with_message(line_info, "NULLVALUE of enum %s was used", enum_name); - } -} diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp deleted file mode 100644 index ad1fcebc6..000000000 --- a/toolsrc/src/vcpkg_Files.cpp +++ /dev/null @@ -1,209 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Files.h" -#include "vcpkg_System.h" -#include "vcpkg_Util.h" -#include - -namespace vcpkg::Files -{ - static const std::regex FILESYSTEM_INVALID_CHARACTERS_REGEX = std::regex(R"([\/:*?"<>|])"); - - struct RealFilesystem final : Filesystem - { - virtual Expected read_contents(const fs::path& file_path) const override - { - std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); - if (file_stream.fail()) - { - return std::make_error_code(std::errc::no_such_file_or_directory); - } - - file_stream.seekg(0, file_stream.end); - auto length = file_stream.tellg(); - file_stream.seekg(0, file_stream.beg); - - if (length > SIZE_MAX) - { - return std::make_error_code(std::errc::file_too_large); - } - - std::string output; - output.resize(static_cast(length)); - file_stream.read(&output[0], length); - file_stream.close(); - - return std::move(output); - } - virtual Expected> read_lines(const fs::path& file_path) const override - { - std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); - if (file_stream.fail()) - { - return std::make_error_code(std::errc::no_such_file_or_directory); - } - - std::vector output; - std::string line; - while (std::getline(file_stream, line)) - { - output.push_back(line); - } - file_stream.close(); - - return std::move(output); - } - virtual fs::path find_file_recursively_up(const fs::path& starting_dir, - const std::string& filename) const override - { - fs::path current_dir = starting_dir; - for (; !current_dir.empty(); current_dir = current_dir.parent_path()) - { - const fs::path candidate = current_dir / filename; - if (exists(candidate)) - { - break; - } - } - - return current_dir; - } - - virtual std::vector get_files_recursive(const fs::path& dir) const override - { - std::vector ret; - - fs::stdfs::recursive_directory_iterator b(dir), e{}; - for (; b != e; ++b) - { - ret.push_back(b->path()); - } - - return ret; - } - - virtual std::vector get_files_non_recursive(const fs::path& dir) const override - { - std::vector ret; - - fs::stdfs::directory_iterator b(dir), e{}; - for (; b != e; ++b) - { - ret.push_back(b->path()); - } - - return ret; - } - - virtual void write_lines(const fs::path& file_path, const std::vector& lines) override - { - std::fstream output(file_path, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); - for (const std::string& line : lines) - { - output << line << "\n"; - } - output.close(); - } - - virtual void rename(const fs::path& oldpath, const fs::path& newpath) override - { - fs::stdfs::rename(oldpath, newpath); - } - virtual bool remove(const fs::path& path) override { return fs::stdfs::remove(path); } - virtual bool remove(const fs::path& path, std::error_code& ec) override { return fs::stdfs::remove(path, ec); } - virtual std::uintmax_t remove_all(const fs::path& path, std::error_code& ec) override - { - // Working around the currently buggy remove_all() - std::uintmax_t out = fs::stdfs::remove_all(path, ec); - - for (int i = 0; i < 5 && this->exists(path); i++) - { - using namespace std::chrono_literals; - std::this_thread::sleep_for(i * 100ms); - out += fs::stdfs::remove_all(path, ec); - } - - if (this->exists(path)) - { - System::println(System::Color::warning, - "Some files in %s were unable to be removed. Close any editors operating in this " - "directory and retry.", - path.string()); - } - - return out; - } - virtual bool exists(const fs::path& path) const override { return fs::stdfs::exists(path); } - virtual bool is_directory(const fs::path& path) const override { return fs::stdfs::is_directory(path); } - virtual bool is_regular_file(const fs::path& path) const override { return fs::stdfs::is_regular_file(path); } - virtual bool is_empty(const fs::path& path) const override { return fs::stdfs::is_empty(path); } - virtual bool create_directory(const fs::path& path, std::error_code& ec) override - { - return fs::stdfs::create_directory(path, ec); - } - virtual bool create_directories(const fs::path& path, std::error_code& ec) override - { - return fs::stdfs::create_directories(path, ec); - } - virtual void copy(const fs::path& oldpath, const fs::path& newpath, fs::copy_options opts) override - { - fs::stdfs::copy(oldpath, newpath, opts); - } - virtual bool copy_file(const fs::path& oldpath, - const fs::path& newpath, - fs::copy_options opts, - std::error_code& ec) override - { - return fs::stdfs::copy_file(oldpath, newpath, opts, ec); - } - - virtual fs::file_status status(const fs::path& path, std::error_code& ec) const override - { - return fs::stdfs::status(path, ec); - } - virtual void write_contents(const fs::path& file_path, const std::string& data) override - { - FILE* f = nullptr; - auto ec = _wfopen_s(&f, file_path.native().c_str(), L"wb"); - Checks::check_exit( - VCPKG_LINE_INFO, ec == 0, "Error: Could not open file for writing: %s", file_path.u8string().c_str()); - auto count = fwrite(data.data(), sizeof(data[0]), data.size(), f); - fclose(f); - - Checks::check_exit(VCPKG_LINE_INFO, count == data.size()); - } - }; - - Filesystem& get_real_filesystem() - { - static RealFilesystem real_fs; - return real_fs; - } - - bool has_invalid_chars_for_filesystem(const std::string& s) - { - return std::regex_search(s, FILESYSTEM_INVALID_CHARACTERS_REGEX); - } - - void print_paths(const std::vector& paths) - { - System::println(); - for (const fs::path& p : paths) - { - System::println(" %s", p.generic_string()); - } - System::println(); - } - - std::vector find_from_PATH(const std::wstring& name) - { - const std::wstring cmd = Strings::wformat(L"where.exe %s", name); - auto out = System::cmd_execute_and_capture_output(cmd); - if (out.exit_code != 0) - { - return {}; - } - - return Util::fmap(Strings::split(out.output, "\n"), [](auto&& s) { return fs::path(s); }); - } -} diff --git a/toolsrc/src/vcpkg_GlobalState.cpp b/toolsrc/src/vcpkg_GlobalState.cpp deleted file mode 100644 index 2221222c0..000000000 --- a/toolsrc/src/vcpkg_GlobalState.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "pch.h" - -#include "vcpkg_GlobalState.h" - -namespace vcpkg -{ - Util::LockGuarded GlobalState::timer; - std::atomic GlobalState::debugging = false; - std::atomic GlobalState::feature_packages = false; - - std::atomic GlobalState::g_init_console_cp = 0; - std::atomic GlobalState::g_init_console_output_cp = 0; -} diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp deleted file mode 100644 index f1cac9632..000000000 --- a/toolsrc/src/vcpkg_Input.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "pch.h" - -#include "metrics.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Input.h" -#include "vcpkg_System.h" - -namespace vcpkg::Input -{ - PackageSpec check_and_get_package_spec(const std::string& package_spec_as_string, - const Triplet& default_triplet, - CStringView example_text) - { - const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); - auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet); - if (const auto spec = expected_spec.get()) - { - return PackageSpec{spec->package_spec}; - } - - // Intentionally show the lowercased string - System::println(System::Color::error, "Error: %s: %s", vcpkg::to_string(expected_spec.error()), as_lowercase); - System::print(example_text); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - void check_triplet(const Triplet& t, const VcpkgPaths& paths) - { - if (!paths.is_valid_triplet(t)) - { - System::println(System::Color::error, "Error: invalid triplet: %s", t); - Metrics::g_metrics.lock()->track_property("error", "invalid triplet: " + t.to_string()); - Commands::Help::help_topic_valid_triplet(paths); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - - FullPackageSpec check_and_get_full_package_spec(const std::string& full_package_spec_as_string, - const Triplet& default_triplet, - CStringView example_text) - { - const std::string as_lowercase = Strings::ascii_to_lowercase(full_package_spec_as_string); - auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet); - if (const auto spec = expected_spec.get()) - { - return *spec; - } - - // Intentionally show the lowercased string - System::println(System::Color::error, "Error: %s: %s", vcpkg::to_string(expected_spec.error()), as_lowercase); - System::print(example_text); - Checks::exit_fail(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/vcpkg_Parse.cpp b/toolsrc/src/vcpkg_Parse.cpp deleted file mode 100644 index e671a1a05..000000000 --- a/toolsrc/src/vcpkg_Parse.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Checks.h" -#include "vcpkg_Maps.h" -#include "vcpkg_Parse.h" - -namespace vcpkg::Parse -{ - static Optional remove_field(std::unordered_map* fields, - const std::string& fieldname) - { - auto it = fields->find(fieldname); - if (it == fields->end()) - { - return nullopt; - } - - const std::string value = std::move(it->second); - fields->erase(it); - return value; - } - - void ParagraphParser::required_field(const std::string& fieldname, std::string& out) - { - auto maybe_field = remove_field(&fields, fieldname); - if (const auto field = maybe_field.get()) - out = std::move(*field); - else - missing_fields.push_back(fieldname); - } - std::string ParagraphParser::optional_field(const std::string& fieldname) const - { - return remove_field(&fields, fieldname).value_or(Strings::EMPTY); - } - std::unique_ptr ParagraphParser::error_info(const std::string& name) const - { - if (!fields.empty() || !missing_fields.empty()) - { - auto err = std::make_unique(); - err->name = name; - err->extra_fields = Maps::extract_keys(fields); - err->missing_fields = std::move(missing_fields); - return err; - } - return nullptr; - } - - std::vector parse_comma_list(const std::string& str) - { - if (str.empty()) - { - return {}; - } - - std::vector out; - - size_t cur = 0; - do - { - auto pos = str.find(',', cur); - if (pos == std::string::npos) - { - out.push_back(str.substr(cur)); - break; - } - out.push_back(str.substr(cur, pos - cur)); - - // skip comma and space - ++pos; - if (str[pos] == ' ') - { - ++pos; - } - - cur = pos; - } while (cur != std::string::npos); - - return out; - } -} diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp deleted file mode 100644 index bbe6b29cd..000000000 --- a/toolsrc/src/vcpkg_Strings.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Checks.h" -#include "vcpkg_Strings.h" -#include "vcpkg_Util.h" - -namespace vcpkg::Strings::details -{ - // To disambiguate between two overloads - static const auto isspace = [](const char c) { return std::isspace(c); }; - - // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower() - static char tolower_char(const char c) { return static_cast(std::tolower(c)); } - -#if defined(_WIN32) - static _locale_t& c_locale() - { - static _locale_t c_locale_impl = _create_locale(LC_ALL, "C"); - return c_locale_impl; - } -#endif - - std::string format_internal(const char* fmtstr, ...) - { - va_list args; - va_start(args, fmtstr); - -#if defined(_WIN32) - const int sz = _vscprintf_l(fmtstr, c_locale(), args); -#else - const int sz = vsnprintf(nullptr, 0, fmtstr, args); -#endif - Checks::check_exit(VCPKG_LINE_INFO, sz > 0); - - std::string output(sz, '\0'); - -#if defined(_WIN32) - _vsnprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args); -#else - vsnprintf(&output.at(0), output.size() + 1, fmtstr, args); -#endif - va_end(args); - - return output; - } - - std::wstring wformat_internal(const wchar_t* fmtstr, ...) - { - va_list args; - va_start(args, fmtstr); - -#if defined(_WIN32) - const int sz = _vscwprintf_l(fmtstr, c_locale(), args); -#else - const int sz = vswprintf(nullptr, 0, fmtstr, args); -#endif - Checks::check_exit(VCPKG_LINE_INFO, sz > 0); - - std::wstring output(sz, L'\0'); - -#if defined(_WIN32) - _vsnwprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args); -#else - vswprintf(&output.at(0), output.size() + 1, fmtstr, args); -#endif - va_end(args); - - return output; - } -} - -namespace vcpkg::Strings -{ - std::wstring to_utf16(const CStringView s) - { - const int size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0); - std::wstring output; - output.resize(size - 1); - MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, output.data(), size - 1); - return output; - } - - std::string to_utf8(const CWStringView w) - { - const int size = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr); - std::string output; - output.resize(size - 1); - WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, output.data(), size - 1, nullptr, nullptr); - return output; - } - - std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern) - { - const std::string pattern_as_lower_case(ascii_to_lowercase(pattern)); - return search(s.begin(), - s.end(), - pattern_as_lower_case.begin(), - pattern_as_lower_case.end(), - [](const char a, const char b) { return details::tolower_char(a) == b; }); - } - - bool case_insensitive_ascii_contains(const std::string& s, const std::string& pattern) - { - return case_insensitive_ascii_find(s, pattern) != s.end(); - } - - int case_insensitive_ascii_compare(const CStringView left, const CStringView right) - { - return _stricmp(left.c_str(), right.c_str()); - } - - std::string ascii_to_lowercase(const std::string& input) - { - std::string output(input); - std::transform(output.begin(), output.end(), output.begin(), &details::tolower_char); - return output; - } - - bool case_insensitive_ascii_starts_with(const std::string& s, const std::string& pattern) - { - return _strnicmp(s.c_str(), pattern.c_str(), pattern.size()) == 0; - } - - void trim(std::string* s) - { - s->erase(std::find_if_not(s->rbegin(), s->rend(), details::isspace).base(), s->end()); - s->erase(s->begin(), std::find_if_not(s->begin(), s->end(), details::isspace)); - } - - std::string trimmed(const std::string& s) - { - auto whitespace_back = std::find_if_not(s.rbegin(), s.rend(), details::isspace).base(); - auto whitespace_front = std::find_if_not(s.begin(), whitespace_back, details::isspace); - return std::string(whitespace_front, whitespace_back); - } - - void trim_all_and_remove_whitespace_strings(std::vector* strings) - { - for (std::string& s : *strings) - { - trim(&s); - } - - Util::erase_remove_if(*strings, [](const std::string& s) { return s.empty(); }); - } - - std::vector split(const std::string& s, const std::string& delimiter) - { - std::vector output; - - if (delimiter.empty()) - { - output.push_back(s); - return output; - } - - const size_t delimiter_length = delimiter.length(); - size_t i = 0; - for (size_t pos = s.find(delimiter); pos != std::string::npos; pos = s.find(delimiter, pos)) - { - output.push_back(s.substr(i, pos - i)); - pos += delimiter_length; - i = pos; - } - - // Add the rest of the string after the last delimiter, unless there is nothing after it - if (i != s.length()) - { - output.push_back(s.substr(i, s.length())); - } - - return output; - } -} diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp deleted file mode 100644 index 3b4c440d8..000000000 --- a/toolsrc/src/vcpkg_System.cpp +++ /dev/null @@ -1,349 +0,0 @@ -#include "pch.h" - -#include "vcpkg_Checks.h" -#include "vcpkg_GlobalState.h" -#include "vcpkg_System.h" -#include "vcpkglib.h" - -namespace vcpkg::System -{ - tm get_current_date_time() - { - using std::chrono::system_clock; - std::time_t now_time = system_clock::to_time_t(system_clock::now()); - tm parts; - localtime_s(&parts, &now_time); - return parts; - } - - fs::path get_exe_path_of_current_process() - { - wchar_t buf[_MAX_PATH]; - const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); - if (bytes == 0) std::abort(); - return fs::path(buf, buf + bytes); - } - - Optional to_cpu_architecture(CStringView arch) - { - if (Strings::case_insensitive_ascii_compare(arch, "x86") == 0) return CPUArchitecture::X86; - if (Strings::case_insensitive_ascii_compare(arch, "x64") == 0) return CPUArchitecture::X64; - if (Strings::case_insensitive_ascii_compare(arch, "amd64") == 0) return CPUArchitecture::X64; - if (Strings::case_insensitive_ascii_compare(arch, "arm") == 0) return CPUArchitecture::ARM; - if (Strings::case_insensitive_ascii_compare(arch, "arm64") == 0) return CPUArchitecture::ARM64; - return nullopt; - } - - CPUArchitecture get_host_processor() - { - auto w6432 = get_environment_variable(L"PROCESSOR_ARCHITEW6432"); - if (const auto p = w6432.get()) return to_cpu_architecture(Strings::to_utf8(*p)).value_or_exit(VCPKG_LINE_INFO); - - const auto procarch = get_environment_variable(L"PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO); - return to_cpu_architecture(Strings::to_utf8(procarch)).value_or_exit(VCPKG_LINE_INFO); - } - - std::vector get_supported_host_architectures() - { - std::vector supported_architectures; - supported_architectures.push_back(get_host_processor()); - - // AMD64 machines support to run x86 applications - if (supported_architectures.back() == CPUArchitecture::X64) - { - supported_architectures.push_back(CPUArchitecture::X86); - } - - return supported_architectures; - } - - int cmd_execute_clean(const CWStringView cmd_line) - { - static const std::wstring SYSTEM_ROOT = get_environment_variable(L"SystemRoot").value_or_exit(VCPKG_LINE_INFO); - static const std::wstring SYSTEM_32 = SYSTEM_ROOT + LR"(\system32)"; - static const std::wstring NEW_PATH = Strings::wformat( - LR"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32); - - std::vector env_wstrings = { - L"ALLUSERSPROFILE", - L"APPDATA", - L"CommonProgramFiles", - L"CommonProgramFiles(x86)", - L"CommonProgramW6432", - L"COMPUTERNAME", - L"ComSpec", - L"HOMEDRIVE", - L"HOMEPATH", - L"LOCALAPPDATA", - L"LOGONSERVER", - L"NUMBER_OF_PROCESSORS", - L"OS", - L"PATHEXT", - L"PROCESSOR_ARCHITECTURE", - L"PROCESSOR_ARCHITEW6432", - L"PROCESSOR_IDENTIFIER", - L"PROCESSOR_LEVEL", - L"PROCESSOR_REVISION", - L"ProgramData", - L"ProgramFiles", - L"ProgramFiles(x86)", - L"ProgramW6432", - L"PROMPT", - L"PSModulePath", - L"PUBLIC", - L"SystemDrive", - L"SystemRoot", - L"TEMP", - L"TMP", - L"USERDNSDOMAIN", - L"USERDOMAIN", - L"USERDOMAIN_ROAMINGPROFILE", - L"USERNAME", - L"USERPROFILE", - L"windir", - // Enables proxy information to be passed to Curl, the underlying download library in cmake.exe - L"HTTP_PROXY", - L"HTTPS_PROXY", - // Enables find_package(CUDA) in CMake - L"CUDA_PATH", - }; - - // Flush stdout before launching external process - fflush(nullptr); - - std::wstring env_cstr; - - for (auto&& env_wstring : env_wstrings) - { - const Optional value = System::get_environment_variable(env_wstring); - const auto v = value.get(); - if (!v || v->empty()) continue; - - env_cstr.append(env_wstring); - env_cstr.push_back(L'='); - env_cstr.append(*v); - env_cstr.push_back(L'\0'); - } - - env_cstr.append(NEW_PATH); - env_cstr.push_back(L'\0'); - - STARTUPINFOW startup_info; - memset(&startup_info, 0, sizeof(STARTUPINFOW)); - startup_info.cb = sizeof(STARTUPINFOW); - - PROCESS_INFORMATION process_info; - memset(&process_info, 0, sizeof(PROCESS_INFORMATION)); - - // Basically we are wrapping it in quotes - std::wstring actual_cmd_line = Strings::wformat(LR"###(cmd.exe /c "%s")###", cmd_line); - Debug::println("CreateProcessW(%s)", Strings::to_utf8(actual_cmd_line)); - bool succeeded = TRUE == CreateProcessW(nullptr, - actual_cmd_line.data(), - nullptr, - nullptr, - FALSE, - BELOW_NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, - env_cstr.data(), - nullptr, - &startup_info, - &process_info); - - Checks::check_exit(VCPKG_LINE_INFO, succeeded, "Process creation failed with error code: %lu", GetLastError()); - - CloseHandle(process_info.hThread); - - const DWORD result = WaitForSingleObject(process_info.hProcess, INFINITE); - Checks::check_exit(VCPKG_LINE_INFO, result != WAIT_FAILED, "WaitForSingleObject failed"); - - DWORD exit_code = 0; - GetExitCodeProcess(process_info.hProcess, &exit_code); - - Debug::println("CreateProcessW() returned %lu", exit_code); - return static_cast(exit_code); - } - - int cmd_execute(const CWStringView cmd_line) - { - // Flush stdout before launching external process - fflush(nullptr); - - // Basically we are wrapping it in quotes - const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); - Debug::println("_wsystem(%s)", Strings::to_utf8(actual_cmd_line)); - const int exit_code = _wsystem(actual_cmd_line.c_str()); - Debug::println("_wsystem() returned %d", exit_code); - return exit_code; - } - - // On Win7, output from powershell calls contain a byte order mark, so we strip it out if it is present - static void remove_byte_order_marks(std::wstring* s) - { - const wchar_t* a = s->c_str(); - // This is the UTF-8 byte-order mark - while (s->size() >= 3 && a[0] == 0xEF && a[1] == 0xBB && a[2] == 0xBF) - { - s->erase(0, 3); - } - } - - ExitCodeAndOutput cmd_execute_and_capture_output(const CWStringView cmd_line) - { - // Flush stdout before launching external process - fflush(stdout); - - const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s 2>&1")###", cmd_line); - - Debug::println("_wpopen(%s)", Strings::to_utf8(actual_cmd_line)); - std::wstring output; - wchar_t buf[1024]; - const auto pipe = _wpopen(actual_cmd_line.c_str(), L"r"); - if (pipe == nullptr) - { - return {1, Strings::to_utf8(output)}; - } - while (fgetws(buf, 1024, pipe)) - { - output.append(buf); - } - if (!feof(pipe)) - { - return {1, Strings::to_utf8(output)}; - } - - const auto ec = _pclose(pipe); - Debug::println("_pclose() returned %d", ec); - remove_byte_order_marks(&output); - return {ec, Strings::to_utf8(output)}; - } - - std::wstring create_powershell_script_cmd(const fs::path& script_path, const CWStringView args) - { - // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned - return Strings::wformat( - LR"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.native(), args); - } - - void println() { println(Strings::EMPTY); } - - void print(const CStringView message) { fputs(message.c_str(), stdout); } - - void println(const CStringView message) - { - print(message); - putchar('\n'); - } - - void print(const Color c, const CStringView message) - { - const HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); - - CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info{}; - GetConsoleScreenBufferInfo(console_handle, &console_screen_buffer_info); - const auto original_color = console_screen_buffer_info.wAttributes; - - SetConsoleTextAttribute(console_handle, static_cast(c) | (original_color & 0xF0)); - print(message); - SetConsoleTextAttribute(console_handle, original_color); - } - - void println(const Color c, const CStringView message) - { - print(c, message); - putchar('\n'); - } - - Optional get_environment_variable(const CWStringView varname) noexcept - { - const auto sz = GetEnvironmentVariableW(varname.c_str(), nullptr, 0); - if (sz == 0) return nullopt; - - std::wstring ret(sz, L'\0'); - - Checks::check_exit(VCPKG_LINE_INFO, MAXDWORD >= ret.size()); - const auto sz2 = GetEnvironmentVariableW(varname.c_str(), ret.data(), static_cast(ret.size())); - Checks::check_exit(VCPKG_LINE_INFO, sz2 + 1 == sz); - ret.pop_back(); - return ret; - } - - static bool is_string_keytype(DWORD hkey_type) - { - return hkey_type == REG_SZ || hkey_type == REG_MULTI_SZ || hkey_type == REG_EXPAND_SZ; - } - - Optional get_registry_string(HKEY base, const CWStringView sub_key, const CWStringView valuename) - { - HKEY k = nullptr; - const LSTATUS ec = RegOpenKeyExW(base, sub_key.c_str(), NULL, KEY_READ, &k); - if (ec != ERROR_SUCCESS) return nullopt; - - DWORD dw_buffer_size = 0; - DWORD dw_type = 0; - auto rc = RegQueryValueExW(k, valuename.c_str(), nullptr, &dw_type, nullptr, &dw_buffer_size); - if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size == 0 || - dw_buffer_size % sizeof(wchar_t) != 0) - return nullopt; - std::wstring ret; - ret.resize(dw_buffer_size / sizeof(wchar_t)); - - rc = RegQueryValueExW( - k, valuename.c_str(), nullptr, &dw_type, reinterpret_cast(ret.data()), &dw_buffer_size); - if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size != sizeof(wchar_t) * ret.size()) - return nullopt; - - ret.pop_back(); // remove extra trailing null byte - return ret; - } - - static const fs::path& get_program_files() - { - static const fs::path PATH = System::get_environment_variable(L"PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO); - return PATH; - } - - const fs::path& get_program_files_32_bit() - { - static const fs::path PATH = []() -> fs::path { - auto value = System::get_environment_variable(L"ProgramFiles(x86)"); - if (auto v = value.get()) - { - return std::move(*v); - } - return get_program_files(); - }(); - return PATH; - } - - const fs::path& get_program_files_platform_bitness() - { - static const fs::path PATH = []() -> fs::path { - auto value = System::get_environment_variable(L"ProgramW6432"); - if (auto v = value.get()) - { - return std::move(*v); - } - return get_program_files(); - }(); - return PATH; - } -} - -namespace vcpkg::Debug -{ - void println(const CStringView message) - { - if (GlobalState::debugging) - { - System::println("[DEBUG] %s", message); - } - } - - void println(const System::Color c, const CStringView message) - { - if (GlobalState::debugging) - { - System::println(c, "[DEBUG] %s", message); - } - } -} diff --git a/toolsrc/src/vcpkg_metrics_uploader.cpp b/toolsrc/src/vcpkg_metrics_uploader.cpp deleted file mode 100644 index cef4f4756..000000000 --- a/toolsrc/src/vcpkg_metrics_uploader.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "metrics.h" -#include "vcpkg_Checks.h" -#include "vcpkg_Files.h" -#include - -using namespace vcpkg; - -int WINAPI WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ int) -{ - int argCount; - LPWSTR* szArgList = CommandLineToArgvW(GetCommandLineW(), &argCount); - - Checks::check_exit(VCPKG_LINE_INFO, argCount == 2, "Requires exactly one argument, the path to the payload file"); - auto v = Files::get_real_filesystem().read_contents(szArgList[1]).value_or_exit(VCPKG_LINE_INFO); - Metrics::g_metrics.lock()->upload(v); - LocalFree(szArgList); - return 0; -} diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp deleted file mode 100644 index 5cdafdbc8..000000000 --- a/toolsrc/src/vcpkglib.cpp +++ /dev/null @@ -1,247 +0,0 @@ -#include "pch.h" - -#include "Paragraphs.h" -#include "metrics.h" -#include "vcpkg_Files.h" -#include "vcpkg_Strings.h" -#include "vcpkg_Util.h" -#include "vcpkglib.h" - -namespace vcpkg -{ - static StatusParagraphs load_current_database(Files::Filesystem& fs, - const fs::path& vcpkg_dir_status_file, - const fs::path& vcpkg_dir_status_file_old) - { - if (!fs.exists(vcpkg_dir_status_file)) - { - if (!fs.exists(vcpkg_dir_status_file_old)) - { - // no status file, use empty db - return StatusParagraphs(); - } - - fs.rename(vcpkg_dir_status_file_old, vcpkg_dir_status_file); - } - - auto pghs = Paragraphs::get_paragraphs(fs, vcpkg_dir_status_file).value_or_exit(VCPKG_LINE_INFO); - - std::vector> status_pghs; - for (auto&& p : pghs) - { - status_pghs.push_back(std::make_unique(std::move(p))); - } - - return StatusParagraphs(std::move(status_pghs)); - } - - StatusParagraphs database_load_check(const VcpkgPaths& paths) - { - auto& fs = paths.get_filesystem(); - - const auto updates_dir = paths.vcpkg_dir_updates; - - std::error_code ec; - fs.create_directory(paths.installed, ec); - fs.create_directory(paths.vcpkg_dir, ec); - fs.create_directory(paths.vcpkg_dir_info, ec); - fs.create_directory(updates_dir, ec); - - const fs::path& status_file = paths.vcpkg_dir_status_file; - const fs::path status_file_old = status_file.parent_path() / "status-old"; - const fs::path status_file_new = status_file.parent_path() / "status-new"; - - StatusParagraphs current_status_db = load_current_database(fs, status_file, status_file_old); - - auto update_files = fs.get_files_non_recursive(updates_dir); - if (update_files.empty()) - { - // updates directory is empty, control file is up-to-date. - return current_status_db; - } - for (auto&& file : update_files) - { - if (!fs.is_regular_file(file)) continue; - if (file.filename() == "incomplete") continue; - - auto pghs = Paragraphs::get_paragraphs(fs, file).value_or_exit(VCPKG_LINE_INFO); - for (auto&& p : pghs) - { - current_status_db.insert(std::make_unique(std::move(p))); - } - } - - fs.write_contents(status_file_new, Strings::serialize(current_status_db)); - - fs.rename(status_file_new, status_file); - - for (auto&& file : update_files) - { - if (!fs.is_regular_file(file)) continue; - - fs.remove(file); - } - - return current_status_db; - } - - void write_update(const VcpkgPaths& paths, const StatusParagraph& p) - { - static int update_id = 0; - auto& fs = paths.get_filesystem(); - - const auto my_update_id = update_id++; - const auto tmp_update_filename = paths.vcpkg_dir_updates / "incomplete"; - const auto update_filename = paths.vcpkg_dir_updates / std::to_string(my_update_id); - - fs.write_contents(tmp_update_filename, Strings::serialize(p)); - fs.rename(tmp_update_filename, update_filename); - } - - static void upgrade_to_slash_terminated_sorted_format(Files::Filesystem& fs, - std::vector* lines, - const fs::path& listfile_path) - { - static bool was_tracked = false; - - if (lines->empty()) - { - return; - } - - if (lines->at(0).back() == '/') - { - return; // File already in the new format - } - - if (!was_tracked) - { - was_tracked = true; - Metrics::g_metrics.lock()->track_property("listfile", "update to new format"); - } - - // The files are sorted such that directories are placed just before the files they contain - // (They are not necessarily sorted alphabetically, e.g. libflac) - // Therefore we can detect the entries that represent directories by comparing every element with the next one - // and checking if the next has a slash immediately after the current one's length - for (size_t i = 0; i < lines->size() - 1; i++) - { - std::string& current_string = lines->at(i); - const std::string& next_string = lines->at(i + 1); - - const size_t potential_slash_char_index = current_string.length(); - // Make sure the index exists first - if (next_string.size() > potential_slash_char_index && next_string.at(potential_slash_char_index) == '/') - { - current_string += '/'; // Mark as a directory - } - } - - // After suffixing the directories with a slash, we can now sort. - // We cannot sort before adding the suffixes because the following (actual example): - /* - x86-windows/include/FLAC <<<<<< This would be separated from its group due to sorting - x86-windows/include/FLAC/all.h - x86-windows/include/FLAC/assert.h - x86-windows/include/FLAC/callback.h - x86-windows/include/FLAC++ - x86-windows/include/FLAC++/all.h - x86-windows/include/FLAC++/decoder.h - x86-windows/include/FLAC++/encoder.h - * - x86-windows/include/FLAC/ <<<<<< This will now be kept with its group when sorting - x86-windows/include/FLAC/all.h - x86-windows/include/FLAC/assert.h - x86-windows/include/FLAC/callback.h - x86-windows/include/FLAC++/ - x86-windows/include/FLAC++/all.h - x86-windows/include/FLAC++/decoder.h - x86-windows/include/FLAC++/encoder.h - */ - // Note that after sorting, the FLAC++/ group will be placed before the FLAC/ group - // The new format is lexicographically sorted - std::sort(lines->begin(), lines->end()); - - // Replace the listfile on disk - const fs::path updated_listfile_path = listfile_path.generic_string() + "_updated"; - fs.write_lines(updated_listfile_path, *lines); - fs.rename(updated_listfile_path, listfile_path); - } - - std::vector get_installed_ports(const StatusParagraphs& status_db) - { - std::vector installed_packages; - for (auto&& pgh : status_db) - { - if (pgh->state != InstallState::INSTALLED || pgh->want != Want::INSTALL) continue; - installed_packages.push_back(pgh.get()); - } - - return installed_packages; - } - - std::vector get_installed_files(const VcpkgPaths& paths, - const StatusParagraphs& status_db) - { - auto& fs = paths.get_filesystem(); - - std::vector installed_files; - - for (const std::unique_ptr& pgh : status_db) - { - if (pgh->state != InstallState::INSTALLED || !pgh->package.feature.empty()) - { - continue; - } - - const fs::path listfile_path = paths.listfile_path(pgh->package); - std::vector installed_files_of_current_pgh = - fs.read_lines(listfile_path).value_or_exit(VCPKG_LINE_INFO); - Strings::trim_all_and_remove_whitespace_strings(&installed_files_of_current_pgh); - upgrade_to_slash_terminated_sorted_format(fs, &installed_files_of_current_pgh, listfile_path); - - // Remove the directories - Util::erase_remove_if(installed_files_of_current_pgh, - [](const std::string& file) { return file.back() == '/'; }); - - StatusParagraphAndAssociatedFiles pgh_and_files = { - *pgh, SortedVector(std::move(installed_files_of_current_pgh))}; - installed_files.push_back(std::move(pgh_and_files)); - } - - return installed_files; - } - - CMakeVariable::CMakeVariable(const CWStringView varname, const wchar_t* varvalue) - : s(Strings::wformat(LR"("-D%s=%s")", varname, varvalue)) - { - } - CMakeVariable::CMakeVariable(const CWStringView varname, const std::string& varvalue) - : CMakeVariable(varname, Strings::to_utf16(varvalue).c_str()) - { - } - CMakeVariable::CMakeVariable(const CWStringView varname, const std::wstring& varvalue) - : CMakeVariable(varname, varvalue.c_str()) - { - } - CMakeVariable::CMakeVariable(const CWStringView varname, const fs::path& path) - : CMakeVariable(varname, path.generic_wstring()) - { - } - - std::wstring make_cmake_cmd(const fs::path& cmake_exe, - const fs::path& cmake_script, - const std::vector& pass_variables) - { - const std::wstring cmd_cmake_pass_variables = Strings::join(L" ", pass_variables, [](auto&& v) { return v.s; }); - return Strings::wformat( - LR"("%s" %s -P "%s")", cmake_exe.native(), cmd_cmake_pass_variables, cmake_script.generic_wstring()); - } - - std::string shorten_text(const std::string& desc, size_t length) - { - Checks::check_exit(VCPKG_LINE_INFO, length >= 3); - auto simple_desc = std::regex_replace(desc, std::regex("\\s+"), " "); - return simple_desc.size() <= length ? simple_desc : simple_desc.substr(0, length - 3) + "..."; - } -} diff --git a/toolsrc/src/vcpkgmetricsuploader.cpp b/toolsrc/src/vcpkgmetricsuploader.cpp new file mode 100644 index 000000000..2239fe750 --- /dev/null +++ b/toolsrc/src/vcpkgmetricsuploader.cpp @@ -0,0 +1,20 @@ +#include + +#include +#include + +#include + +using namespace vcpkg; + +int WINAPI WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ int) +{ + int argCount; + LPWSTR* szArgList = CommandLineToArgvW(GetCommandLineW(), &argCount); + + Checks::check_exit(VCPKG_LINE_INFO, argCount == 2, "Requires exactly one argument, the path to the payload file"); + auto v = Files::get_real_filesystem().read_contents(szArgList[1]).value_or_exit(VCPKG_LINE_INFO); + Metrics::g_metrics.lock()->upload(v); + LocalFree(szArgList); + return 0; +} -- cgit v1.2.3 From bea4c2ff4936f22b4024c2afef5e403533c7b291 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 13 Oct 2017 20:58:00 -0700 Subject: [vcpkg] Begin refactor to use CommandStructure to represent command parsing --- toolsrc/src/vcpkg/commands.autocomplete.cpp | 77 ++++++++++++++++++----------- toolsrc/src/vcpkg/install.cpp | 38 +++++++++++--- toolsrc/src/vcpkg/remove.cpp | 37 ++++++++++++-- 3 files changed, 112 insertions(+), 40 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp index b8c633142..2e191b428 100644 --- a/toolsrc/src/vcpkg/commands.autocomplete.cpp +++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp @@ -2,8 +2,10 @@ #include #include +#include #include #include +#include #include namespace vcpkg::Commands::Autocomplete @@ -47,6 +49,7 @@ namespace vcpkg::Commands::Autocomplete { const SortedVector sorted_results(results); System::println(Strings::join("\n", sorted_results)); + Checks::exit_success(line_info); } @@ -63,21 +66,23 @@ namespace vcpkg::Commands::Autocomplete { const std::string requested_command = match[1].str(); - std::vector valid_commands = {"install", - "search", - "remove", - "list", - "update", - "hash", - "help", - "integrate", - "export", - "edit", - "create", - "owns", - "cache", - "version", - "contact"}; + std::vector valid_commands = { + "install", + "search", + "remove", + "list", + "update", + "hash", + "help", + "integrate", + "export", + "edit", + "create", + "owns", + "cache", + "version", + "contact", + }; Util::unstable_keep_if(valid_commands, [&](const std::string& s) { return Strings::case_insensitive_ascii_starts_with(s, requested_command); @@ -86,22 +91,36 @@ namespace vcpkg::Commands::Autocomplete output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(valid_commands)); } - // Handles vcpkg install - if (std::regex_match(to_autocomplete, match, std::regex{R"###(^install.* (\S*)$)###"})) + struct CommandEntry { - const std::string start_with = match[1].str(); - auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); - auto& source_paragraphs = sources_and_errors.paragraphs; - output_sorted_results_and_exit(VCPKG_LINE_INFO, autocomplete_install(source_paragraphs, start_with)); - } - - // Handles vcpkg remove - if (std::regex_match(to_autocomplete, match, std::regex{R"###(^remove.* (\S*)$)###"})) + CStringView regex; + const CommandStructure& structure; + }; + static constexpr CommandEntry commands[] = { + {R"###(^install\s(.*\s|)(\S*)$)###", Install::INSTALL_COMMAND_STRUCTURE}, + {R"###(^remove\s(.*\s|)(\S*)$)###", Remove::REMOVE_COMMAND_STRUCTURE}, + }; + + for (auto&& command : commands) { - const std::string start_with = match[1].str(); - const StatusParagraphs status_db = database_load_check(paths); - const std::vector installed_packages = get_installed_ports(status_db); - output_sorted_results_and_exit(VCPKG_LINE_INFO, autocomplete_remove(installed_packages, start_with)); + if (std::regex_match(to_autocomplete, match, std::regex{command.regex.c_str()})) + { + auto prefix = match[2].str(); + std::vector v; + if (Strings::case_insensitive_ascii_starts_with(prefix, "-")) + { + v = Util::fmap(command.structure.switches, [](auto&& s) -> std::string { return s; }); + } + else + { + v = command.structure.valid_arguments(paths); + } + + Util::unstable_keep_if( + v, [&](const std::string& s) { return Strings::case_insensitive_ascii_starts_with(s, prefix); }); + + output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(v)); + } } Checks::exit_success(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 28d6d1cc6..6a564b00c 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -525,14 +525,40 @@ namespace vcpkg::Install Checks::exit_success(VCPKG_LINE_INFO); } - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + static const std::string OPTION_DRY_RUN = "--dry-run"; + static const std::string OPTION_USE_HEAD_VERSION = "--head"; + static const std::string OPTION_NO_DOWNLOADS = "--no-downloads"; + static const std::string OPTION_RECURSE = "--recurse"; + static const std::string OPTION_KEEP_GOING = "--keep-going"; + + static const std::array INSTALL_SWITCHES = { + OPTION_DRY_RUN, + OPTION_USE_HEAD_VERSION, + OPTION_NO_DOWNLOADS, + OPTION_RECURSE, + OPTION_KEEP_GOING, + }; + static const std::array INSTALL_SETTINGS; + + static std::vector valid_arguments(const VcpkgPaths& paths) { - static const std::string OPTION_DRY_RUN = "--dry-run"; - static const std::string OPTION_USE_HEAD_VERSION = "--head"; - static const std::string OPTION_NO_DOWNLOADS = "--no-downloads"; - static const std::string OPTION_RECURSE = "--recurse"; - static const std::string OPTION_KEEP_GOING = "--keep-going"; + auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + + return Util::fmap(sources_and_errors.paragraphs, + [](auto&& pgh) -> std::string { return pgh->core_paragraph->name; }); + } + const CommandStructure INSTALL_COMMAND_STRUCTURE = { + "install zlib zlib:x64-windows curl boost", + 1, + SIZE_MAX, + INSTALL_SWITCHES, + INSTALL_SETTINGS, + &valid_arguments, + }; + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { // input sanitization static const std::string EXAMPLE = Help::create_example_string("install zlib zlib:x64-windows curl boost"); args.check_min_arg_count(1, EXAMPLE); diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 3751566f7..30b3d6cd8 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -163,13 +163,40 @@ namespace vcpkg::Remove } } + static const std::string OPTION_PURGE = "--purge"; + static const std::string OPTION_NO_PURGE = "--no-purge"; + static const std::string OPTION_RECURSE = "--recurse"; + static const std::string OPTION_DRY_RUN = "--dry-run"; + static const std::string OPTION_OUTDATED = "--outdated"; + + static const std::array REMOVE_SWITCHES = { + OPTION_PURGE, + OPTION_NO_PURGE, + OPTION_RECURSE, + OPTION_DRY_RUN, + OPTION_OUTDATED, + }; + static const std::array REMOVE_SETTINGS; + + static std::vector valid_arguments(const VcpkgPaths& paths) + { + const StatusParagraphs status_db = database_load_check(paths); + const std::vector installed_packages = get_installed_ports(status_db); + + return Util::fmap(installed_packages, [](auto&& pgh) -> std::string { return pgh->package.spec.to_string(); }); + } + + const CommandStructure REMOVE_COMMAND_STRUCTURE = { + "remove zlib zlib:x64-windows curl boost", + 1, + SIZE_MAX, + REMOVE_SWITCHES, + REMOVE_SETTINGS, + &valid_arguments, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string OPTION_PURGE = "--purge"; - static const std::string OPTION_NO_PURGE = "--no-purge"; - static const std::string OPTION_RECURSE = "--recurse"; - static const std::string OPTION_DRY_RUN = "--dry-run"; - static const std::string OPTION_OUTDATED = "--outdated"; static const std::string EXAMPLE = Help::create_example_string("remove zlib zlib:x64-windows curl boost"); const std::unordered_set options = args.check_and_get_optional_command_arguments( {OPTION_PURGE, OPTION_NO_PURGE, OPTION_RECURSE, OPTION_DRY_RUN, OPTION_OUTDATED}); -- cgit v1.2.3 From bf41a93b9de45f5d407fd03a36096f2cd37902b4 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 14 Oct 2017 02:07:42 -0700 Subject: [vcpkg] Prefer the current vcpkg directory over the one the vcpkg.exe is located in --- toolsrc/src/vcpkg.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 748b4f0ee..f1a86ae22 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -74,8 +74,14 @@ static void inner(const VcpkgCmdArguments& args) } else { - vcpkg_root_dir = Files::get_real_filesystem().find_file_recursively_up( - fs::stdfs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root"); + const fs::path current_path = fs::stdfs::current_path(); + vcpkg_root_dir = Files::get_real_filesystem().find_file_recursively_up(current_path, ".vcpkg-root"); + + if (vcpkg_root_dir.empty()) + { + vcpkg_root_dir = Files::get_real_filesystem().find_file_recursively_up( + fs::stdfs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root"); + } } } @@ -88,6 +94,7 @@ static void inner(const VcpkgCmdArguments& args) vcpkg_root_dir.string(), expected_paths.error().message()); const VcpkgPaths paths = expected_paths.value_or_exit(VCPKG_LINE_INFO); + const int exit_code = _wchdir(paths.root.c_str()); Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed"); Commands::Version::warn_if_vcpkg_version_mismatch(paths); -- cgit v1.2.3 From b73327558ba79354769961a8c3f68e61fe9b673e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 14 Oct 2017 02:07:56 -0700 Subject: `integrate` Fix quotes in command (in case of space in the path) --- toolsrc/src/vcpkg/commands.integrate.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 7f6639222..85b567adb 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -230,13 +230,14 @@ namespace vcpkg::Commands::Integrate } System::println(System::Color::success, "Applied user-wide integration for this vcpkg root."); const fs::path cmake_toolchain = paths.buildsystems / "vcpkg.cmake"; - System::println("\n" - "All MSBuild C++ projects can now #include any installed libraries.\n" - "Linking will be handled automatically.\n" - "Installing new libraries will make them instantly available.\n" - "\n" - "CMake projects should use -DCMAKE_TOOLCHAIN_FILE=%s", - cmake_toolchain.generic_string()); + System::println( + R"( +All MSBuild C++ projects can now #include any installed libraries. +Linking will be handled automatically. +Installing new libraries will make them instantly available. + +CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")", + cmake_toolchain.generic_string()); Checks::exit_success(VCPKG_LINE_INFO); } -- cgit v1.2.3 From 58fd38c8200ce4c96ebe1aae3f85b324456b0ff7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 14 Oct 2017 02:16:55 -0700 Subject: [vcpkg-autocomplete] Add edit completion --- toolsrc/src/vcpkg/commands.autocomplete.cpp | 5 +++-- toolsrc/src/vcpkg/commands.edit.cpp | 27 +++++++++++++++++++++++++-- toolsrc/src/vcpkg/install.cpp | 2 +- toolsrc/src/vcpkg/remove.cpp | 2 +- 4 files changed, 30 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp index 2e191b428..23c2c2f7e 100644 --- a/toolsrc/src/vcpkg/commands.autocomplete.cpp +++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp @@ -97,8 +97,9 @@ namespace vcpkg::Commands::Autocomplete const CommandStructure& structure; }; static constexpr CommandEntry commands[] = { - {R"###(^install\s(.*\s|)(\S*)$)###", Install::INSTALL_COMMAND_STRUCTURE}, - {R"###(^remove\s(.*\s|)(\S*)$)###", Remove::REMOVE_COMMAND_STRUCTURE}, + {R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE}, + {R"###(^edit\s(.*\s|)(\S*)$)###", Edit::COMMAND_STRUCTURE}, + {R"###(^remove\s(.*\s|)(\S*)$)###", Remove::COMMAND_STRUCTURE}, }; for (auto&& command : commands) diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index 9497bd76e..a90ae1bc3 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace vcpkg::Commands::Edit { @@ -30,10 +31,32 @@ namespace vcpkg::Commands::Edit return output; } - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + static const std::string OPTION_BUILDTREES = "--buildtrees"; + + static const std::array SWITCHES = { + OPTION_BUILDTREES, + }; + static const std::array SETTINGS; + + static std::vector valid_arguments(const VcpkgPaths& paths) { - static const std::string OPTION_BUILDTREES = "--buildtrees"; + auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + + return Util::fmap(sources_and_errors.paragraphs, + [](auto&& pgh) -> std::string { return pgh->core_paragraph->name; }); + } + + const CommandStructure COMMAND_STRUCTURE = { + "edit zlib", + 1, + 1, + SWITCHES, + SETTINGS, + &valid_arguments, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { static const fs::path VS_CODE_INSIDERS = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe"; static const fs::path VS_CODE = fs::path{"Microsoft VS Code"} / "Code.exe"; diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 6a564b00c..26f729a57 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -548,7 +548,7 @@ namespace vcpkg::Install [](auto&& pgh) -> std::string { return pgh->core_paragraph->name; }); } - const CommandStructure INSTALL_COMMAND_STRUCTURE = { + const CommandStructure COMMAND_STRUCTURE = { "install zlib zlib:x64-windows curl boost", 1, SIZE_MAX, diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 30b3d6cd8..04ddba1e4 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -186,7 +186,7 @@ namespace vcpkg::Remove return Util::fmap(installed_packages, [](auto&& pgh) -> std::string { return pgh->package.spec.to_string(); }); } - const CommandStructure REMOVE_COMMAND_STRUCTURE = { + const CommandStructure COMMAND_STRUCTURE = { "remove zlib zlib:x64-windows curl boost", 1, SIZE_MAX, -- cgit v1.2.3 From 630bcd84b8325217c440def11681e375f5ef4652 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sat, 14 Oct 2017 18:31:53 +0200 Subject: - Updated naming of msvcrt vector. --- toolsrc/src/PostBuildLint.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 58d6f987b..5de1078cd 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -57,7 +57,7 @@ namespace vcpkg::PostBuildLint {"msvcrt40.dll", R"(msvcrt40\.dll)"}, }; - static const std::vector V = [&]() { + static const std::vector V_NO_MSVCRT = [&]() { auto ret = V_NO_120; ret.push_back({"msvcp120.dll", R"(msvcp120\.dll)"}); ret.push_back({"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"}); @@ -69,7 +69,7 @@ namespace vcpkg::PostBuildLint if (toolset == "v120") return V_NO_120; else - return V; + return V_NO_MSVCRT; } static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs, -- cgit v1.2.3 From c6d69fac625706c52fc8e48615bc0c6d7b8dad25 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sun, 15 Oct 2017 02:13:36 +0200 Subject: - Fixed formatting. --- toolsrc/src/vcpkg/postbuildlint.cpp | 16 ++++++++-------- toolsrc/src/vcpkg/vcpkgpaths.cpp | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp index b2422b4b2..548093c6f 100644 --- a/toolsrc/src/vcpkg/postbuildlint.cpp +++ b/toolsrc/src/vcpkg/postbuildlint.cpp @@ -66,14 +66,14 @@ namespace vcpkg::PostBuildLint return ret; }(); - const auto tsv = toolset_version.get(); - if (tsv && (*tsv) == "v120") - { - return V_NO_120; - } - - // Default case for all version >= VS 2015. - return V_NO_MSVCRT; + const auto tsv = toolset_version.get(); + if (tsv && (*tsv) == "v120") + { + return V_NO_120; + } + + // Default case for all version >= VS 2015. + return V_NO_MSVCRT; } static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs, diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index f0e02db8a..b6ec2cb52 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -448,7 +448,7 @@ namespace vcpkg vs_dumpbin_exe, vcvarsall_bat, {}, - major_version == "14" ? V_140 : V_120, + major_version == "14" ? V_140 : V_120, supported_architectures}); } } -- cgit v1.2.3 From 93497f5eab0c1628cc5b1a3a9a671c069c8f8533 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sun, 15 Oct 2017 22:16:46 -0700 Subject: Casing and specification correctness --- toolsrc/src/vcpkg/commands.autocomplete.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp index 23c2c2f7e..3901566d9 100644 --- a/toolsrc/src/vcpkg/commands.autocomplete.cpp +++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp @@ -93,16 +93,21 @@ namespace vcpkg::Commands::Autocomplete struct CommandEntry { + constexpr CommandEntry(const CStringView& regex, const CommandStructure& structure) + : regex(regex), structure(structure) + { + } + CStringView regex; const CommandStructure& structure; }; - static constexpr CommandEntry commands[] = { - {R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE}, - {R"###(^edit\s(.*\s|)(\S*)$)###", Edit::COMMAND_STRUCTURE}, - {R"###(^remove\s(.*\s|)(\S*)$)###", Remove::COMMAND_STRUCTURE}, + static constexpr CommandEntry COMMANDS[] = { + CommandEntry{R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE}, + CommandEntry{R"###(^edit\s(.*\s|)(\S*)$)###", Edit::COMMAND_STRUCTURE}, + CommandEntry{R"###(^remove\s(.*\s|)(\S*)$)###", Remove::COMMAND_STRUCTURE}, }; - for (auto&& command : commands) + for (auto&& command : COMMANDS) { if (std::regex_match(to_autocomplete, match, std::regex{command.regex.c_str()})) { -- cgit v1.2.3 From 6942c00a453c9fa4f9fbde7ba821974110b43d57 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sun, 15 Oct 2017 23:23:39 -0700 Subject: [triplet] Remove obsolete check about dash in the name Triplets haven't required that for a while now --- toolsrc/src/vcpkg/triplet.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/triplet.cpp b/toolsrc/src/vcpkg/triplet.cpp index 8a84ee2b2..4ebb97a9b 100644 --- a/toolsrc/src/vcpkg/triplet.cpp +++ b/toolsrc/src/vcpkg/triplet.cpp @@ -41,9 +41,6 @@ namespace vcpkg Triplet Triplet::from_canonical_name(const std::string& triplet_as_string) { std::string s(Strings::ascii_to_lowercase(triplet_as_string)); - const auto it = std::find(s.cbegin(), s.cend(), '-'); - Checks::check_exit(VCPKG_LINE_INFO, it != s.cend(), "Invalid triplet: %s", triplet_as_string); - const auto p = g_triplet_instances.emplace(std::move(s)); return &*p.first; } -- cgit v1.2.3 From b486be5eb3b12c0a6fa0a81992768340317ec5c2 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sun, 15 Oct 2017 23:24:34 -0700 Subject: Introduce VcpkgPaths::get_available_triplets() --- toolsrc/src/vcpkg/help.cpp | 4 ++-- toolsrc/src/vcpkg/vcpkgpaths.cpp | 25 ++++++++++++++++--------- 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index 7867f71d2..2a0578211 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -16,9 +16,9 @@ namespace vcpkg::Help void help_topic_valid_triplet(const VcpkgPaths& paths) { System::println("Available architecture triplets:"); - for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.triplets)) + for (auto&& triplet : paths.get_available_triplets()) { - System::println(" %s", path.stem().filename().string()); + System::println(" %s", triplet); } } diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 07ce5c961..c57077eaa 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -255,18 +255,25 @@ namespace vcpkg return this->vcpkg_dir_info / (pgh.fullstem() + ".list"); } - bool VcpkgPaths::is_valid_triplet(const Triplet& t) const + const std::vector& VcpkgPaths::get_available_triplets() const { - for (auto&& path : get_filesystem().get_files_non_recursive(this->triplets)) - { - const std::string triplet_file_name = path.stem().generic_u8string(); - if (t.canonical_name() == triplet_file_name) // TODO: fuzzy compare + return this->available_triplets.get_lazy([this]() -> std::vector { + + std::vector output; + for (auto&& path : this->get_filesystem().get_files_non_recursive(this->triplets)) { - // t.value = triplet_file_name; // NOTE: uncomment when implementing fuzzy compare - return true; + output.push_back(path.stem().filename().string()); } - } - return false; + + return output; + }); + } + + bool VcpkgPaths::is_valid_triplet(const Triplet& t) const + { + auto it = Util::find_if(this->get_available_triplets(), + [&](auto&& available_triplet) { return t.canonical_name() == available_triplet; }); + return it != this->get_available_triplets().cend(); } const fs::path& VcpkgPaths::get_cmake_exe() const -- cgit v1.2.3 From e46ec5369318f84f359af9f88cb3d517329bf088 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sun, 15 Oct 2017 23:33:52 -0700 Subject: Remove unused functions --- toolsrc/src/vcpkg/commands.autocomplete.cpp | 34 ----------------------------- 1 file changed, 34 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp index 3901566d9..feca75dcd 100644 --- a/toolsrc/src/vcpkg/commands.autocomplete.cpp +++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp @@ -10,40 +10,6 @@ namespace vcpkg::Commands::Autocomplete { - std::vector autocomplete_install( - const std::vector>& source_paragraphs, const std::string& start_with) - { - std::vector results; - - for (const auto& source_control_file : source_paragraphs) - { - auto&& sp = *source_control_file->core_paragraph; - - if (Strings::case_insensitive_ascii_starts_with(sp.name, start_with)) - { - results.push_back(sp.name); - } - } - return results; - } - - std::vector autocomplete_remove(std::vector installed_packages, - const std::string& start_with) - { - std::vector results; - - for (const auto& installed_package : installed_packages) - { - const auto sp = installed_package->package.displayname(); - - if (Strings::case_insensitive_ascii_starts_with(sp, start_with)) - { - results.push_back(sp); - } - } - return results; - } - [[noreturn]] static void output_sorted_results_and_exit(const LineInfo& line_info, std::vector&& results) { -- cgit v1.2.3 From 798f8a91e43bfdeda8113639ff262f42e5ab6f84 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sun, 15 Oct 2017 23:53:35 -0700 Subject: Introduce Vectors::concatenate() --- toolsrc/src/vcpkg/install.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 26f729a57..4a1e5537b 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -145,7 +145,7 @@ namespace vcpkg::Install continue; } - output.insert(output.end(), t.files.begin(), t.files.end()); + Util::Vectors::concatenate(&output, t.files); } std::sort(output.begin(), output.end()); -- cgit v1.2.3 From 01f47f5823b0c0db4a7e3e5b690dbc809429da56 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 16 Oct 2017 01:14:04 -0700 Subject: [autocomplete] Add triplet completion for `vcpkg install` --- toolsrc/src/vcpkg/commands.autocomplete.cpp | 65 +++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 12 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp index feca75dcd..addb9edaf 100644 --- a/toolsrc/src/vcpkg/commands.autocomplete.cpp +++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp @@ -19,6 +19,13 @@ namespace vcpkg::Commands::Autocomplete Checks::exit_success(line_info); } + std::vector combine_port_with_triplets(const std::string& port, + const std::vector& triplets) + { + return Util::fmap(triplets, + [&](const std::string& triplet) { return Strings::format("%s:%s", port, triplet); }); + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { Metrics::g_metrics.lock()->set_send_metrics(false); @@ -57,41 +64,75 @@ namespace vcpkg::Commands::Autocomplete output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(valid_commands)); } + // Handles vcpkg install package: + if (std::regex_match(to_autocomplete, match, std::regex{R"###(^install(.*|)\s([^:]+):(\S*)$)###"})) + { + const auto port_name = match[2].str(); + const auto triplet_prefix = match[3].str(); + + auto maybe_port = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(port_name)); + if (maybe_port.error()) + { + Checks::exit_success(VCPKG_LINE_INFO); + } + + std::vector triplets = paths.get_available_triplets(); + Util::unstable_keep_if(triplets, [&](const std::string& s) { + return Strings::case_insensitive_ascii_starts_with(s, triplet_prefix); + }); + + auto result = combine_port_with_triplets(port_name, triplets); + + output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(result)); + } + struct CommandEntry { - constexpr CommandEntry(const CStringView& regex, const CommandStructure& structure) - : regex(regex), structure(structure) + constexpr CommandEntry(const CStringView& name, const CStringView& regex, const CommandStructure& structure) + : name(name), regex(regex), structure(structure) { } + CStringView name; CStringView regex; const CommandStructure& structure; }; + static constexpr CommandEntry COMMANDS[] = { - CommandEntry{R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE}, - CommandEntry{R"###(^edit\s(.*\s|)(\S*)$)###", Edit::COMMAND_STRUCTURE}, - CommandEntry{R"###(^remove\s(.*\s|)(\S*)$)###", Remove::COMMAND_STRUCTURE}, + CommandEntry{"install", R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE}, + CommandEntry{"install", R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE}, + CommandEntry{"edit", R"###(^edit\s(.*\s|)(\S*)$)###", Edit::COMMAND_STRUCTURE}, + CommandEntry{"remove", R"###(^remove\s(.*\s|)(\S*)$)###", Remove::COMMAND_STRUCTURE}, }; for (auto&& command : COMMANDS) { if (std::regex_match(to_autocomplete, match, std::regex{command.regex.c_str()})) { - auto prefix = match[2].str(); - std::vector v; + const auto prefix = match[2].str(); + std::vector results; + if (Strings::case_insensitive_ascii_starts_with(prefix, "-")) { - v = Util::fmap(command.structure.switches, [](auto&& s) -> std::string { return s; }); + results = Util::fmap(command.structure.switches, [](auto&& s) -> std::string { return s; }); } else { - v = command.structure.valid_arguments(paths); + results = command.structure.valid_arguments(paths); } - Util::unstable_keep_if( - v, [&](const std::string& s) { return Strings::case_insensitive_ascii_starts_with(s, prefix); }); + Util::unstable_keep_if(results, [&](const std::string& s) { + return Strings::case_insensitive_ascii_starts_with(s, prefix); + }); + + if (command.name == "install" && results.size() == 1) + { + const auto port_at_each_triplet = + combine_port_with_triplets(results[0], paths.get_available_triplets()); + Util::Vectors::concatenate(&results, port_at_each_triplet); + } - output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(v)); + output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(results)); } } -- cgit v1.2.3 From 7214c3583bdf569bc873305908ec109a6c8716cc Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 16 Oct 2017 11:44:04 -0700 Subject: [vcpkg] Push use of UTF-16 to only around Win32 call boundaries. --- toolsrc/src/vcpkg.cpp | 46 ++++++--- toolsrc/src/vcpkg/base/checks.cpp | 12 ++- toolsrc/src/vcpkg/base/cofffilereader.cpp | 7 +- toolsrc/src/vcpkg/base/files.cpp | 13 ++- toolsrc/src/vcpkg/base/strings.cpp | 21 +++- toolsrc/src/vcpkg/base/system.cpp | 157 ++++++++++++++++++++++-------- toolsrc/src/vcpkg/binaryparagraph.cpp | 4 +- toolsrc/src/vcpkg/build.cpp | 72 +++++++------- toolsrc/src/vcpkg/commands.create.cpp | 6 +- toolsrc/src/vcpkg/commands.edit.cpp | 15 ++- toolsrc/src/vcpkg/commands.env.cpp | 2 +- toolsrc/src/vcpkg/commands.exportifw.cpp | 32 +++--- toolsrc/src/vcpkg/commands.hash.cpp | 23 ++--- toolsrc/src/vcpkg/commands.integrate.cpp | 33 ++++--- toolsrc/src/vcpkg/commands.portsdiff.cpp | 46 +++++---- toolsrc/src/vcpkg/commands.version.cpp | 15 ++- toolsrc/src/vcpkg/dependencies.cpp | 15 +-- toolsrc/src/vcpkg/export.cpp | 43 ++++---- toolsrc/src/vcpkg/globalstate.cpp | 8 +- toolsrc/src/vcpkg/install.cpp | 5 +- toolsrc/src/vcpkg/metrics.cpp | 44 ++++++--- toolsrc/src/vcpkg/packagespec.cpp | 4 +- toolsrc/src/vcpkg/parse.cpp | 2 +- toolsrc/src/vcpkg/postbuildlint.cpp | 39 +++----- toolsrc/src/vcpkg/remove.cpp | 2 +- toolsrc/src/vcpkg/sourceparagraph.cpp | 6 +- toolsrc/src/vcpkg/triplet.cpp | 11 ++- toolsrc/src/vcpkg/vcpkgcmdarguments.cpp | 14 ++- toolsrc/src/vcpkg/vcpkglib.cpp | 26 +++-- toolsrc/src/vcpkg/vcpkgpaths.cpp | 102 ++++++++++--------- 30 files changed, 492 insertions(+), 333 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index f1a86ae22..e1e2240e7 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -1,6 +1,15 @@ +#if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include +#pragma warning(push) +#pragma warning(disable : 4768) +#include +#pragma warning(pop) +#else +#include +#endif + #include #include #include @@ -13,10 +22,6 @@ #include #include -#pragma warning(push) -#pragma warning(disable : 4768) -#include -#pragma warning(pop) #include #include #include @@ -44,7 +49,7 @@ static void inner(const VcpkgCmdArguments& args) static const auto find_command = [&](auto&& commands) { auto it = Util::find_if(commands, [&](auto&& commandc) { - return Strings::case_insensitive_ascii_compare(commandc.name, args.command); + return Strings::case_insensitive_ascii_equals(commandc.name, args.command); }); using std::end; if (it != end(commands)) @@ -67,7 +72,7 @@ static void inner(const VcpkgCmdArguments& args) } else { - const Optional vcpkg_root_dir_env = System::get_environment_variable(L"VCPKG_ROOT"); + const auto vcpkg_root_dir_env = System::get_environment_variable("VCPKG_ROOT"); if (const auto v = vcpkg_root_dir_env.get()) { vcpkg_root_dir = fs::stdfs::absolute(*v); @@ -95,7 +100,11 @@ static void inner(const VcpkgCmdArguments& args) expected_paths.error().message()); const VcpkgPaths paths = expected_paths.value_or_exit(VCPKG_LINE_INFO); +#if defined(_WIN32) const int exit_code = _wchdir(paths.root.c_str()); +#else + const int exit_code = chdir(paths.root.c_str()); +#endif Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed"); Commands::Version::warn_if_vcpkg_version_mismatch(paths); @@ -111,11 +120,10 @@ static void inner(const VcpkgCmdArguments& args) } else { - const Optional vcpkg_default_triplet_env = - System::get_environment_variable(L"VCPKG_DEFAULT_TRIPLET"); + const auto vcpkg_default_triplet_env = System::get_environment_variable("VCPKG_DEFAULT_TRIPLET"); if (const auto v = vcpkg_default_triplet_env.get()) { - default_triplet = Triplet::from_canonical_name(Strings::to_utf8(*v)); + default_triplet = Triplet::from_canonical_name(*v); } else { @@ -135,6 +143,7 @@ static void inner(const VcpkgCmdArguments& args) static void load_config() { +#if defined(_WIN32) fs::path localappdata; { // Config path in AppDataLocal @@ -194,6 +203,7 @@ static void load_config() catch (...) { } +#endif } static std::string trim_path_from_command_line(const std::string& full_command_line) @@ -217,24 +227,32 @@ static std::string trim_path_from_command_line(const std::string& full_command_l return std::string(it, full_command_line.cend()); } +#if defined(_WIN32) int wmain(const int argc, const wchar_t* const* const argv) +#else +int main(const int argc, const char* const* const argv) +#endif { if (argc == 0) std::abort(); + *GlobalState::timer.lock() = Chrono::ElapsedTime::create_started(); + +#if defined(_WIN32) GlobalState::g_init_console_cp = GetConsoleCP(); GlobalState::g_init_console_output_cp = GetConsoleOutputCP(); SetConsoleCP(65001); SetConsoleOutputCP(65001); - *GlobalState::timer.lock() = Chrono::ElapsedTime::create_started(); - const std::string trimmed_command_line = trim_path_from_command_line(Strings::to_utf8(GetCommandLineW())); +#endif { auto locked_metrics = Metrics::g_metrics.lock(); locked_metrics->track_property("version", Commands::Version::version()); +#if defined(_WIN32) locked_metrics->track_property("cmdline", trimmed_command_line); +#endif } load_config(); Metrics::g_metrics.lock()->track_property("sqmuser", Metrics::get_SQM_user()); @@ -283,6 +301,12 @@ int wmain(const int argc, const wchar_t* const* const argv) exc_msg); fflush(stdout); for (int x = 0; x < argc; ++x) + { +#if defined(_WIN32) System::println("%s|", Strings::to_utf8(argv[x])); +#else + System::println("%s|", argv[x]); +#endif + } fflush(stdout); } diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp index 73c7b9b1a..ed28d6e2b 100644 --- a/toolsrc/src/vcpkg/base/checks.cpp +++ b/toolsrc/src/vcpkg/base/checks.cpp @@ -17,14 +17,21 @@ namespace vcpkg::Checks GlobalState::debugging = false; metrics->flush(); +#if defined(_WIN32) SetConsoleCP(GlobalState::g_init_console_cp); SetConsoleOutputCP(GlobalState::g_init_console_output_cp); +#endif fflush(nullptr); +#if defined(_WIN32) ::TerminateProcess(::GetCurrentProcess(), exit_code); +#else + ::exit(exit_code); +#endif } +#if defined(_WIN32) static BOOL ctrl_handler(DWORD fdw_ctrl_type) { { @@ -39,6 +46,9 @@ namespace vcpkg::Checks { SetConsoleCtrlHandler(reinterpret_cast(ctrl_handler), TRUE); } +#else + void register_console_ctrl_handler() {} +#endif [[noreturn]] void unreachable(const LineInfo& line_info) { @@ -67,7 +77,7 @@ namespace vcpkg::Checks { if (!expression) { - exit_with_message(line_info, Strings::EMPTY); + exit_with_message(line_info, ""); } } diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp index 5e9c86998..1927e0b5e 100644 --- a/toolsrc/src/vcpkg/base/cofffilereader.cpp +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -7,6 +7,7 @@ using namespace std; namespace vcpkg::CoffFileReader { +#if defined(_WIN32) template static T reinterpret_bytes(const char* data) { @@ -24,7 +25,7 @@ namespace vcpkg::CoffFileReader template static T peek_value_from_stream(fstream& fs) { - const fpos_t original_pos = fs.tellg().seekpos(); + const std::streampos original_pos = fs.tellg(); T data; fs.read(reinterpret_cast(&data), sizeof data); fs.seekg(original_pos); @@ -305,4 +306,8 @@ namespace vcpkg::CoffFileReader return {std::vector(machine_types.cbegin(), machine_types.cend())}; } +#else + DllInfo read_dll(const fs::path& path) { exit(-1); } + LibInfo read_lib(const fs::path& path) { exit(-1); } +#endif } diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index f8b239eaa..6e43debb1 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -163,7 +163,12 @@ namespace vcpkg::Files virtual void write_contents(const fs::path& file_path, const std::string& data) override { FILE* f = nullptr; +#if defined(_WIN32) auto ec = _wfopen_s(&f, file_path.native().c_str(), L"wb"); +#else + f = fopen(file_path.native().c_str(), "wb"); + int ec = f != nullptr ? 0 : 1; +#endif Checks::check_exit( VCPKG_LINE_INFO, ec == 0, "Error: Could not open file for writing: %s", file_path.u8string().c_str()); auto count = fwrite(data.data(), sizeof(data[0]), data.size(), f); @@ -194,9 +199,13 @@ namespace vcpkg::Files System::println(); } - std::vector find_from_PATH(const std::wstring& name) + std::vector find_from_PATH(const std::string& name) { - const std::wstring cmd = Strings::wformat(L"where.exe %s", name); +#if defined(_WIN32) + const std::string cmd = Strings::format("where.exe %s", name); +#else + const std::string cmd = Strings::format("which %s", name); +#endif auto out = System::cmd_execute_and_capture_output(cmd); if (out.exit_code != 0) { diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index 2a6d3dff2..fa04279b9 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -37,7 +37,8 @@ namespace vcpkg::Strings::details #if defined(_WIN32) _vsnprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args); #else - vsnprintf(&output.at(0), output.size() + 1, fmtstr, args); + va_start(args, fmtstr); + auto res = vsnprintf(&output.at(0), output.size() + 1, fmtstr, args); #endif va_end(args); @@ -73,20 +74,28 @@ namespace vcpkg::Strings { std::wstring to_utf16(const CStringView s) { +#if defined(_WIN32) const int size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0); std::wstring output; output.resize(size - 1); MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, output.data(), size - 1); return output; +#else + Checks::unreachable(VCPKG_LINE_INFO); +#endif } std::string to_utf8(const CWStringView w) { +#if defined(_WIN32) const int size = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr); std::string output; output.resize(size - 1); WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, output.data(), size - 1, nullptr, nullptr); return output; +#else + Checks::unreachable(VCPKG_LINE_INFO); +#endif } std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern) @@ -104,9 +113,13 @@ namespace vcpkg::Strings return case_insensitive_ascii_find(s, pattern) != s.end(); } - bool case_insensitive_ascii_compare(const CStringView left, const CStringView right) + bool case_insensitive_ascii_equals(const CStringView left, const CStringView right) { +#if defined(_WIN32) return _stricmp(left.c_str(), right.c_str()) == 0; +#else + return strcasecmp(left.c_str(), right.c_str()) == 0; +#endif } std::string ascii_to_lowercase(const std::string& input) @@ -118,7 +131,11 @@ namespace vcpkg::Strings bool case_insensitive_ascii_starts_with(const std::string& s, const std::string& pattern) { +#if defined(_WIN32) return _strnicmp(s.c_str(), pattern.c_str(), pattern.size()) == 0; +#else + return strncasecmp(s.c_str(), pattern.c_str(), pattern.size()) == 0; +#endif } void trim(std::string* s) diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index d5d39461c..e92d06f6e 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -4,6 +4,8 @@ #include #include +#include + #pragma comment(lib, "Advapi32") namespace vcpkg::System @@ -13,35 +15,46 @@ namespace vcpkg::System using std::chrono::system_clock; std::time_t now_time = system_clock::to_time_t(system_clock::now()); tm parts; +#if defined(_WIN32) localtime_s(&parts, &now_time); +#else + parts = *localtime(&now_time); +#endif return parts; } fs::path get_exe_path_of_current_process() { +#if defined(_WIN32) wchar_t buf[_MAX_PATH]; const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); if (bytes == 0) std::abort(); return fs::path(buf, buf + bytes); +#else + std::array buf; + auto written = readlink("/proc/self/exe", buf.data(), buf.size()); + Checks::check_exit(VCPKG_LINE_INFO, written != -1, "Could not determine current executable path."); + return fs::path(buf.data(), buf.data() + written); +#endif } Optional to_cpu_architecture(CStringView arch) { - if (Strings::case_insensitive_ascii_compare(arch, "x86")) return CPUArchitecture::X86; - if (Strings::case_insensitive_ascii_compare(arch, "x64")) return CPUArchitecture::X64; - if (Strings::case_insensitive_ascii_compare(arch, "amd64")) return CPUArchitecture::X64; - if (Strings::case_insensitive_ascii_compare(arch, "arm")) return CPUArchitecture::ARM; - if (Strings::case_insensitive_ascii_compare(arch, "arm64")) return CPUArchitecture::ARM64; + if (Strings::case_insensitive_ascii_equals(arch, "x86")) return CPUArchitecture::X86; + if (Strings::case_insensitive_ascii_equals(arch, "x64")) return CPUArchitecture::X64; + if (Strings::case_insensitive_ascii_equals(arch, "amd64")) return CPUArchitecture::X64; + if (Strings::case_insensitive_ascii_equals(arch, "arm")) return CPUArchitecture::ARM; + if (Strings::case_insensitive_ascii_equals(arch, "arm64")) return CPUArchitecture::ARM64; return nullopt; } CPUArchitecture get_host_processor() { - auto w6432 = get_environment_variable(L"PROCESSOR_ARCHITEW6432"); - if (const auto p = w6432.get()) return to_cpu_architecture(Strings::to_utf8(*p)).value_or_exit(VCPKG_LINE_INFO); + auto w6432 = get_environment_variable("PROCESSOR_ARCHITEW6432"); + if (const auto p = w6432.get()) return to_cpu_architecture(*p).value_or_exit(VCPKG_LINE_INFO); - const auto procarch = get_environment_variable(L"PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO); - return to_cpu_architecture(Strings::to_utf8(procarch)).value_or_exit(VCPKG_LINE_INFO); + const auto procarch = get_environment_variable("PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO); + return to_cpu_architecture(procarch).value_or_exit(VCPKG_LINE_INFO); } std::vector get_supported_host_architectures() @@ -58,12 +71,13 @@ namespace vcpkg::System return supported_architectures; } - int cmd_execute_clean(const CWStringView cmd_line) + int cmd_execute_clean(const CStringView cmd_line) { - static const std::wstring SYSTEM_ROOT = get_environment_variable(L"SystemRoot").value_or_exit(VCPKG_LINE_INFO); - static const std::wstring SYSTEM_32 = SYSTEM_ROOT + LR"(\system32)"; - static const std::wstring NEW_PATH = Strings::wformat( - LR"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32); +#if defined(_WIN32) + static const std::string SYSTEM_ROOT = get_environment_variable("SystemRoot").value_or_exit(VCPKG_LINE_INFO); + static const std::string SYSTEM_32 = SYSTEM_ROOT + R"(\system32)"; + static const std::string NEW_PATH = Strings::format( + R"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32); std::vector env_wstrings = { L"ALLUSERSPROFILE", @@ -118,17 +132,17 @@ namespace vcpkg::System for (auto&& env_wstring : env_wstrings) { - const Optional value = System::get_environment_variable(env_wstring); + const Optional value = System::get_environment_variable(Strings::to_utf8(env_wstring)); const auto v = value.get(); if (!v || v->empty()) continue; env_cstr.append(env_wstring); env_cstr.push_back(L'='); - env_cstr.append(*v); + env_cstr.append(Strings::to_utf16(*v)); env_cstr.push_back(L'\0'); } - env_cstr.append(NEW_PATH); + env_cstr.append(Strings::to_utf16(NEW_PATH)); env_cstr.push_back(L'\0'); STARTUPINFOW startup_info; @@ -139,10 +153,10 @@ namespace vcpkg::System memset(&process_info, 0, sizeof(PROCESS_INFORMATION)); // Basically we are wrapping it in quotes - std::wstring actual_cmd_line = Strings::wformat(LR"###(cmd.exe /c "%s")###", cmd_line); - Debug::println("CreateProcessW(%s)", Strings::to_utf8(actual_cmd_line)); + std::string actual_cmd_line = Strings::format(R"###(cmd.exe /c "%s")###", cmd_line); + Debug::println("CreateProcessW(%s)", actual_cmd_line); bool succeeded = TRUE == CreateProcessW(nullptr, - actual_cmd_line.data(), + Strings::to_utf16(actual_cmd_line).data(), nullptr, nullptr, FALSE, @@ -164,18 +178,28 @@ namespace vcpkg::System Debug::println("CreateProcessW() returned %lu", exit_code); return static_cast(exit_code); +#else + fflush(nullptr); + return system(cmd_line.c_str()); +#endif } - int cmd_execute(const CWStringView cmd_line) + int cmd_execute(const CStringView cmd_line) { // Flush stdout before launching external process fflush(nullptr); // Basically we are wrapping it in quotes - const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); - Debug::println("_wsystem(%s)", Strings::to_utf8(actual_cmd_line)); - const int exit_code = _wsystem(actual_cmd_line.c_str()); + const std::string& actual_cmd_line = Strings::format(R"###("%s")###", cmd_line); +#if defined(_WIN32) + Debug::println("_wsystem(%s)", actual_cmd_line); + const int exit_code = _wsystem(Strings::to_utf16(actual_cmd_line).c_str()); Debug::println("_wsystem() returned %d", exit_code); +#else + Debug::println("_system(%s)", actual_cmd_line); + const int exit_code = system(actual_cmd_line.c_str()); + Debug::println("_system() returned %d", exit_code); +#endif return exit_code; } @@ -190,17 +214,18 @@ namespace vcpkg::System } } - ExitCodeAndOutput cmd_execute_and_capture_output(const CWStringView cmd_line) + ExitCodeAndOutput cmd_execute_and_capture_output(const CStringView cmd_line) { // Flush stdout before launching external process fflush(stdout); - const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s 2>&1")###", cmd_line); +#if defined(_WIN32) + const auto actual_cmd_line = Strings::format(R"###("%s 2>&1")###", cmd_line); - Debug::println("_wpopen(%s)", Strings::to_utf8(actual_cmd_line)); + Debug::println("_wpopen(%s)", actual_cmd_line); std::wstring output; wchar_t buf[1024]; - const auto pipe = _wpopen(actual_cmd_line.c_str(), L"r"); + const auto pipe = _wpopen(Strings::to_utf16(actual_cmd_line).c_str(), L"r"); if (pipe == nullptr) { return {1, Strings::to_utf8(output)}; @@ -218,27 +243,52 @@ namespace vcpkg::System Debug::println("_pclose() returned %d", ec); remove_byte_order_marks(&output); return {ec, Strings::to_utf8(output)}; +#else + const auto actual_cmd_line = Strings::format(R"###(%s 2>&1)###", cmd_line); + + Debug::println("popen(%s)", actual_cmd_line); + std::string output; + char buf[1024]; + const auto pipe = popen(actual_cmd_line.c_str(), "r"); + if (pipe == nullptr) + { + return {1, output}; + } + while (fgets(buf, 1024, pipe)) + { + output.append(buf); + } + if (!feof(pipe)) + { + return {1, output}; + } + + const auto ec = pclose(pipe); + Debug::println("pclose() returned %d", ec); + return {ec, output}; +#endif } - std::wstring create_powershell_script_cmd(const fs::path& script_path, const CWStringView args) + std::string create_powershell_script_cmd(const fs::path& script_path, const CStringView args) { // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned - return Strings::wformat( - LR"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.native(), args); + return Strings::format( + R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args); } - void println() { println(Strings::EMPTY); } + void println() { putchar('\n'); } void print(const CStringView message) { fputs(message.c_str(), stdout); } void println(const CStringView message) { print(message); - putchar('\n'); + println(); } void print(const Color c, const CStringView message) { +#if defined(_WIN32) const HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info{}; @@ -248,37 +298,50 @@ namespace vcpkg::System SetConsoleTextAttribute(console_handle, static_cast(c) | (original_color & 0xF0)); print(message); SetConsoleTextAttribute(console_handle, original_color); +#else + print(message); +#endif } void println(const Color c, const CStringView message) { print(c, message); - putchar('\n'); + println(); } - Optional get_environment_variable(const CWStringView varname) noexcept + Optional get_environment_variable(const CStringView varname) noexcept { - const auto sz = GetEnvironmentVariableW(varname.c_str(), nullptr, 0); +#if defined(_WIN32) + const auto w_varname = Strings::to_utf16(varname); + const auto sz = GetEnvironmentVariableW(w_varname.c_str(), nullptr, 0); if (sz == 0) return nullopt; std::wstring ret(sz, L'\0'); Checks::check_exit(VCPKG_LINE_INFO, MAXDWORD >= ret.size()); - const auto sz2 = GetEnvironmentVariableW(varname.c_str(), ret.data(), static_cast(ret.size())); + const auto sz2 = GetEnvironmentVariableW(w_varname.c_str(), ret.data(), static_cast(ret.size())); Checks::check_exit(VCPKG_LINE_INFO, sz2 + 1 == sz); ret.pop_back(); - return ret; + return Strings::to_utf8(ret); +#else + auto v = getenv(varname.c_str()); + if (!v) return nullopt; + return std::string(v); +#endif } +#if defined(_WIN32) static bool is_string_keytype(DWORD hkey_type) { return hkey_type == REG_SZ || hkey_type == REG_MULTI_SZ || hkey_type == REG_EXPAND_SZ; } - Optional get_registry_string(HKEY base, const CWStringView sub_key, const CWStringView valuename) + Optional get_registry_string(void* base_hkey, + const CWStringView sub_key, + const CWStringView valuename) { HKEY k = nullptr; - const LSTATUS ec = RegOpenKeyExW(base, sub_key.c_str(), NULL, KEY_READ, &k); + const LSTATUS ec = RegOpenKeyExW(reinterpret_cast(base_hkey), sub_key.c_str(), NULL, KEY_READ, &k); if (ec != ERROR_SUCCESS) return nullopt; DWORD dw_buffer_size = 0; @@ -298,17 +361,25 @@ namespace vcpkg::System ret.pop_back(); // remove extra trailing null byte return ret; } +#else + Optional get_registry_string(void* base_hkey, + const CWStringView sub_key, + const CWStringView valuename) + { + return nullopt; + } +#endif static const fs::path& get_program_files() { - static const fs::path PATH = System::get_environment_variable(L"PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO); + static const fs::path PATH = System::get_environment_variable("PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO); return PATH; } const fs::path& get_program_files_32_bit() { static const fs::path PATH = []() -> fs::path { - auto value = System::get_environment_variable(L"ProgramFiles(x86)"); + auto value = System::get_environment_variable("ProgramFiles(x86)"); if (auto v = value.get()) { return std::move(*v); @@ -321,7 +392,7 @@ namespace vcpkg::System const fs::path& get_program_files_platform_bitness() { static const fs::path PATH = []() -> fs::path { - auto value = System::get_environment_variable(L"ProgramW6432"); + auto value = System::get_environment_variable("ProgramW6432"); if (auto v = value.get()) { return std::move(*v); diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp index ef943011f..3a493eb4c 100644 --- a/toolsrc/src/vcpkg/binaryparagraph.cpp +++ b/toolsrc/src/vcpkg/binaryparagraph.cpp @@ -80,10 +80,10 @@ namespace vcpkg BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, const Triplet& triplet) { this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); - this->version = Strings::EMPTY; + this->version = ""; this->feature = fpgh.name; this->description = fpgh.description; - this->maintainer = Strings::EMPTY; + this->maintainer = ""; this->depends = filter_dependencies(fpgh.depends, triplet); } diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 99ec541c1..3d3bcb5fe 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -155,16 +155,16 @@ namespace vcpkg::Build static const std::string LIBRARY_LINKAGE = "LibraryLinkage"; } - CWStringView to_vcvarsall_target(const std::string& cmake_system_name) + CStringView to_vcvarsall_target(const std::string& cmake_system_name) { - if (cmake_system_name == Strings::EMPTY) return Strings::WEMPTY; - if (cmake_system_name == "Windows") return Strings::WEMPTY; - if (cmake_system_name == "WindowsStore") return L"store"; + if (cmake_system_name.empty()) return ""; + if (cmake_system_name == "Windows") return ""; + if (cmake_system_name == "WindowsStore") return "store"; Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported vcvarsall target %s", cmake_system_name); } - CWStringView to_vcvarsall_toolchain(const std::string& target_architecture, const Toolset& toolset) + CStringView to_vcvarsall_toolchain(const std::string& target_architecture, const Toolset& toolset) { auto maybe_target_arch = System::to_cpu_architecture(target_architecture); Checks::check_exit( @@ -183,23 +183,23 @@ namespace vcpkg::Build Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported toolchain combination %s", target_architecture); } - std::wstring make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset) + std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset) { - const wchar_t* tonull = L" >nul"; + const char* tonull = " >nul"; if (GlobalState::debugging) { - tonull = Strings::WEMPTY; + tonull = ""; } const auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset); const auto target = to_vcvarsall_target(pre_build_info.cmake_system_name); - return Strings::wformat(LR"("%s" %s %s %s %s 2>&1)", - toolset.vcvarsall.native(), - Strings::join(L" ", toolset.vcvarsall_options), - arch, - target, - tonull); + return Strings::format(R"("%s" %s %s %s %s 2>&1)", + toolset.vcvarsall.u8string(), + Strings::join(" ", toolset.vcvarsall_options), + arch, + target, + tonull); } static void create_binary_feature_control_file(const SourceParagraph& source_paragraph, @@ -265,8 +265,6 @@ namespace vcpkg::Build const fs::path ports_cmake_script_path = paths.ports_cmake; const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); - const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); - const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); std::string features; if (GlobalState::feature_packages) @@ -284,22 +282,26 @@ namespace vcpkg::Build } } - const std::wstring cmd_launch_cmake = make_cmake_cmd( + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); + + const std::string cmd_launch_cmake = make_cmake_cmd( cmake_exe_path, ports_cmake_script_path, { - {L"CMD", L"BUILD"}, - {L"PORT", config.src.name}, - {L"CURRENT_PORT_DIR", config.port_dir / "/."}, - {L"TARGET_TRIPLET", triplet.canonical_name()}, - {L"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, - {L"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? L"1" : L"0"}, - {L"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? L"1" : L"0"}, - {L"GIT", git_exe_path}, - {L"FEATURES", features}, + {"CMD", "BUILD"}, + {"PORT", config.src.name}, + {"CURRENT_PORT_DIR", config.port_dir / "/."}, + {"TARGET_TRIPLET", triplet.canonical_name()}, + {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, + {"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, + {"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, + {"GIT", git_exe_path}, + {"FEATURES", features}, }); - const std::wstring command = Strings::wformat(LR"(%s && %s)", cmd_set_environment, cmd_launch_cmake); + std::string command; + const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); + command = Strings::format(R"(%s && %s)", cmd_set_environment, cmd_launch_cmake); const auto timer = Chrono::ElapsedTime::create_started(); @@ -461,14 +463,12 @@ namespace vcpkg::Build const fs::path ports_cmake_script_path = paths.scripts / "get_triplet_environment.cmake"; const fs::path triplet_file_path = paths.triplets / (triplet.canonical_name() + ".cmake"); - const std::wstring cmd_launch_cmake = make_cmake_cmd(cmake_exe_path, - ports_cmake_script_path, - { - {L"CMAKE_TRIPLET_FILE", triplet_file_path}, - }); - - const std::wstring command = Strings::wformat(LR"(%s)", cmd_launch_cmake); - const auto ec_data = System::cmd_execute_and_capture_output(command); + const auto cmd_launch_cmake = make_cmake_cmd(cmake_exe_path, + ports_cmake_script_path, + { + {"CMAKE_TRIPLET_FILE", triplet_file_path}, + }); + const auto ec_data = System::cmd_execute_and_capture_output(cmd_launch_cmake); Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0); const std::vector lines = Strings::split(ec_data.output, "\n"); @@ -491,7 +491,7 @@ namespace vcpkg::Build const bool variable_with_no_value = s.size() == 1; const std::string variable_name = s.at(0); - const std::string variable_value = variable_with_no_value ? Strings::EMPTY : s.at(1); + const std::string variable_value = variable_with_no_value ? "" : s.at(1); if (variable_name == "VCPKG_TARGET_ARCHITECTURE") { diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp index d923cf555..85763f25e 100644 --- a/toolsrc/src/vcpkg/commands.create.cpp +++ b/toolsrc/src/vcpkg/commands.create.cpp @@ -20,7 +20,7 @@ namespace vcpkg::Commands::Create const fs::path& cmake_exe = paths.get_cmake_exe(); - std::vector cmake_args{{L"CMD", L"CREATE"}, {L"PORT", port_name}, {L"URL", url}}; + std::vector cmake_args{{"CMD", "CREATE"}, {"PORT", port_name}, {"URL", url}}; if (args.command_arguments.size() >= 3) { @@ -30,10 +30,10 @@ namespace vcpkg::Commands::Create R"(Filename cannot contain invalid chars %s, but was %s)", Files::FILESYSTEM_INVALID_CHARACTERS, zip_file_name); - cmake_args.push_back({L"FILENAME", zip_file_name}); + cmake_args.push_back({"FILENAME", zip_file_name}); } - const std::wstring cmd_launch_cmake = make_cmake_cmd(cmake_exe, paths.ports_cmake, cmake_args); + const std::string cmd_launch_cmake = make_cmake_cmd(cmake_exe, paths.ports_cmake, cmake_args); Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute_clean(cmd_launch_cmake)); } } diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index a90ae1bc3..fe6f76bd2 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -17,6 +17,7 @@ namespace vcpkg::Commands::Edit }; std::vector output; +#if defined(_WIN32) for (auto&& keypath : REGKEYS) { const Optional code_installpath = @@ -28,6 +29,7 @@ namespace vcpkg::Commands::Edit output.push_back(install_path / "Code.exe"); } } +#endif return output; } @@ -72,7 +74,7 @@ namespace vcpkg::Commands::Edit Checks::check_exit(VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name); std::vector candidate_paths; - const std::vector from_path = Files::find_from_PATH(L"EDITOR"); + const std::vector from_path = Files::find_from_PATH("EDITOR"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE_INSIDERS); candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE_INSIDERS); @@ -98,13 +100,16 @@ namespace vcpkg::Commands::Edit { const auto buildtrees_current_dir = paths.buildtrees / port_name; - const std::wstring cmd_line = - Strings::wformat(LR"("%s" "%s" -n)", env_editor, buildtrees_current_dir.native()); + const auto cmd_line = + Strings::format(R"("%s" "%s" -n)", env_editor.u8string(), buildtrees_current_dir.u8string()); Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); } - const std::wstring cmd_line = Strings::wformat( - LR"("%s" "%s" "%s" -n)", env_editor, portpath.native(), (portpath / "portfile.cmake").native()); + const auto cmd_line = Strings::format( + R"("%s" "%s" "%s" -n)", + env_editor.u8string(), + portpath.u8string(), + (portpath / "portfile.cmake").u8string()); Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); } } diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp index 089881588..9f8ae5207 100644 --- a/toolsrc/src/vcpkg/commands.env.cpp +++ b/toolsrc/src/vcpkg/commands.env.cpp @@ -15,7 +15,7 @@ namespace vcpkg::Commands::Env const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); - System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, toolset) + L" && cmd"); + System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, toolset) + " && cmd"); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg/commands.exportifw.cpp b/toolsrc/src/vcpkg/commands.exportifw.cpp index fbf3beb8c..682267acb 100644 --- a/toolsrc/src/vcpkg/commands.exportifw.cpp +++ b/toolsrc/src/vcpkg/commands.exportifw.cpp @@ -29,7 +29,7 @@ namespace vcpkg::Export::IFW std::string safe_rich_from_plain_text(const std::string& text) { - // match standalone ampersand, no HTML number or name + // match standalone ampersand, no HTML number or name std::regex standalone_ampersand(R"###(&(?!(#[0-9]+|\w+);))###"); return std::regex_replace(text, standalone_ampersand, "&"); @@ -350,10 +350,10 @@ namespace vcpkg::Export::IFW Checks::check_exit( VCPKG_LINE_INFO, !ec, "Could not remove outdated repository directory %s", repository_dir.generic_string()); - const std::wstring cmd_line = Strings::wformat(LR"("%s" --packages "%s" "%s" > nul)", - repogen_exe.native(), - packages_dir.native(), - repository_dir.native()); + const auto cmd_line = Strings::format(R"("%s" --packages "%s" "%s" > nul)", + repogen_exe.u8string(), + packages_dir.u8string(), + repository_dir.u8string()); const int exit_code = System::cmd_execute_clean(cmd_line); Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW repository generating failed"); @@ -371,24 +371,24 @@ namespace vcpkg::Export::IFW System::println("Generating installer %s...", installer_file.generic_string()); - std::wstring cmd_line; + std::string cmd_line; std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); if (!ifw_repo_url.empty()) { - cmd_line = Strings::wformat(LR"("%s" --online-only --config "%s" --repository "%s" "%s" > nul)", - binarycreator_exe.native(), - config_file.native(), - repository_dir.native(), - installer_file.native()); + cmd_line = Strings::format(R"("%s" --online-only --config "%s" --repository "%s" "%s" > nul)", + binarycreator_exe.u8string(), + config_file.u8string(), + repository_dir.u8string(), + installer_file.u8string()); } else { - cmd_line = Strings::wformat(LR"("%s" --config "%s" --packages "%s" "%s" > nul)", - binarycreator_exe.native(), - config_file.native(), - packages_dir.native(), - installer_file.native()); + cmd_line = Strings::format(R"("%s" --config "%s" --packages "%s" "%s" > nul)", + binarycreator_exe.u8string(), + config_file.u8string(), + packages_dir.u8string(), + installer_file.u8string()); } const int exit_code = System::cmd_execute_clean(cmd_line); diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 394a02e23..4bc58b509 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -7,26 +7,21 @@ namespace vcpkg::Commands::Hash { - static void do_file_hash(fs::path const& path, std::wstring const& hash_type) + static void do_file_hash(fs::path const& path, std::string const& hash_type) { - const auto cmd_line = Strings::wformat(LR"(CertUtil.exe -hashfile "%s" %s)", path.c_str(), hash_type); + const auto cmd_line = Strings::format(R"(CertUtil.exe -hashfile "%s" %s)", path.u8string().c_str(), hash_type); const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit( - VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::to_utf8(cmd_line)); + Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line); std::string const& output = ec_data.output; const auto start = output.find_first_of("\r\n"); - Checks::check_exit(VCPKG_LINE_INFO, - start != std::string::npos, - "Unexpected output format from command: %s", - Strings::to_utf8(cmd_line)); + Checks::check_exit( + VCPKG_LINE_INFO, start != std::string::npos, "Unexpected output format from command: %s", cmd_line); const auto end = output.find_first_of("\r\n", start + 1); - Checks::check_exit(VCPKG_LINE_INFO, - end != std::string::npos, - "Unexpected output format from command: %s", - Strings::to_utf8(cmd_line)); + Checks::check_exit( + VCPKG_LINE_INFO, end != std::string::npos, "Unexpected output format from command: %s", cmd_line); auto hash = output.substr(start, end - start); Util::erase_remove_if(hash, isspace); @@ -43,11 +38,11 @@ namespace vcpkg::Commands::Hash if (args.command_arguments.size() == 1) { - do_file_hash(args.command_arguments[0], L"SHA512"); + do_file_hash(args.command_arguments[0], "SHA512"); } if (args.command_arguments.size() == 2) { - do_file_hash(args.command_arguments[0], Strings::to_utf16(args.command_arguments[1])); + do_file_hash(args.command_arguments[0], args.command_arguments[1]); } Checks::exit_success(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 85b567adb..0d185476e 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -8,12 +8,6 @@ namespace vcpkg::Commands::Integrate { - static const std::array OLD_SYSTEM_TARGET_FILES = { - System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", - System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"}; - static const fs::path SYSTEM_WIDE_TARGETS_FILE = - System::get_program_files_32_bit() / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; - static std::string create_appdata_targets_shortcut(const std::string& target_path) noexcept { return Strings::format(R"###( @@ -111,6 +105,7 @@ namespace vcpkg::Commands::Integrate NO }; +#if defined(_WIN32) static ElevationPromptChoice elevated_cmd_execute(const std::string& param) { SHELLEXECUTEINFOW sh_ex_info = {0}; @@ -138,16 +133,29 @@ namespace vcpkg::Commands::Integrate CloseHandle(sh_ex_info.hProcess); return ElevationPromptChoice::YES; } +#endif +#if defined(_WIN32) static fs::path get_appdata_targets_path() { static const fs::path LOCAL_APP_DATA = - fs::path(System::get_environment_variable(L"LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO)); + fs::path(System::get_environment_variable("LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO)); return LOCAL_APP_DATA / "vcpkg" / "vcpkg.user.targets"; } +#endif +#if defined(_WIN32) static void integrate_install(const VcpkgPaths& paths) { + static const std::array OLD_SYSTEM_TARGET_FILES = { + System::get_program_files_32_bit() / + "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", + System::get_program_files_32_bit() / + "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"}; + static const fs::path SYSTEM_WIDE_TARGETS_FILE = + System::get_program_files_32_bit() / + "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; + auto& fs = paths.get_filesystem(); // TODO: This block of code should eventually be removed @@ -262,6 +270,7 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")", Checks::exit_success(VCPKG_LINE_INFO); } +#endif static void integrate_project(const VcpkgPaths& paths) { @@ -286,10 +295,10 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")", fs.write_contents(nuspec_file_path, create_nuspec_file_contents(paths.root, nuget_id, nupkg_version)); // Using all forward slashes for the command line - const std::wstring cmd_line = Strings::wformat(LR"("%s" pack -OutputDirectory "%s" "%s" > nul)", - nuget_exe.native(), - buildsystems_dir.native(), - nuspec_file_path.native()); + const std::string cmd_line = Strings::format(R"("%s" pack -OutputDirectory "%s" "%s" > nul)", + nuget_exe.u8string(), + buildsystems_dir.u8string(), + nuspec_file_path.u8string()); const int exit_code = System::cmd_execute_clean(cmd_line); @@ -325,6 +334,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console args.check_exact_arg_count(1, EXAMPLE); args.check_and_get_optional_command_arguments({}); +#if defined(_WIN32) if (args.command_arguments[0] == "install") { return integrate_install(paths); @@ -337,6 +347,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console { return integrate_project(paths); } +#endif Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown parameter %s for integrate", args.command_arguments[0]); } diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp index b70ad2b80..a8c043751 100644 --- a/toolsrc/src/vcpkg/commands.portsdiff.cpp +++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp @@ -75,28 +75,28 @@ namespace vcpkg::Commands::PortsDiff } static std::map read_ports_from_commit(const VcpkgPaths& paths, - const std::wstring& git_commit_id) + const std::string& git_commit_id) { std::error_code ec; auto& fs = paths.get_filesystem(); const fs::path& git_exe = paths.get_git_exe(); const fs::path dot_git_dir = paths.root / ".git"; - const std::wstring ports_dir_name_as_string = paths.ports.filename().native(); + const std::string ports_dir_name_as_string = paths.ports.filename().u8string(); const fs::path temp_checkout_path = - paths.root / Strings::wformat(L"%s-%s", ports_dir_name_as_string, git_commit_id); + paths.root / Strings::format("%s-%s", ports_dir_name_as_string, git_commit_id); fs.create_directory(temp_checkout_path, ec); - const std::wstring checkout_this_dir = - Strings::wformat(LR"(.\%s)", ports_dir_name_as_string); // Must be relative to the root of the repository - - const std::wstring cmd = - Strings::wformat(LR"("%s" --git-dir="%s" --work-tree="%s" checkout %s -f -q -- %s %s & "%s" reset >NUL)", - git_exe.native(), - dot_git_dir.native(), - temp_checkout_path.native(), - git_commit_id, - checkout_this_dir, - L".vcpkg-root", - git_exe.native()); + const auto checkout_this_dir = + Strings::format(R"(.\%s)", ports_dir_name_as_string); // Must be relative to the root of the repository + + const std::string cmd = + Strings::format(R"("%s" --git-dir="%s" --work-tree="%s" checkout %s -f -q -- %s %s & "%s" reset >NUL)", + git_exe.u8string(), + dot_git_dir.u8string(), + temp_checkout_path.u8string(), + git_commit_id, + checkout_this_dir, + ".vcpkg-root", + git_exe.u8string()); System::cmd_execute_clean(cmd); const std::map names_and_versions = Paragraphs::load_all_port_names_and_versions( paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); @@ -104,16 +104,14 @@ namespace vcpkg::Commands::PortsDiff return names_and_versions; } - static void check_commit_exists(const fs::path& git_exe, const std::wstring& git_commit_id) + static void check_commit_exists(const fs::path& git_exe, const std::string& git_commit_id) { static const std::string VALID_COMMIT_OUTPUT = "commit\n"; - const std::wstring cmd = Strings::wformat(LR"("%s" cat-file -t %s)", git_exe.native(), git_commit_id); + const auto cmd = Strings::format(R"("%s" cat-file -t %s)", git_exe.u8string(), git_commit_id); const System::ExitCodeAndOutput output = System::cmd_execute_and_capture_output(cmd); - Checks::check_exit(VCPKG_LINE_INFO, - output.output == VALID_COMMIT_OUTPUT, - "Invalid commit id %s", - Strings::to_utf8(git_commit_id)); + Checks::check_exit( + VCPKG_LINE_INFO, output.output == VALID_COMMIT_OUTPUT, "Invalid commit id %s", git_commit_id); } void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) @@ -126,9 +124,9 @@ namespace vcpkg::Commands::PortsDiff const fs::path& git_exe = paths.get_git_exe(); - const std::wstring git_commit_id_for_previous_snapshot = Strings::to_utf16(args.command_arguments.at(0)); - const std::wstring git_commit_id_for_current_snapshot = - args.command_arguments.size() < 2 ? L"HEAD" : Strings::to_utf16(args.command_arguments.at(1)); + const std::string git_commit_id_for_previous_snapshot = args.command_arguments.at(0); + const std::string git_commit_id_for_current_snapshot = + args.command_arguments.size() < 2 ? "HEAD" : args.command_arguments.at(1); check_commit_exists(git_exe, git_commit_id_for_current_snapshot); check_commit_exists(git_exe, git_commit_id_for_previous_snapshot); diff --git a/toolsrc/src/vcpkg/commands.version.cpp b/toolsrc/src/vcpkg/commands.version.cpp index c6cc82d1f..403c355b5 100644 --- a/toolsrc/src/vcpkg/commands.version.cpp +++ b/toolsrc/src/vcpkg/commands.version.cpp @@ -20,20 +20,29 @@ namespace vcpkg::Commands::Version #ifndef NDEBUG + std::string("-debug") #endif - + std::string(Metrics::get_compiled_metrics_enabled() ? Strings::EMPTY : "-external"); + + std::string(Metrics::get_compiled_metrics_enabled() ? "" : "-external"); return S_VERSION; } + static int scan3(const char* input, const char* pattern, int* a, int* b, int* c) + { +#if defined(_WIN32) + return sscanf_s(input, pattern, a, b, c); +#else + return sscanf(input, pattern, a, b, c); +#endif + } + void warn_if_vcpkg_version_mismatch(const VcpkgPaths& paths) { auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt"); if (const auto version_contents = version_file.get()) { int maj1, min1, rev1; - const auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1); + const auto num1 = scan3(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1); int maj2, min2, rev2; - const auto num2 = sscanf_s(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2); + const auto num2 = scan3(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2); if (num1 == 3 && num2 == 3) { diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index da8f1e178..02b2ec785 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -43,14 +43,17 @@ namespace vcpkg::Dependencies bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } } -template<> -struct std::hash +namespace std { - size_t operator()(const vcpkg::Dependencies::ClusterPtr& value) const + template<> + struct hash { - return std::hash()(value.ptr->spec); - } -}; + size_t operator()(const vcpkg::Dependencies::ClusterPtr& value) const + { + return std::hash()(value.ptr->spec); + } + }; +} namespace vcpkg::Dependencies { diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index de6464c87..5e27d4126 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -137,11 +137,10 @@ namespace vcpkg::Export fs.write_contents(nuspec_file_path, nuspec_file_content); // -NoDefaultExcludes is needed for ".vcpkg-root" - const std::wstring cmd_line = - Strings::wformat(LR"("%s" pack -OutputDirectory "%s" "%s" -NoDefaultExcludes > nul)", - nuget_exe.native(), - output_dir.native(), - nuspec_file_path.native()); + const auto cmd_line = Strings::format(R"("%s" pack -OutputDirectory "%s" "%s" -NoDefaultExcludes > nul)", + nuget_exe.u8string(), + output_dir.u8string(), + nuspec_file_path.u8string()); const int exit_code = System::cmd_execute_clean(cmd_line); Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: NuGet package creation failed"); @@ -160,25 +159,25 @@ namespace vcpkg::Export constexpr ArchiveFormat() = delete; - constexpr ArchiveFormat(BackingEnum backing_enum, const wchar_t* extension, const wchar_t* cmake_option) + constexpr ArchiveFormat(BackingEnum backing_enum, const char* extension, const char* cmake_option) : backing_enum(backing_enum), m_extension(extension), m_cmake_option(cmake_option) { } constexpr operator BackingEnum() const { return backing_enum; } - constexpr CWStringView extension() const { return this->m_extension; } - constexpr CWStringView cmake_option() const { return this->m_cmake_option; } + constexpr CStringView extension() const { return this->m_extension; } + constexpr CStringView cmake_option() const { return this->m_cmake_option; } private: BackingEnum backing_enum; - const wchar_t* m_extension; - const wchar_t* m_cmake_option; + const char* m_extension; + const char* m_cmake_option; }; namespace ArchiveFormatC { - constexpr const ArchiveFormat ZIP(ArchiveFormat::BackingEnum::ZIP, L"zip", L"zip"); - constexpr const ArchiveFormat SEVEN_ZIP(ArchiveFormat::BackingEnum::SEVEN_ZIP, L"7z", L"7zip"); + constexpr const ArchiveFormat ZIP(ArchiveFormat::BackingEnum::ZIP, "zip", "zip"); + constexpr const ArchiveFormat SEVEN_ZIP(ArchiveFormat::BackingEnum::SEVEN_ZIP, "7z", "7zip"); } static fs::path do_archive_export(const VcpkgPaths& paths, @@ -188,17 +187,17 @@ namespace vcpkg::Export { const fs::path& cmake_exe = paths.get_cmake_exe(); - const std::wstring exported_dir_filename = raw_exported_dir.filename().native(); - const std::wstring exported_archive_filename = - Strings::wformat(L"%s.%s", exported_dir_filename, format.extension()); + const std::string exported_dir_filename = raw_exported_dir.filename().u8string(); + const std::string exported_archive_filename = + Strings::format("%s.%s", exported_dir_filename, format.extension()); const fs::path exported_archive_path = (output_dir / exported_archive_filename); // -NoDefaultExcludes is needed for ".vcpkg-root" - const std::wstring cmd_line = Strings::wformat(LR"("%s" -E tar "cf" "%s" --format=%s -- "%s")", - cmake_exe.native(), - exported_archive_path.native(), - format.cmake_option(), - raw_exported_dir.native()); + const auto cmd_line = Strings::format(R"("%s" -E tar "cf" "%s" --format=%s -- "%s")", + cmake_exe.u8string(), + exported_archive_path.u8string(), + format.cmake_option(), + raw_exported_dir.u8string()); const int exit_code = System::cmd_execute_clean(cmd_line); Checks::check_exit( @@ -361,13 +360,13 @@ namespace vcpkg::Export static void print_next_step_info(const fs::path& prefix) { const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; - const CMakeVariable cmake_variable = CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); + const CMakeVariable cmake_variable = CMakeVariable("CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); System::println("\n" "To use the exported libraries in CMake projects use:" "\n" " %s" "\n", - Strings::to_utf8(cmake_variable.s)); + cmake_variable.s); }; static void handle_raw_based_export(Span export_plan, diff --git a/toolsrc/src/vcpkg/globalstate.cpp b/toolsrc/src/vcpkg/globalstate.cpp index de564d357..43230fa4b 100644 --- a/toolsrc/src/vcpkg/globalstate.cpp +++ b/toolsrc/src/vcpkg/globalstate.cpp @@ -5,9 +5,9 @@ namespace vcpkg { Util::LockGuarded GlobalState::timer; - std::atomic GlobalState::debugging = false; - std::atomic GlobalState::feature_packages = false; + std::atomic GlobalState::debugging(false); + std::atomic GlobalState::feature_packages(false); - std::atomic GlobalState::g_init_console_cp = 0; - std::atomic GlobalState::g_init_console_output_cp = 0; + std::atomic GlobalState::g_init_console_cp(0); + std::atomic GlobalState::g_init_console_output_cp(0); } diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 4a1e5537b..adbd8c943 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -70,9 +70,8 @@ namespace vcpkg::Install } const std::string filename = file.filename().generic_string(); - if (fs::is_regular_file(status) && - (Strings::case_insensitive_ascii_compare(filename.c_str(), "CONTROL") || - Strings::case_insensitive_ascii_compare(filename.c_str(), "BUILD_INFO"))) + if (fs::is_regular_file(status) && (Strings::case_insensitive_ascii_equals(filename.c_str(), "CONTROL") || + Strings::case_insensitive_ascii_equals(filename.c_str(), "BUILD_INFO"))) { // Do not copy the control file continue; diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 84c1ee208..854baa0ca 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -19,6 +19,7 @@ namespace vcpkg::Metrics std::array date; date.fill(0); +#if defined(_WIN32) struct _timeb timebuffer; _ftime_s(&timebuffer); @@ -26,10 +27,17 @@ namespace vcpkg::Metrics const int milli = timebuffer.millitm; const errno_t err = gmtime_s(&newtime, &now); + if (err) { - return Strings::EMPTY; + return ""; } +#else + time_t now; + time(&now); + gmtime_r(&now, &newtime); + const int milli = 0; +#endif strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S", &newtime); return std::string(&date[0]) + "." + std::to_string(milli) + "Z"; @@ -121,6 +129,7 @@ namespace vcpkg::Metrics static std::string get_os_version_string() { +#if defined(_WIN32) std::wstring path; path.resize(MAX_PATH); const auto n = GetSystemDirectoryW(&path[0], static_cast(path.size())); @@ -128,16 +137,16 @@ namespace vcpkg::Metrics path += L"\\kernel32.dll"; const auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr); - if (versz == 0) return Strings::EMPTY; + if (versz == 0) return ""; std::vector verbuf; verbuf.resize(versz); - if (!GetFileVersionInfoW(path.c_str(), 0, static_cast(verbuf.size()), &verbuf[0])) return Strings::EMPTY; + if (!GetFileVersionInfoW(path.c_str(), 0, static_cast(verbuf.size()), &verbuf[0])) return ""; void* rootblock; UINT rootblocksize; - if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return Strings::EMPTY; + if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return ""; auto rootblock_ffi = static_cast(rootblock); @@ -145,6 +154,9 @@ namespace vcpkg::Metrics static_cast(HIWORD(rootblock_ffi->dwProductVersionMS)), static_cast(LOWORD(rootblock_ffi->dwProductVersionMS)), static_cast(HIWORD(rootblock_ffi->dwProductVersionLS))); +#else + return "unknown"; +#endif } struct MetricMessage @@ -223,9 +235,13 @@ namespace vcpkg::Metrics std::wstring get_SQM_user() { +#if defined(_WIN32) auto hkcu_sqmclient = System::get_registry_string(HKEY_CURRENT_USER, LR"(Software\Microsoft\SQMClient)", L"UserId"); return hkcu_sqmclient.value_or(L"{}"); +#else + return L"{}"; +#endif } void Metrics::set_user_information(const std::string& user_id, const std::string& first_use_time) @@ -264,6 +280,7 @@ namespace vcpkg::Metrics void Metrics::upload(const std::string& payload) { +#if defined(_WIN32) HINTERNET connect = nullptr, request = nullptr; BOOL results = FALSE; @@ -344,18 +361,12 @@ namespace vcpkg::Metrics if (request) WinHttpCloseHandle(request); if (connect) WinHttpCloseHandle(connect); if (session) WinHttpCloseHandle(session); - } - - static fs::path get_bindir() - { - wchar_t buf[_MAX_PATH]; - const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); - if (bytes == 0) std::abort(); - return fs::path(buf, buf + bytes); +#endif } void Metrics::flush() { +#if defined(_WIN32) const std::string payload = g_metricmessage.format_event_data_template(); if (g_should_print_metrics) std::cerr << payload << "\n"; if (!g_should_send_metrics) return; @@ -373,14 +384,14 @@ namespace vcpkg::Metrics if (true) { const fs::path exe_path = [&fs]() -> fs::path { - auto vcpkgdir = get_bindir().parent_path(); + auto vcpkgdir = System::get_exe_path_of_current_process().parent_path(); auto path = vcpkgdir / "vcpkgmetricsuploader.exe"; if (fs.exists(path)) return path; path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; if (fs.exists(path)) return path; - return Strings::WEMPTY; + return ""; }(); std::error_code ec; @@ -391,8 +402,9 @@ namespace vcpkg::Metrics const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); fs.write_contents(vcpkg_metrics_txt_path, payload); - const std::wstring cmd_line = - Strings::wformat(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native()); + const std::string cmd_line = + Strings::format("start %s %s", temp_folder_path_exe.u8string(), vcpkg_metrics_txt_path.u8string()); System::cmd_execute_clean(cmd_line); +#endif } } diff --git a/toolsrc/src/vcpkg/packagespec.cpp b/toolsrc/src/vcpkg/packagespec.cpp index 01a09618d..6e40d70f5 100644 --- a/toolsrc/src/vcpkg/packagespec.cpp +++ b/toolsrc/src/vcpkg/packagespec.cpp @@ -38,7 +38,7 @@ namespace vcpkg for (auto&& feature : spec->features) f_specs.push_back(FeatureSpec{pspec, feature}); - if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, Strings::EMPTY}); + if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, ""}); } else { @@ -56,7 +56,7 @@ namespace vcpkg std::vector ret; for (auto&& spec : specs) { - ret.emplace_back(spec.package_spec, Strings::EMPTY); + ret.emplace_back(spec.package_spec, ""); for (auto&& feature : spec.features) ret.emplace_back(spec.package_spec, feature); } diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp index 116a7f5c8..c2670f561 100644 --- a/toolsrc/src/vcpkg/parse.cpp +++ b/toolsrc/src/vcpkg/parse.cpp @@ -31,7 +31,7 @@ namespace vcpkg::Parse } std::string ParagraphParser::optional_field(const std::string& fieldname) const { - return remove_field(&fields, fieldname).value_or(Strings::EMPTY); + return remove_field(&fields, fieldname).value_or(""); } std::unique_ptr ParagraphParser::error_info(const std::string& name) const { diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp index 22cf67e86..0063f8d98 100644 --- a/toolsrc/src/vcpkg/postbuildlint.cpp +++ b/toolsrc/src/vcpkg/postbuildlint.cpp @@ -284,13 +284,10 @@ namespace vcpkg::PostBuildLint std::vector dlls_with_no_exports; for (const fs::path& dll : dlls) { - const std::wstring cmd_line = - Strings::wformat(LR"("%s" /exports "%s")", dumpbin_exe.native(), dll.native()); + const std::string cmd_line = + Strings::format(R"("%s" /exports "%s")", dumpbin_exe.u8string(), dll.u8string()); System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, - ec_data.exit_code == 0, - "Running command:\n %s\n failed", - Strings::to_utf8(cmd_line)); + Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line); if (ec_data.output.find("ordinal hint RVA name") == std::string::npos) { @@ -321,13 +318,10 @@ namespace vcpkg::PostBuildLint std::vector dlls_with_improper_uwp_bit; for (const fs::path& dll : dlls) { - const std::wstring cmd_line = - Strings::wformat(LR"("%s" /headers "%s")", dumpbin_exe.native(), dll.native()); + const std::string cmd_line = + Strings::format(R"("%s" /headers "%s")", dumpbin_exe.u8string(), dll.u8string()); System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, - ec_data.exit_code == 0, - "Running command:\n %s\n failed", - Strings::to_utf8(cmd_line)); + Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line); if (ec_data.output.find("App Container") == std::string::npos) { @@ -599,13 +593,10 @@ namespace vcpkg::PostBuildLint for (const fs::path& lib : libs) { - const std::wstring cmd_line = - Strings::wformat(LR"("%s" /directives "%s")", dumpbin_exe.native(), lib.native()); + const std::string cmd_line = + Strings::format(R"("%s" /directives "%s")", dumpbin_exe.u8string(), lib.u8string()); System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, - ec_data.exit_code == 0, - "Running command:\n %s\n failed", - Strings::to_utf8(cmd_line)); + Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line); for (const BuildType& bad_build_type : bad_build_types) { @@ -655,13 +646,9 @@ namespace vcpkg::PostBuildLint for (const fs::path& dll : dlls) { - const std::wstring cmd_line = - Strings::wformat(LR"("%s" /dependents "%s")", dumpbin_exe.native(), dll.native()); + const auto cmd_line = Strings::format(R"("%s" /dependents "%s")", dumpbin_exe.u8string(), dll.u8string()); System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, - ec_data.exit_code == 0, - "Running command:\n %s\n failed", - Strings::to_utf8(cmd_line)); + Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line); for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts("v141")) { @@ -696,8 +683,8 @@ namespace vcpkg::PostBuildLint std::vector misplaced_files = fs.get_files_non_recursive(dir); Util::unstable_keep_if(misplaced_files, [&fs](const fs::path& path) { const std::string filename = path.filename().generic_string(); - if (Strings::case_insensitive_ascii_compare(filename.c_str(), "CONTROL") || - Strings::case_insensitive_ascii_compare(filename.c_str(), "BUILD_INFO")) + if (Strings::case_insensitive_ascii_equals(filename.c_str(), "CONTROL") || + Strings::case_insensitive_ascii_equals(filename.c_str(), "BUILD_INFO")) return false; return !fs.is_directory(path); }); diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 04ddba1e4..2ec32855a 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -21,7 +21,7 @@ namespace vcpkg::Remove { auto& fs = paths.get_filesystem(); auto spghs = status_db->find_all(spec.name(), spec.triplet()); - const auto core_pkg = **status_db->find(spec.name(), spec.triplet(), Strings::EMPTY); + const auto core_pkg = **status_db->find(spec.name(), spec.triplet(), ""); for (auto&& spgh : spghs) { diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp index d766dcb72..2a9480538 100644 --- a/toolsrc/src/vcpkg/sourceparagraph.cpp +++ b/toolsrc/src/vcpkg/sourceparagraph.cpp @@ -178,11 +178,11 @@ namespace vcpkg return Strings::format("%s[%s]", this->depend.name, features); } - std::vector vcpkg::expand_qualified_dependencies(const std::vector& depends) + std::vector expand_qualified_dependencies(const std::vector& depends) { return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency { auto pos = depend_string.find(' '); - if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, Strings::EMPTY); + if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, ""); // expect of the form "\w+ \[\w+\]" Dependency dep; @@ -190,7 +190,7 @@ namespace vcpkg if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')') { // Error, but for now just slurp the entire string. - return Dependency::parse_dependency(depend_string, Strings::EMPTY); + return Dependency::parse_dependency(depend_string, ""); } dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3); return dep; diff --git a/toolsrc/src/vcpkg/triplet.cpp b/toolsrc/src/vcpkg/triplet.cpp index 4ebb97a9b..4cba1523d 100644 --- a/toolsrc/src/vcpkg/triplet.cpp +++ b/toolsrc/src/vcpkg/triplet.cpp @@ -18,11 +18,14 @@ namespace vcpkg const TripletInstance Triplet::DEFAULT_INSTANCE({}); } -template<> -struct std::hash +namespace std { - size_t operator()(const vcpkg::TripletInstance& t) const { return t.hash; } -}; + template<> + struct hash + { + size_t operator()(const vcpkg::TripletInstance& t) const { return t.hash; } + }; +} namespace vcpkg { diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp index 522961693..209f6a3f2 100644 --- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp +++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp @@ -45,12 +45,20 @@ namespace vcpkg option_field = new_setting; } +#if defined(_WIN32) VcpkgCmdArguments VcpkgCmdArguments::create_from_command_line(const int argc, const wchar_t* const* const argv) +#else + VcpkgCmdArguments VcpkgCmdArguments::create_from_command_line(const int argc, const char* const* const argv) +#endif { std::vector v; for (int i = 1; i < argc; ++i) { +#if defined(_WIN32) v.push_back(Strings::to_utf8(argv[i])); +#else + v.push_back(argv[i]); +#endif } return VcpkgCmdArguments::create_from_arg_sequence(v.data(), v.data() + v.size()); @@ -223,17 +231,17 @@ namespace vcpkg void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count) const { - return check_max_arg_count(expected_arg_count, Strings::EMPTY); + return check_max_arg_count(expected_arg_count, ""); } void VcpkgCmdArguments::check_min_arg_count(const size_t expected_arg_count) const { - return check_min_arg_count(expected_arg_count, Strings::EMPTY); + return check_min_arg_count(expected_arg_count, ""); } void VcpkgCmdArguments::check_exact_arg_count(const size_t expected_arg_count) const { - return check_exact_arg_count(expected_arg_count, Strings::EMPTY); + return check_exact_arg_count(expected_arg_count, ""); } void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count, const std::string& example_text) const diff --git a/toolsrc/src/vcpkg/vcpkglib.cpp b/toolsrc/src/vcpkg/vcpkglib.cpp index 23c774210..38b130f6f 100644 --- a/toolsrc/src/vcpkg/vcpkglib.cpp +++ b/toolsrc/src/vcpkg/vcpkglib.cpp @@ -212,30 +212,26 @@ namespace vcpkg return installed_files; } - CMakeVariable::CMakeVariable(const CWStringView varname, const wchar_t* varvalue) - : s(Strings::wformat(LR"("-D%s=%s")", varname, varvalue)) + CMakeVariable::CMakeVariable(const CStringView varname, const char* varvalue) + : s(Strings::format(R"("-D%s=%s")", varname, varvalue)) { } - CMakeVariable::CMakeVariable(const CWStringView varname, const std::string& varvalue) - : CMakeVariable(varname, Strings::to_utf16(varvalue).c_str()) - { - } - CMakeVariable::CMakeVariable(const CWStringView varname, const std::wstring& varvalue) + CMakeVariable::CMakeVariable(const CStringView varname, const std::string& varvalue) : CMakeVariable(varname, varvalue.c_str()) { } - CMakeVariable::CMakeVariable(const CWStringView varname, const fs::path& path) - : CMakeVariable(varname, path.generic_wstring()) + CMakeVariable::CMakeVariable(const CStringView varname, const fs::path& path) + : CMakeVariable(varname, path.generic_u8string()) { } - std::wstring make_cmake_cmd(const fs::path& cmake_exe, - const fs::path& cmake_script, - const std::vector& pass_variables) + std::string make_cmake_cmd(const fs::path& cmake_exe, + const fs::path& cmake_script, + const std::vector& pass_variables) { - const std::wstring cmd_cmake_pass_variables = Strings::join(L" ", pass_variables, [](auto&& v) { return v.s; }); - return Strings::wformat( - LR"("%s" %s -P "%s")", cmake_exe.native(), cmd_cmake_pass_variables, cmake_script.generic_wstring()); + const std::string cmd_cmake_pass_variables = Strings::join(" ", pass_variables, [](auto&& v) { return v.s; }); + return Strings::format( + R"("%s" %s -P "%s")", cmake_exe.u8string(), cmd_cmake_pass_variables, cmake_script.generic_u8string()); } std::string shorten_text(const std::string& desc, size_t length) diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index c57077eaa..90f9cb00b 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -10,16 +10,16 @@ namespace vcpkg { - static constexpr CWStringView V_120 = L"v120"; - static constexpr CWStringView V_140 = L"v140"; - static constexpr CWStringView V_141 = L"v141"; + static constexpr CStringView V_120 = "v120"; + static constexpr CStringView V_140 = "v140"; + static constexpr CStringView V_141 = "v141"; - static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd, + static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, const std::array& expected_version) { static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###"); - const auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s)", version_cmd)); + const auto rc = System::cmd_execute_and_capture_output(Strings::format(R"(%s)", version_cmd)); if (rc.exit_code != 0) { return false; @@ -46,11 +46,11 @@ namespace vcpkg } static Optional find_if_has_equal_or_greater_version(const std::vector& candidate_paths, - const std::wstring& version_check_arguments, + const std::string& version_check_arguments, const std::array& expected_version) { auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { - const std::wstring cmd = Strings::wformat(LR"("%s" %s)", p.native(), version_check_arguments); + const std::string cmd = Strings::format(R"("%s" %s)", p.u8string(), version_check_arguments); return exists_and_has_equal_or_greater_version(cmd, expected_version); }); @@ -63,27 +63,26 @@ namespace vcpkg } static fs::path fetch_dependency(const fs::path& scripts_folder, - const std::wstring& tool_name, + const std::string& tool_name, const fs::path& expected_downloaded_path, const std::array& version) { - const std::string tool_name_utf8 = Strings::to_utf8(tool_name); const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", - tool_name_utf8, + tool_name, version_as_string, - tool_name_utf8, + tool_name, version_as_string); const fs::path script = scripts_folder / "fetchDependency.ps1"; const auto install_cmd = - System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name)); + System::create_powershell_script_cmd(script, Strings::format("-Dependency %s", tool_name)); const System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd); if (rc.exit_code) { System::println(System::Color::error, "Launching powershell failed or was denied when trying to fetch %s version %s.\n" "(No sufficient installed version was found)", - tool_name_utf8, + tool_name, version_as_string); { auto locked_metrics = Metrics::g_metrics.lock(); @@ -107,16 +106,18 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { static constexpr std::array EXPECTED_VERSION = {3, 9, 3}; - static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; + static const std::string VERSION_CHECK_ARGUMENTS = "--version"; const fs::path downloaded_copy = downloads_folder / "cmake-3.9.3-win32-x86" / "bin" / "cmake.exe"; - const std::vector from_path = Files::find_from_PATH(L"cmake"); + const std::vector from_path = Files::find_from_PATH("cmake"); std::vector candidate_paths; candidate_paths.push_back(downloaded_copy); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); +#if defined(_WIN32) candidate_paths.push_back(System::get_program_files_platform_bitness() / "CMake" / "bin" / "cmake.exe"); candidate_paths.push_back(System::get_program_files_32_bit() / "CMake" / "bin"); +#endif const Optional path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); @@ -125,43 +126,44 @@ namespace vcpkg return *p; } - return fetch_dependency(scripts_folder, L"cmake", downloaded_copy, EXPECTED_VERSION); + return fetch_dependency(scripts_folder, "cmake", downloaded_copy, EXPECTED_VERSION); } fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { static constexpr std::array EXPECTED_VERSION = {4, 3, 0}; - static const std::wstring VERSION_CHECK_ARGUMENTS = Strings::WEMPTY; const fs::path downloaded_copy = downloads_folder / "nuget-4.3.0" / "nuget.exe"; - const std::vector from_path = Files::find_from_PATH(L"nuget"); + const std::vector from_path = Files::find_from_PATH("nuget"); std::vector candidate_paths; candidate_paths.push_back(downloaded_copy); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - auto path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + auto path = find_if_has_equal_or_greater_version(candidate_paths, "", EXPECTED_VERSION); if (const auto p = path.get()) { return *p; } - return fetch_dependency(scripts_folder, L"nuget", downloaded_copy, EXPECTED_VERSION); + return fetch_dependency(scripts_folder, "nuget", downloaded_copy, EXPECTED_VERSION); } fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { static constexpr std::array EXPECTED_VERSION = {2, 14, 1}; - static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; + static const std::string VERSION_CHECK_ARGUMENTS = "--version"; const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.1-32-bit" / "cmd" / "git.exe"; - const std::vector from_path = Files::find_from_PATH(L"git"); + const std::vector from_path = Files::find_from_PATH("git"); std::vector candidate_paths; candidate_paths.push_back(downloaded_copy); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); +#if defined(_WIN32) candidate_paths.push_back(System::get_program_files_platform_bitness() / "git" / "cmd" / "git.exe"); candidate_paths.push_back(System::get_program_files_32_bit() / "git" / "cmd" / "git.exe"); +#endif const Optional path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); @@ -170,13 +172,13 @@ namespace vcpkg return *p; } - return fetch_dependency(scripts_folder, L"git", downloaded_copy, EXPECTED_VERSION); + return fetch_dependency(scripts_folder, "git", downloaded_copy, EXPECTED_VERSION); } static fs::path get_ifw_installerbase_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { static constexpr std::array EXPECTED_VERSION = {3, 1, 81}; - static const std::wstring VERSION_CHECK_ARGUMENTS = L"--framework-version"; + static const std::string VERSION_CHECK_ARGUMENTS = "--framework-version"; const fs::path downloaded_copy = downloads_folder / "QtInstallerFramework-win-x86" / "bin" / "installerbase.exe"; @@ -184,11 +186,11 @@ namespace vcpkg std::vector candidate_paths; candidate_paths.push_back(downloaded_copy); // TODO: Uncomment later - // const std::vector from_path = Files::find_from_PATH(L"installerbase"); + // const std::vector from_path = Files::find_from_PATH("installerbase"); // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / + // candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" / // "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe"); - // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / + // candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" / // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); const Optional path = @@ -198,7 +200,7 @@ namespace vcpkg return *p; } - return fetch_dependency(scripts_folder, L"installerbase", downloaded_copy, EXPECTED_VERSION); + return fetch_dependency(scripts_folder, "installerbase", downloaded_copy, EXPECTED_VERSION); } Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir) @@ -322,7 +324,7 @@ namespace vcpkg static std::vector get_visual_studio_instances(const VcpkgPaths& paths) { const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; - const std::wstring cmd = System::create_powershell_script_cmd(script); + const std::string cmd = System::create_powershell_script_cmd(script); const System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); Checks::check_exit( VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect Visual Studio instances"); @@ -370,21 +372,21 @@ namespace vcpkg // Get all supported architectures std::vector supported_architectures; if (fs.exists(vcvarsall_dir / "vcvars32.bat")) - supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); + supported_architectures.push_back({"x86", CPU::X86, CPU::X86}); if (fs.exists(vcvarsall_dir / "vcvars64.bat")) - supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); + supported_architectures.push_back({"amd64", CPU::X64, CPU::X64}); if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) - supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + supported_architectures.push_back({"x86_amd64", CPU::X86, CPU::X64}); if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) - supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); + supported_architectures.push_back({"x86_arm", CPU::X86, CPU::ARM}); if (fs.exists(vcvarsall_dir / "vcvarsx86_arm64.bat")) - supported_architectures.push_back({L"x86_arm64", CPU::X86, CPU::ARM64}); + supported_architectures.push_back({"x86_arm64", CPU::X86, CPU::ARM64}); if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) - supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + supported_architectures.push_back({"amd64_x86", CPU::X64, CPU::X86}); if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) - supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + supported_architectures.push_back({"amd64_arm", CPU::X64, CPU::ARM}); if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm64.bat")) - supported_architectures.push_back({L"amd64_arm64", CPU::X64, CPU::ARM64}); + supported_architectures.push_back({"amd64_arm64", CPU::X64, CPU::ARM64}); // Locate the "best" MSVC toolchain version const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; @@ -412,7 +414,7 @@ namespace vcpkg found_toolsets.push_back(Toolset{vs_instance.root_path, dumpbin_path, vcvarsall_bat, - {L"-vcvars_ver=14.0"}, + {"-vcvars_ver=14.0"}, V_140, supported_architectures}); } @@ -437,17 +439,17 @@ namespace vcpkg const fs::path vs2015_bin_dir = vcvarsall_bat.parent_path() / "bin"; std::vector supported_architectures; if (fs.exists(vs2015_bin_dir / "vcvars32.bat")) - supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); + supported_architectures.push_back({"x86", CPU::X86, CPU::X86}); if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat")) - supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); + supported_architectures.push_back({"x64", CPU::X64, CPU::X64}); if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) - supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + supported_architectures.push_back({"x86_amd64", CPU::X86, CPU::X64}); if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) - supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); + supported_architectures.push_back({"x86_arm", CPU::X86, CPU::ARM}); if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) - supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + supported_architectures.push_back({"amd64_x86", CPU::X64, CPU::X86}); if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) - supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + supported_architectures.push_back({"amd64_arm", CPU::X64, CPU::ARM}); if (fs.exists(vs2015_dumpbin_exe)) { @@ -489,15 +491,12 @@ namespace vcpkg if (tsv && vsp) { - const std::wstring w_toolset_version = Strings::to_utf16(*tsv); - const fs::path vs_root_path = *vsp; - Util::stable_keep_if(candidates, [&](const Toolset* t) { - return w_toolset_version == t->version && vs_root_path == t->visual_studio_root_path; - }); + Util::stable_keep_if( + candidates, [&](const Toolset* t) { return *tsv == t->version && *vsp == t->visual_studio_root_path; }); Checks::check_exit(VCPKG_LINE_INFO, !candidates.empty(), "Could not find Visual Studio instace at %s with %s toolset.", - vs_root_path.generic_string(), + vsp->u8string(), *tsv); Checks::check_exit(VCPKG_LINE_INFO, candidates.size() == 1); @@ -506,8 +505,7 @@ namespace vcpkg if (tsv) { - const std::wstring w_toolset_version = Strings::to_utf16(*tsv); - Util::stable_keep_if(candidates, [&](const Toolset* t) { return w_toolset_version == t->version; }); + Util::stable_keep_if(candidates, [&](const Toolset* t) { return *tsv == t->version; }); Checks::check_exit( VCPKG_LINE_INFO, !candidates.empty(), "Could not find Visual Studio instace with %s toolset.", *tsv); } -- cgit v1.2.3 From ced047ad78734aed239669a0fd9eca9e81718966 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 16 Oct 2017 13:50:28 -0700 Subject: Remove usages of CWStringView, except in Strings::to_utf8() --- toolsrc/src/vcpkg/base/strings.cpp | 4 ++-- toolsrc/src/vcpkg/base/system.cpp | 26 +++++++++++++++----------- toolsrc/src/vcpkg/commands.edit.cpp | 13 ++++++------- toolsrc/src/vcpkg/metrics.cpp | 8 ++++---- 4 files changed, 27 insertions(+), 24 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index fa04279b9..160aa98e9 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -72,7 +72,7 @@ namespace vcpkg::Strings::details namespace vcpkg::Strings { - std::wstring to_utf16(const CStringView s) + std::wstring to_utf16(const CStringView& s) { #if defined(_WIN32) const int size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0); @@ -85,7 +85,7 @@ namespace vcpkg::Strings #endif } - std::string to_utf8(const CWStringView w) + std::string to_utf8(const CWStringView& w) { #if defined(_WIN32) const int size = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr); diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index e92d06f6e..730b22c43 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -38,7 +38,7 @@ namespace vcpkg::System #endif } - Optional to_cpu_architecture(CStringView arch) + Optional to_cpu_architecture(const CStringView& arch) { if (Strings::case_insensitive_ascii_equals(arch, "x86")) return CPUArchitecture::X86; if (Strings::case_insensitive_ascii_equals(arch, "x64")) return CPUArchitecture::X64; @@ -153,7 +153,7 @@ namespace vcpkg::System memset(&process_info, 0, sizeof(PROCESS_INFORMATION)); // Basically we are wrapping it in quotes - std::string actual_cmd_line = Strings::format(R"###(cmd.exe /c "%s")###", cmd_line); + const std::string actual_cmd_line = Strings::format(R"###(cmd.exe /c "%s")###", cmd_line); Debug::println("CreateProcessW(%s)", actual_cmd_line); bool succeeded = TRUE == CreateProcessW(nullptr, Strings::to_utf16(actual_cmd_line).data(), @@ -331,35 +331,39 @@ namespace vcpkg::System } #if defined(_WIN32) - static bool is_string_keytype(DWORD hkey_type) + static bool is_string_keytype(const DWORD hkey_type) { return hkey_type == REG_SZ || hkey_type == REG_MULTI_SZ || hkey_type == REG_EXPAND_SZ; } - Optional get_registry_string(void* base_hkey, - const CWStringView sub_key, - const CWStringView valuename) + Optional get_registry_string(void* base_hkey, const CStringView sub_key, const CStringView valuename) { HKEY k = nullptr; - const LSTATUS ec = RegOpenKeyExW(reinterpret_cast(base_hkey), sub_key.c_str(), NULL, KEY_READ, &k); + const LSTATUS ec = + RegOpenKeyExW(reinterpret_cast(base_hkey), Strings::to_utf16(sub_key).c_str(), NULL, KEY_READ, &k); if (ec != ERROR_SUCCESS) return nullopt; DWORD dw_buffer_size = 0; DWORD dw_type = 0; - auto rc = RegQueryValueExW(k, valuename.c_str(), nullptr, &dw_type, nullptr, &dw_buffer_size); + auto rc = + RegQueryValueExW(k, Strings::to_utf16(valuename).c_str(), nullptr, &dw_type, nullptr, &dw_buffer_size); if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size == 0 || dw_buffer_size % sizeof(wchar_t) != 0) return nullopt; std::wstring ret; ret.resize(dw_buffer_size / sizeof(wchar_t)); - rc = RegQueryValueExW( - k, valuename.c_str(), nullptr, &dw_type, reinterpret_cast(ret.data()), &dw_buffer_size); + rc = RegQueryValueExW(k, + Strings::to_utf16(valuename).c_str(), + nullptr, + &dw_type, + reinterpret_cast(ret.data()), + &dw_buffer_size); if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size != sizeof(wchar_t) * ret.size()) return nullopt; ret.pop_back(); // remove extra trailing null byte - return ret; + return Strings::to_utf8(ret); } #else Optional get_registry_string(void* base_hkey, diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index fe6f76bd2..668ec9b1a 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -3,25 +3,24 @@ #include #include #include -#include #include namespace vcpkg::Commands::Edit { static std::vector find_from_registry() { - static const std::array REGKEYS = { - LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", - LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1)", - LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", + static const std::array REGKEYS = { + R"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", + R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1)", + R"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", }; std::vector output; #if defined(_WIN32) for (auto&& keypath : REGKEYS) { - const Optional code_installpath = - System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation"); + const Optional code_installpath = + System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, "InstallLocation"); if (const auto c = code_installpath.get()) { const fs::path install_path = fs::path(*c); diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 854baa0ca..c93d47d6e 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -233,14 +233,14 @@ namespace vcpkg::Metrics bool get_compiled_metrics_enabled() { return DISABLE_METRICS == 0; } - std::wstring get_SQM_user() + std::string get_SQM_user() { #if defined(_WIN32) auto hkcu_sqmclient = - System::get_registry_string(HKEY_CURRENT_USER, LR"(Software\Microsoft\SQMClient)", L"UserId"); - return hkcu_sqmclient.value_or(L"{}"); + System::get_registry_string(HKEY_CURRENT_USER, R"(Software\Microsoft\SQMClient)", "UserId"); + return hkcu_sqmclient.value_or("{}"); #else - return L"{}"; + return "{}"; #endif } -- cgit v1.2.3 From 70b458f5d97d5c189379b3d6b8913b27a2878661 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 16 Oct 2017 13:56:05 -0700 Subject: Remove Metrics::track_property(std::wstring) --- toolsrc/src/vcpkg/metrics.cpp | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index c93d47d6e..8f2575886 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -262,17 +262,6 @@ namespace vcpkg::Metrics void Metrics::track_metric(const std::string& name, double value) { g_metricmessage.track_metric(name, value); } - void Metrics::track_property(const std::string& name, const std::wstring& value) - { - // Note: this is not valid UTF-16 -> UTF-8, it just yields a close enough approximation for our purposes. - std::string converted_value; - converted_value.resize(value.size()); - std::transform( - value.begin(), value.end(), converted_value.begin(), [](wchar_t ch) { return static_cast(ch); }); - - g_metricmessage.track_property(name, converted_value); - } - void Metrics::track_property(const std::string& name, const std::string& value) { g_metricmessage.track_property(name, value); -- cgit v1.2.3 From fdc6b1ea1a59910df19962e0161b593c948abe98 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 16 Oct 2017 13:57:07 -0700 Subject: Remove wformat_internal() --- toolsrc/src/vcpkg/base/strings.cpp | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index 160aa98e9..af41eed9a 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -44,30 +44,6 @@ namespace vcpkg::Strings::details return output; } - - std::wstring wformat_internal(const wchar_t* fmtstr, ...) - { - va_list args; - va_start(args, fmtstr); - -#if defined(_WIN32) - const int sz = _vscwprintf_l(fmtstr, c_locale(), args); -#else - const int sz = vswprintf(nullptr, 0, fmtstr, args); -#endif - Checks::check_exit(VCPKG_LINE_INFO, sz > 0); - - std::wstring output(sz, L'\0'); - -#if defined(_WIN32) - _vsnwprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args); -#else - vswprintf(&output.at(0), output.size() + 1, fmtstr, args); -#endif - va_end(args); - - return output; - } } namespace vcpkg::Strings -- cgit v1.2.3 From dfe1f880d4e2a7f23d3b43d42a5d6ac2d68dc135 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 16 Oct 2017 14:22:20 -0700 Subject: [system.cpp] Remove usage of std::wstring. Convert at the last step --- toolsrc/src/vcpkg/base/system.cpp | 102 +++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 52 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 730b22c43..ac527f9fc 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -79,71 +79,71 @@ namespace vcpkg::System static const std::string NEW_PATH = Strings::format( R"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32); - std::vector env_wstrings = { - L"ALLUSERSPROFILE", - L"APPDATA", - L"CommonProgramFiles", - L"CommonProgramFiles(x86)", - L"CommonProgramW6432", - L"COMPUTERNAME", - L"ComSpec", - L"HOMEDRIVE", - L"HOMEPATH", - L"LOCALAPPDATA", - L"LOGONSERVER", - L"NUMBER_OF_PROCESSORS", - L"OS", - L"PATHEXT", - L"PROCESSOR_ARCHITECTURE", - L"PROCESSOR_ARCHITEW6432", - L"PROCESSOR_IDENTIFIER", - L"PROCESSOR_LEVEL", - L"PROCESSOR_REVISION", - L"ProgramData", - L"ProgramFiles", - L"ProgramFiles(x86)", - L"ProgramW6432", - L"PROMPT", - L"PSModulePath", - L"PUBLIC", - L"SystemDrive", - L"SystemRoot", - L"TEMP", - L"TMP", - L"USERDNSDOMAIN", - L"USERDOMAIN", - L"USERDOMAIN_ROAMINGPROFILE", - L"USERNAME", - L"USERPROFILE", - L"windir", + std::vector env_wstrings = { + "ALLUSERSPROFILE", + "APPDATA", + "CommonProgramFiles", + "CommonProgramFiles(x86)", + "CommonProgramW6432", + "COMPUTERNAME", + "ComSpec", + "HOMEDRIVE", + "HOMEPATH", + "LOCALAPPDATA", + "LOGONSERVER", + "NUMBER_OF_PROCESSORS", + "OS", + "PATHEXT", + "PROCESSOR_ARCHITECTURE", + "PROCESSOR_ARCHITEW6432", + "PROCESSOR_IDENTIFIER", + "PROCESSOR_LEVEL", + "PROCESSOR_REVISION", + "ProgramData", + "ProgramFiles", + "ProgramFiles(x86)", + "ProgramW6432", + "PROMPT", + "PSModulePath", + "PUBLIC", + "SystemDrive", + "SystemRoot", + "TEMP", + "TMP", + "USERDNSDOMAIN", + "USERDOMAIN", + "USERDOMAIN_ROAMINGPROFILE", + "USERNAME", + "USERPROFILE", + "windir", // Enables proxy information to be passed to Curl, the underlying download library in cmake.exe - L"HTTP_PROXY", - L"HTTPS_PROXY", + "HTTP_PROXY", + "HTTPS_PROXY", // Enables find_package(CUDA) in CMake - L"CUDA_PATH", + "CUDA_PATH", // Environmental variable generated automatically by CUDA after installation - L"NVCUDASAMPLES_ROOT", + "NVCUDASAMPLES_ROOT", }; // Flush stdout before launching external process fflush(nullptr); - std::wstring env_cstr; + std::string env_cstr; for (auto&& env_wstring : env_wstrings) { - const Optional value = System::get_environment_variable(Strings::to_utf8(env_wstring)); + const Optional value = System::get_environment_variable(env_wstring); const auto v = value.get(); if (!v || v->empty()) continue; env_cstr.append(env_wstring); - env_cstr.push_back(L'='); - env_cstr.append(Strings::to_utf16(*v)); - env_cstr.push_back(L'\0'); + env_cstr.push_back('='); + env_cstr.append(*v); + env_cstr.push_back('\0'); } - env_cstr.append(Strings::to_utf16(NEW_PATH)); - env_cstr.push_back(L'\0'); + env_cstr.append(NEW_PATH); + env_cstr.push_back('\0'); STARTUPINFOW startup_info; memset(&startup_info, 0, sizeof(STARTUPINFOW)); @@ -161,7 +161,7 @@ namespace vcpkg::System nullptr, FALSE, BELOW_NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, - env_cstr.data(), + Strings::to_utf16(env_cstr).data(), nullptr, &startup_info, &process_info); @@ -366,9 +366,7 @@ namespace vcpkg::System return Strings::to_utf8(ret); } #else - Optional get_registry_string(void* base_hkey, - const CWStringView sub_key, - const CWStringView valuename) + Optional get_registry_string(void* base_hkey, const CStringView sub_key, const CStringView valuename) { return nullopt; } -- cgit v1.2.3 From 558dcb32ca4ef43c35570794bf4cc4fc46f4af6c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 16 Oct 2017 15:09:02 -0700 Subject: Revert "[system.cpp] Remove usage of std::wstring. Convert at the last step" This reverts commit dfe1f880d4e2a7f23d3b43d42a5d6ac2d68dc135. --- toolsrc/src/vcpkg/base/system.cpp | 102 +++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 50 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index ac527f9fc..730b22c43 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -79,71 +79,71 @@ namespace vcpkg::System static const std::string NEW_PATH = Strings::format( R"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32); - std::vector env_wstrings = { - "ALLUSERSPROFILE", - "APPDATA", - "CommonProgramFiles", - "CommonProgramFiles(x86)", - "CommonProgramW6432", - "COMPUTERNAME", - "ComSpec", - "HOMEDRIVE", - "HOMEPATH", - "LOCALAPPDATA", - "LOGONSERVER", - "NUMBER_OF_PROCESSORS", - "OS", - "PATHEXT", - "PROCESSOR_ARCHITECTURE", - "PROCESSOR_ARCHITEW6432", - "PROCESSOR_IDENTIFIER", - "PROCESSOR_LEVEL", - "PROCESSOR_REVISION", - "ProgramData", - "ProgramFiles", - "ProgramFiles(x86)", - "ProgramW6432", - "PROMPT", - "PSModulePath", - "PUBLIC", - "SystemDrive", - "SystemRoot", - "TEMP", - "TMP", - "USERDNSDOMAIN", - "USERDOMAIN", - "USERDOMAIN_ROAMINGPROFILE", - "USERNAME", - "USERPROFILE", - "windir", + std::vector env_wstrings = { + L"ALLUSERSPROFILE", + L"APPDATA", + L"CommonProgramFiles", + L"CommonProgramFiles(x86)", + L"CommonProgramW6432", + L"COMPUTERNAME", + L"ComSpec", + L"HOMEDRIVE", + L"HOMEPATH", + L"LOCALAPPDATA", + L"LOGONSERVER", + L"NUMBER_OF_PROCESSORS", + L"OS", + L"PATHEXT", + L"PROCESSOR_ARCHITECTURE", + L"PROCESSOR_ARCHITEW6432", + L"PROCESSOR_IDENTIFIER", + L"PROCESSOR_LEVEL", + L"PROCESSOR_REVISION", + L"ProgramData", + L"ProgramFiles", + L"ProgramFiles(x86)", + L"ProgramW6432", + L"PROMPT", + L"PSModulePath", + L"PUBLIC", + L"SystemDrive", + L"SystemRoot", + L"TEMP", + L"TMP", + L"USERDNSDOMAIN", + L"USERDOMAIN", + L"USERDOMAIN_ROAMINGPROFILE", + L"USERNAME", + L"USERPROFILE", + L"windir", // Enables proxy information to be passed to Curl, the underlying download library in cmake.exe - "HTTP_PROXY", - "HTTPS_PROXY", + L"HTTP_PROXY", + L"HTTPS_PROXY", // Enables find_package(CUDA) in CMake - "CUDA_PATH", + L"CUDA_PATH", // Environmental variable generated automatically by CUDA after installation - "NVCUDASAMPLES_ROOT", + L"NVCUDASAMPLES_ROOT", }; // Flush stdout before launching external process fflush(nullptr); - std::string env_cstr; + std::wstring env_cstr; for (auto&& env_wstring : env_wstrings) { - const Optional value = System::get_environment_variable(env_wstring); + const Optional value = System::get_environment_variable(Strings::to_utf8(env_wstring)); const auto v = value.get(); if (!v || v->empty()) continue; env_cstr.append(env_wstring); - env_cstr.push_back('='); - env_cstr.append(*v); - env_cstr.push_back('\0'); + env_cstr.push_back(L'='); + env_cstr.append(Strings::to_utf16(*v)); + env_cstr.push_back(L'\0'); } - env_cstr.append(NEW_PATH); - env_cstr.push_back('\0'); + env_cstr.append(Strings::to_utf16(NEW_PATH)); + env_cstr.push_back(L'\0'); STARTUPINFOW startup_info; memset(&startup_info, 0, sizeof(STARTUPINFOW)); @@ -161,7 +161,7 @@ namespace vcpkg::System nullptr, FALSE, BELOW_NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, - Strings::to_utf16(env_cstr).data(), + env_cstr.data(), nullptr, &startup_info, &process_info); @@ -366,7 +366,9 @@ namespace vcpkg::System return Strings::to_utf8(ret); } #else - Optional get_registry_string(void* base_hkey, const CStringView sub_key, const CStringView valuename) + Optional get_registry_string(void* base_hkey, + const CWStringView sub_key, + const CWStringView valuename) { return nullopt; } -- cgit v1.2.3 From e5867d1d63606cef5c53a764e31ce05385f36497 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 16 Oct 2017 15:26:28 -0700 Subject: CWStringView->CStringView, std::wstring->std::string --- toolsrc/src/vcpkg/base/system.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 730b22c43..b04f79414 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -366,9 +366,7 @@ namespace vcpkg::System return Strings::to_utf8(ret); } #else - Optional get_registry_string(void* base_hkey, - const CWStringView sub_key, - const CWStringView valuename) + Optional get_registry_string(void* base_hkey, const CStringView sub_key, const CStringView valuename) { return nullopt; } -- cgit v1.2.3 From fb1f5f87fb0cbb666882586271581d57c5e0ef76 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 16 Oct 2017 15:37:14 -0700 Subject: Add timer to `vcpkg build` --- toolsrc/src/vcpkg/build.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 3d3bcb5fe..cf16c8f9c 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -69,7 +69,10 @@ namespace vcpkg::Build::Command const Build::BuildPackageConfig build_config{ *scf->core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options}; + const auto build_timer = Chrono::ElapsedTime::create_started(); const auto result = Build::build_package(paths, build_config, status_db); + System::println("Elapsed time for package %s: %s", spec.to_string(), build_timer.to_string()); + if (result.code == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES) { System::println(System::Color::error, -- cgit v1.2.3 From 7ed8d4f75e903fdad4c02b4e784f2f4bcb30a3b0 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 16 Oct 2017 17:24:17 -0700 Subject: Don't warn for outdated vcpkg if command is autocomplete --- toolsrc/src/vcpkg.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index e1e2240e7..b4c2d0fe2 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -106,7 +106,11 @@ static void inner(const VcpkgCmdArguments& args) const int exit_code = chdir(paths.root.c_str()); #endif Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed"); - Commands::Version::warn_if_vcpkg_version_mismatch(paths); + + if (args.command != "autocomplete") + { + Commands::Version::warn_if_vcpkg_version_mismatch(paths); + } if (const auto command_function = find_command(Commands::get_available_commands_type_b())) { -- cgit v1.2.3 From 947c6cac332cabb58452178d563a2a0c26def35e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 17 Oct 2017 02:30:27 -0700 Subject: `autocomplete` Consider private commands if no public commands match --- toolsrc/src/vcpkg/commands.autocomplete.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp index addb9edaf..fcbe73835 100644 --- a/toolsrc/src/vcpkg/commands.autocomplete.cpp +++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp @@ -39,7 +39,8 @@ namespace vcpkg::Commands::Autocomplete { const std::string requested_command = match[1].str(); - std::vector valid_commands = { + // First try public commands + std::vector public_commands = { "install", "search", "remove", @@ -57,11 +58,31 @@ namespace vcpkg::Commands::Autocomplete "contact", }; - Util::unstable_keep_if(valid_commands, [&](const std::string& s) { + Util::unstable_keep_if(public_commands, [&](const std::string& s) { return Strings::case_insensitive_ascii_starts_with(s, requested_command); }); - output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(valid_commands)); + if (!public_commands.empty()) + { + output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(public_commands)); + } + + // If no public commands match, try private commands + std::vector private_commands = { + "build", + "buildexternal", + "ci", + "depend-info", + "env", + "import", + "portsdiff", + }; + + Util::unstable_keep_if(private_commands, [&](const std::string& s) { + return Strings::case_insensitive_ascii_starts_with(s, requested_command); + }); + + output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(private_commands)); } // Handles vcpkg install package: -- cgit v1.2.3 From 3c4f620dbc7ef0005c694ab758c6c7d5e42dbe93 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 17 Oct 2017 02:59:55 -0700 Subject: `autocomplete` Add autocompletion for `vcpkg integrate` --- toolsrc/src/vcpkg/commands.autocomplete.cpp | 1 + toolsrc/src/vcpkg/commands.integrate.cpp | 33 ++++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp index fcbe73835..e36bf8430 100644 --- a/toolsrc/src/vcpkg/commands.autocomplete.cpp +++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp @@ -124,6 +124,7 @@ namespace vcpkg::Commands::Autocomplete CommandEntry{"install", R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE}, CommandEntry{"edit", R"###(^edit\s(.*\s|)(\S*)$)###", Edit::COMMAND_STRUCTURE}, CommandEntry{"remove", R"###(^remove\s(.*\s|)(\S*)$)###", Remove::COMMAND_STRUCTURE}, + CommandEntry{"integrate", R"###(^integrate(\s+)(\S*)$)###", Integrate::COMMAND_STRUCTURE}, }; for (auto&& command : COMMANDS) diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 0d185476e..c8fa275ab 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -326,6 +326,33 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console " vcpkg integrate remove Remove user-wide integration\n" " vcpkg integrate project Generate a referencing nuget package for individual VS project use\n"; + namespace Subcommand + { + static const std::string INSTALL = "install"; + static const std::string REMOVE = "remove"; + static const std::string PROJECT = "project"; + } + + static const std::array INSTALL_SWITCHES; + + static const std::array INSTALL_SETTINGS; + + static std::vector valid_arguments(const VcpkgPaths&) + { + return {Subcommand::INSTALL, Subcommand::REMOVE, Subcommand::PROJECT}; + } + + const CommandStructure COMMAND_STRUCTURE = { + Strings::format("Commands:\n" + "%s", + INTEGRATE_COMMAND_HELPSTRING), + 1, + 1, + INSTALL_SWITCHES, + INSTALL_SETTINGS, + &valid_arguments, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { static const std::string EXAMPLE = Strings::format("Commands:\n" @@ -335,15 +362,15 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console args.check_and_get_optional_command_arguments({}); #if defined(_WIN32) - if (args.command_arguments[0] == "install") + if (args.command_arguments[0] == Subcommand::INSTALL) { return integrate_install(paths); } - if (args.command_arguments[0] == "remove") + if (args.command_arguments[0] == Subcommand::REMOVE) { return integrate_remove(paths.get_filesystem()); } - if (args.command_arguments[0] == "project") + if (args.command_arguments[0] == Subcommand::PROJECT) { return integrate_project(paths); } -- cgit v1.2.3 From a536a4630261684370cd1b43b88e8121fe50f9ad Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 17 Oct 2017 03:07:39 -0700 Subject: `remove`: Consistency renames --- toolsrc/src/vcpkg/remove.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 2ec32855a..6f555b9b8 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -169,14 +169,14 @@ namespace vcpkg::Remove static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_OUTDATED = "--outdated"; - static const std::array REMOVE_SWITCHES = { + static const std::array SWITCHES = { OPTION_PURGE, OPTION_NO_PURGE, OPTION_RECURSE, OPTION_DRY_RUN, OPTION_OUTDATED, }; - static const std::array REMOVE_SETTINGS; + static const std::array SETTINGS; static std::vector valid_arguments(const VcpkgPaths& paths) { @@ -190,8 +190,8 @@ namespace vcpkg::Remove "remove zlib zlib:x64-windows curl boost", 1, SIZE_MAX, - REMOVE_SWITCHES, - REMOVE_SETTINGS, + SWITCHES, + SETTINGS, &valid_arguments, }; -- cgit v1.2.3 From 87296823ac9cc939c233caf7c02585b5fe6d3df7 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 17 Oct 2017 12:41:34 -0700 Subject: [cmake] Update to 3.9.4 (was 3.9.3) --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 90f9cb00b..486fff40e 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -105,10 +105,10 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array EXPECTED_VERSION = {3, 9, 3}; + static constexpr std::array EXPECTED_VERSION = {3, 9, 4}; static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - const fs::path downloaded_copy = downloads_folder / "cmake-3.9.3-win32-x86" / "bin" / "cmake.exe"; + const fs::path downloaded_copy = downloads_folder / "cmake-3.9.4-win32-x86" / "bin" / "cmake.exe"; const std::vector from_path = Files::find_from_PATH("cmake"); std::vector candidate_paths; -- cgit v1.2.3 From fa4e54a37356ad0200ce6387541ef78997b8a87e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 17 Oct 2017 14:05:55 -0700 Subject: [git] Update to 2.14.2.3 (was 2.14.1) --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 486fff40e..8da718e87 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -151,10 +151,10 @@ namespace vcpkg fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array EXPECTED_VERSION = {2, 14, 1}; + static constexpr std::array EXPECTED_VERSION = {2, 14, 2}; static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.1-32-bit" / "cmd" / "git.exe"; + const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.2.3-32-bit" / "cmd" / "git.exe"; const std::vector from_path = Files::find_from_PATH("git"); std::vector candidate_paths; -- cgit v1.2.3 From e9ba8b0ecbe5c49cda2710acaae0983dfe2552f9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 17 Oct 2017 14:19:48 -0700 Subject: [nuget] Update to 4.4.0 (was 4.3.0) --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 8da718e87..34c661afd 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -131,9 +131,9 @@ namespace vcpkg fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array EXPECTED_VERSION = {4, 3, 0}; + static constexpr std::array EXPECTED_VERSION = {4, 4, 0}; - const fs::path downloaded_copy = downloads_folder / "nuget-4.3.0" / "nuget.exe"; + const fs::path downloaded_copy = downloads_folder / "nuget-4.4.0" / "nuget.exe"; const std::vector from_path = Files::find_from_PATH("nuget"); std::vector candidate_paths; -- cgit v1.2.3 From ae3fe7cd16c82b794d5074104cf078afc1a12c7d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 17 Oct 2017 14:42:05 -0700 Subject: [boost] Add feature packages for regex-icu, locale-icu, and python --- toolsrc/src/vcpkg/install.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index adbd8c943..70757ff38 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -591,11 +591,12 @@ namespace vcpkg::Install const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), Build::to_allow_downloads(!no_downloads)}; + // Note: action_plan will hold raw pointers to SourceControlFiles from this map + std::unordered_map scf_map; std::vector action_plan; if (GlobalState::feature_packages) { - std::unordered_map scf_map; auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); for (auto&& port : all_ports) { -- cgit v1.2.3 From 7a4023f1dcb3686d7d8deaf9e40cc0283e508b08 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 18 Oct 2017 14:47:04 -0700 Subject: [autocomplete] Don't try to autocomplete triplets to --options --- toolsrc/src/vcpkg/commands.autocomplete.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp index e36bf8430..410bfcd0d 100644 --- a/toolsrc/src/vcpkg/commands.autocomplete.cpp +++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp @@ -134,7 +134,8 @@ namespace vcpkg::Commands::Autocomplete const auto prefix = match[2].str(); std::vector results; - if (Strings::case_insensitive_ascii_starts_with(prefix, "-")) + const bool is_option = Strings::case_insensitive_ascii_starts_with(prefix, "-"); + if (is_option) { results = Util::fmap(command.structure.switches, [](auto&& s) -> std::string { return s; }); } @@ -147,7 +148,7 @@ namespace vcpkg::Commands::Autocomplete return Strings::case_insensitive_ascii_starts_with(s, prefix); }); - if (command.name == "install" && results.size() == 1) + if (command.name == "install" && results.size() == 1 && !is_option) { const auto port_at_each_triplet = combine_port_with_triplets(results[0], paths.get_available_triplets()); -- cgit v1.2.3 From ecdfd3c8e3a4b924bfad5b70f6557dd9f337bd1c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 18 Oct 2017 19:04:14 -0700 Subject: ci now accepts multiple triplets. Refactoring to accomodate --- toolsrc/src/vcpkg/commands.ci.cpp | 49 +++++++++++++++++---- toolsrc/src/vcpkg/install.cpp | 93 +++++++++++++++++++++------------------ 2 files changed, 90 insertions(+), 52 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 1c98d1d83..ffeaad790 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -30,15 +30,10 @@ namespace vcpkg::Commands::CI }); } - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + static Install::InstallSummary run_ci_on_triplet(const Triplet& triplet, const VcpkgPaths& paths) { - static const std::string EXAMPLE = Help::create_example_string("ci x64-windows"); - args.check_max_arg_count(1, EXAMPLE); - const Triplet triplet = args.command_arguments.size() == 1 - ? Triplet::from_canonical_name(args.command_arguments.at(0)) - : default_triplet; Input::check_triplet(triplet, paths); - args.check_and_get_optional_command_arguments({}); + const std::vector specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet); StatusParagraphs status_db = database_load_check(paths); @@ -54,8 +49,44 @@ namespace vcpkg::Commands::CI return Dependencies::AnyAction(std::move(install_action)); }); - Install::perform_and_exit_ex( - action_plan, install_plan_options, Install::KeepGoing::YES, Install::PrintSummary::YES, paths, status_db); + return Install::perform(action_plan, install_plan_options, Install::KeepGoing::YES, paths, status_db); + } + + struct TripletAndSummary + { + Triplet triplet; + Install::InstallSummary summary; + }; + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + static const std::string EXAMPLE = Help::create_example_string("ci x64-windows"); + args.check_and_get_optional_command_arguments({}); + + std::vector triplets; + for (const std::string& triplet : args.command_arguments) + { + triplets.push_back(Triplet::from_canonical_name(triplet)); + } + + if (triplets.empty()) + { + triplets.push_back(default_triplet); + } + + std::vector results; + for (const Triplet& triplet : triplets) + { + Install::InstallSummary summary = run_ci_on_triplet(triplet, paths); + results.push_back({triplet, std::move(summary)}); + } + + for (auto&& result : results) + { + System::println("\nTriplet: %s", result.triplet); + System::println("Total elapsed time: %s", result.summary.total_elapsed_time); + result.summary.print(); + } Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 70757ff38..bd924fcba 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -444,15 +444,41 @@ namespace vcpkg::Install } } - void perform_and_exit_ex(const std::vector& action_plan, - const Build::BuildPackageOptions& install_plan_options, - const KeepGoing keep_going, - const PrintSummary print_summary, - const VcpkgPaths& paths, - StatusParagraphs& status_db) + void InstallSummary::print() const { - std::vector results; - std::vector timing; + System::println("RESULTS"); + + for (const SpecSummary& result : this->results) + { + System::println(" %s: %s: %s", result.spec, Build::to_string(result.result), result.timing); + } + + std::map summary; + for (const BuildResult& v : Build::BUILD_RESULT_VALUES) + { + summary[v] = 0; + } + + for (const SpecSummary& r : this->results) + { + summary[r.result]++; + } + + System::println("\nSUMMARY"); + for (const std::pair& entry : summary) + { + System::println(" %s: %d", Build::to_string(entry.first), entry.second); + } + } + + InstallSummary perform(const std::vector& action_plan, + const Build::BuildPackageOptions& install_plan_options, + const KeepGoing keep_going, + const VcpkgPaths& paths, + StatusParagraphs& status_db) + { + std::vector results; + const auto timer = Chrono::ElapsedTime::create_started(); size_t counter = 0; const size_t package_count = action_plan.size(); @@ -462,11 +488,11 @@ namespace vcpkg::Install const auto build_timer = Chrono::ElapsedTime::create_started(); counter++; - const std::string display_name = action.spec().to_string(); + const PackageSpec& spec = action.spec(); + const std::string display_name = spec.to_string(); System::println("Starting package %d/%d: %s", counter, package_count, display_name); - timing.push_back("0"); - results.push_back(BuildResult::NULLVALUE); + results.push_back(SpecSummary{spec}); if (const auto install_action = action.install_plan.get()) { @@ -478,7 +504,7 @@ namespace vcpkg::Install Checks::exit_fail(VCPKG_LINE_INFO); } - results.back() = result; + results.back().result = result; } else if (const auto remove_action = action.remove_plan.get()) { @@ -490,38 +516,11 @@ namespace vcpkg::Install Checks::unreachable(VCPKG_LINE_INFO); } - timing.back() = build_timer.to_string(); + results.back().timing = build_timer.to_string(); System::println("Elapsed time for package %s: %s", display_name, build_timer.to_string()); } - System::println("Total time taken: %s", timer.to_string()); - - if (print_summary == PrintSummary::YES) - { - for (size_t i = 0; i < results.size(); i++) - { - System::println("%s: %s: %s", action_plan[i].spec(), Build::to_string(results[i]), timing[i]); - } - - std::map summary; - for (const BuildResult& v : Build::BUILD_RESULT_VALUES) - { - summary[v] = 0; - } - - for (const BuildResult& r : results) - { - summary[r]++; - } - - System::println("\n\nSUMMARY"); - for (const std::pair& entry : summary) - { - System::println(" %s: %d", Build::to_string(entry.first), entry.second); - } - } - - Checks::exit_success(VCPKG_LINE_INFO); + return InstallSummary{results, timer.to_string()}; } static const std::string OPTION_DRY_RUN = "--dry-run"; @@ -583,7 +582,6 @@ namespace vcpkg::Install const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); const KeepGoing keep_going = to_keep_going(options.find(OPTION_KEEP_GOING) != options.cend()); - const PrintSummary print_summary = to_print_summary(keep_going == KeepGoing::YES); // create the plan StatusParagraphs status_db = database_load_check(paths); @@ -635,8 +633,17 @@ namespace vcpkg::Install Checks::exit_success(VCPKG_LINE_INFO); } - perform_and_exit_ex(action_plan, install_plan_options, keep_going, print_summary, paths, status_db); + const InstallSummary summary = perform(action_plan, install_plan_options, keep_going, paths, status_db); + + System::println("\nTotal elapsed time: %s", summary.total_elapsed_time); + + if (keep_going == KeepGoing::YES) + { + summary.print(); + } Checks::exit_success(VCPKG_LINE_INFO); } + + SpecSummary::SpecSummary(const PackageSpec& spec) : spec(spec), result(BuildResult::NULLVALUE), timing("0") {} } -- cgit v1.2.3 From 9964d84b53442ef4f555cfe090ed22503b90d213 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 18 Oct 2017 19:20:11 -0700 Subject: Add extra checks on the return Visual Studio instances --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 34c661afd..2f2dd877e 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -330,10 +330,19 @@ namespace vcpkg VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect Visual Studio instances"); const std::vector instances_as_strings = Strings::split(ec_data.output, "\n"); + Checks::check_exit( + VCPKG_LINE_INFO, !instances_as_strings.empty(), "Could not detect any Visual Studio instances"); + std::vector output; for (const std::string& instance_as_string : instances_as_strings) { const std::vector split = Strings::split(instance_as_string, "::"); + Checks::check_exit(VCPKG_LINE_INFO, + split.size() == 4, + "Invalid Visual Studio instance format.\n" + "Expected: PreferenceWeight::ReleaseType::Version::PathToVisualStudio\n" + "Actual : %s", + instance_as_string); output.push_back({split.at(3), split.at(2), split.at(1), split.at(0)}); } -- cgit v1.2.3 From b1d5d8e8baf4bd5132de4415a0168432600ce998 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 19 Oct 2017 19:38:23 -0700 Subject: Introduce Strings::replace_all() --- toolsrc/src/vcpkg/base/strings.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index af41eed9a..36efc3adc 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -114,6 +114,17 @@ namespace vcpkg::Strings #endif } + std::string replace_all(std::string&& s, const std::string& search, const std::string& rep) + { + size_t pos = 0; + while ((pos = s.find(search, pos)) != std::string::npos) + { + s.replace(pos, search.size(), rep); + pos += rep.size(); + } + return std::move(s); + } + void trim(std::string* s) { s->erase(std::find_if_not(s->rbegin(), s->rend(), details::isspace).base(), s->end()); -- cgit v1.2.3 From 8cefb25bcb7edaedd20d8aa170b2e1b945fd1762 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 19 Oct 2017 19:48:46 -0700 Subject: Use Strings::replace_all() instead of std::regex_replace() --- toolsrc/src/vcpkg/commands.integrate.cpp | 8 ++++---- toolsrc/src/vcpkg/export.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index c8fa275ab..27e563cfa 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -93,9 +93,9 @@ namespace vcpkg::Commands::Integrate )"; - std::string content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id); - content = std::regex_replace(content, std::regex("@VCPKG_DIR@"), vcpkg_root_dir.string()); - content = std::regex_replace(content, std::regex("@VERSION@"), nupkg_version); + std::string content = Strings::replace_all(CONTENT_TEMPLATE, "@NUGET_ID@", nuget_id); + content = Strings::replace_all(std::move(content), "@VCPKG_DIR@", vcpkg_root_dir.string()); + content = Strings::replace_all(std::move(content), "@VERSION@", nupkg_version); return content; } @@ -308,7 +308,7 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")", System::println(System::Color::success, "Created nupkg: %s", nuget_package.string()); auto source_path = buildsystems_dir.u8string(); - source_path = std::regex_replace(source_path, std::regex("`"), "``"); + source_path = Strings::replace_all(std::move(source_path), "`", "``"); System::println(R"( With a project open, go to Tools->NuGet Package Manager->Package Manager Console and paste: diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 5e27d4126..f0a3b23d0 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -44,12 +44,12 @@ namespace vcpkg::Export )"; - std::string nuspec_file_content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id); - nuspec_file_content = std::regex_replace(nuspec_file_content, std::regex("@VERSION@"), nupkg_version); + std::string nuspec_file_content = Strings::replace_all(CONTENT_TEMPLATE, "@NUGET_ID@", nuget_id); + nuspec_file_content = Strings::replace_all(std::move(nuspec_file_content), "@VERSION@", nupkg_version); nuspec_file_content = - std::regex_replace(nuspec_file_content, std::regex("@RAW_EXPORTED_DIR@"), raw_exported_dir); + Strings::replace_all(std::move(nuspec_file_content), "@RAW_EXPORTED_DIR@", raw_exported_dir); nuspec_file_content = - std::regex_replace(nuspec_file_content, std::regex("@TARGETS_REDIRECT_PATH@"), targets_redirect_path); + Strings::replace_all(std::move(nuspec_file_content), "@TARGETS_REDIRECT_PATH@", targets_redirect_path); return nuspec_file_content; } -- cgit v1.2.3 From 50ae9eec872a0802d2450b4ae2d640475d0d7889 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 19 Oct 2017 19:50:23 -0700 Subject: Do not depend on newlines when getting output from powershell --- toolsrc/src/vcpkg/base/system.cpp | 16 ++++++++++++++-- toolsrc/src/vcpkg/vcpkgpaths.cpp | 14 ++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index b04f79414..a1bc9daf6 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -269,11 +269,23 @@ namespace vcpkg::System #endif } - std::string create_powershell_script_cmd(const fs::path& script_path, const CStringView args) + ExitCodeAndOutput powershell_execute_and_capture_output(const fs::path& script_path, const CStringView args) { // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned - return Strings::format( + const std::string cmd = Strings::format( R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args); + + auto rc = System::cmd_execute_and_capture_output(cmd); + + // Remove newline from all output. + // Powershell returns newlines when it hits the column count of the console. + // For example, this is 80 in cmd on Windows 7. If the expected output is longer than 80 lines, we get + // newlines in-between the data. + // To solve this, we design our interaction with powershell to not depend on newlines, + // and then strip all newlines here. + rc.output = Strings::replace_all(std::move(rc.output), "\n", ""); + + return rc; } void println() { putchar('\n'); } diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 2f2dd877e..ef9e383bc 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -74,9 +74,8 @@ namespace vcpkg tool_name, version_as_string); const fs::path script = scripts_folder / "fetchDependency.ps1"; - const auto install_cmd = - System::create_powershell_script_cmd(script, Strings::format("-Dependency %s", tool_name)); - const System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd); + const System::ExitCodeAndOutput rc = + System::powershell_execute_and_capture_output(script, Strings::format("-Dependency %s", tool_name)); if (rc.exit_code) { System::println(System::Color::error, @@ -324,14 +323,13 @@ namespace vcpkg static std::vector get_visual_studio_instances(const VcpkgPaths& paths) { const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; - const std::string cmd = System::create_powershell_script_cmd(script); - const System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); + const System::ExitCodeAndOutput ec_data = System::powershell_execute_and_capture_output(script); Checks::check_exit( VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect Visual Studio instances"); - const std::vector instances_as_strings = Strings::split(ec_data.output, "\n"); + const std::vector instances_as_strings = Strings::split(ec_data.output, "::"); Checks::check_exit( - VCPKG_LINE_INFO, !instances_as_strings.empty(), "Could not detect any Visual Studio instances"); + VCPKG_LINE_INFO, !instances_as_strings.empty(), "Could not detect any Visual Studio instances.\n"); std::vector output; for (const std::string& instance_as_string : instances_as_strings) @@ -341,7 +339,7 @@ namespace vcpkg split.size() == 4, "Invalid Visual Studio instance format.\n" "Expected: PreferenceWeight::ReleaseType::Version::PathToVisualStudio\n" - "Actual : %s", + "Actual : %s\n", instance_as_string); output.push_back({split.at(3), split.at(2), split.at(1), split.at(0)}); } -- cgit v1.2.3 From 23702360ce912b1827afe5559de936cc9a24cd0c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 20 Oct 2017 16:43:44 -0700 Subject: Merge trim() and trimmed() functions --- toolsrc/src/vcpkg/base/strings.cpp | 16 +++++----------- toolsrc/src/vcpkg/vcpkgpaths.cpp | 2 +- 2 files changed, 6 insertions(+), 12 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index 36efc3adc..27cfcbe71 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -125,24 +125,18 @@ namespace vcpkg::Strings return std::move(s); } - void trim(std::string* s) + std::string trim(std::string&& s) { - s->erase(std::find_if_not(s->rbegin(), s->rend(), details::isspace).base(), s->end()); - s->erase(s->begin(), std::find_if_not(s->begin(), s->end(), details::isspace)); - } - - std::string trimmed(const std::string& s) - { - auto whitespace_back = std::find_if_not(s.rbegin(), s.rend(), details::isspace).base(); - auto whitespace_front = std::find_if_not(s.begin(), whitespace_back, details::isspace); - return std::string(whitespace_front, whitespace_back); + s.erase(std::find_if_not(s.rbegin(), s.rend(), details::isspace).base(), s.end()); + s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), details::isspace)); + return std::move(s); } void trim_all_and_remove_whitespace_strings(std::vector* strings) { for (std::string& s : *strings) { - trim(&s); + s = trim(std::move(s)); } Util::erase_remove_if(*strings, [](const std::string& s) { return s.empty(); }); diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index ef9e383bc..363319767 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -91,7 +91,7 @@ namespace vcpkg Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); } - const fs::path actual_downloaded_path = Strings::trimmed(rc.output); + const fs::path actual_downloaded_path = Strings::trim(std::string{rc.output}); std::error_code ec; const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); Checks::check_exit(VCPKG_LINE_INFO, -- cgit v1.2.3 From 2c9536ce4fe0ac755e188617ce61076b26646100 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 26 Oct 2017 19:00:30 -0700 Subject: [vcpkg ci] Introduce --exclude option --- toolsrc/src/tests.installplan.cpp | 7 ++++--- toolsrc/src/vcpkg/build.cpp | 6 +++++- toolsrc/src/vcpkg/commands.ci.cpp | 39 +++++++++++++++++++++----------------- toolsrc/src/vcpkg/dependencies.cpp | 22 ++++++++------------- toolsrc/src/vcpkg/install.cpp | 21 ++++++++++++++++++-- toolsrc/src/vcpkg/packagespec.cpp | 8 ++++++++ 6 files changed, 66 insertions(+), 37 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.installplan.cpp b/toolsrc/src/tests.installplan.cpp index 120009db5..347612abd 100644 --- a/toolsrc/src/tests.installplan.cpp +++ b/toolsrc/src/tests.installplan.cpp @@ -17,8 +17,9 @@ namespace Microsoft::VisualStudio::CppUnitTestFramework case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; case Dependencies::InstallPlanType::INSTALL: return L"INSTALL"; + case Dependencies::InstallPlanType::EXCLUDED: return L"EXCLUDED"; case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; - default: return ToString((int)t); + default: return ToString(static_cast(t)); } } @@ -30,7 +31,7 @@ namespace Microsoft::VisualStudio::CppUnitTestFramework case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED"; case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED"; case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN"; - default: return ToString((int)t); + default: return ToString(static_cast(t)); } } } @@ -484,4 +485,4 @@ namespace UnitTest1 features_check(&install_plan[7], "c", {"core"}); } }; -} \ No newline at end of file +} diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index cf16c8f9c..c26dcc591 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -87,6 +87,8 @@ namespace vcpkg::Build::Command Checks::exit_fail(VCPKG_LINE_INFO); } + Checks::check_exit(VCPKG_LINE_INFO, result.code != BuildResult::EXCLUDED); + if (result.code != BuildResult::SUCCEEDED) { System::println(System::Color::error, Build::create_error_message(result.code, spec)); @@ -365,6 +367,7 @@ namespace vcpkg::Build static const std::string FILE_CONFLICTS_STRING = "FILE_CONFLICTS"; static const std::string POST_BUILD_CHECKS_FAILED_STRING = "POST_BUILD_CHECKS_FAILED"; static const std::string CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING = "CASCADED_DUE_TO_MISSING_DEPENDENCIES"; + static const std::string EXCLUDED_STRING = "EXCLUDED"; switch (build_result) { @@ -372,8 +375,9 @@ namespace vcpkg::Build case BuildResult::SUCCEEDED: return SUCCEEDED_STRING; case BuildResult::BUILD_FAILED: return BUILD_FAILED_STRING; case BuildResult::POST_BUILD_CHECKS_FAILED: return POST_BUILD_CHECKS_FAILED_STRING; - case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: return CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING; case BuildResult::FILE_CONFLICTS: return FILE_CONFLICTS_STRING; + case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: return CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING; + case BuildResult::EXCLUDED: return EXCLUDED_STRING; default: Checks::unreachable(VCPKG_LINE_INFO); } } diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index ffeaad790..559dc4541 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -1,6 +1,5 @@ #include "pch.h" -#include #include #include #include @@ -10,7 +9,6 @@ #include #include #include -#include #include namespace vcpkg::Commands::CI @@ -19,27 +17,28 @@ namespace vcpkg::Commands::CI using Dependencies::InstallPlanAction; using Dependencies::InstallPlanType; - static std::vector load_all_package_specs(Files::Filesystem& fs, - const fs::path& ports_directory, - const Triplet& triplet) - { - auto ports = Paragraphs::load_all_ports(fs, ports_directory); - return Util::fmap(ports, [&](auto&& control_file) -> PackageSpec { - return PackageSpec::from_name_and_triplet(control_file->core_paragraph->name, triplet) - .value_or_exit(VCPKG_LINE_INFO); - }); - } - - static Install::InstallSummary run_ci_on_triplet(const Triplet& triplet, const VcpkgPaths& paths) + static Install::InstallSummary run_ci_on_triplet(const Triplet& triplet, + const VcpkgPaths& paths, + const std::vector& ports, + const std::set& exclusions_set) { Input::check_triplet(triplet, paths); - const std::vector specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet); + const std::vector specs = PackageSpec::to_package_specs(ports, triplet); StatusParagraphs status_db = database_load_check(paths); const auto& paths_port_file = Dependencies::PathsPortFile(paths); std::vector install_plan = Dependencies::create_install_plan(paths_port_file, specs, status_db); + + for (InstallPlanAction& plan : install_plan) + { + if (Util::Sets::contains(exclusions_set, plan.spec.name())) + { + plan.plan_type = InstallPlanType::EXCLUDED; + } + } + Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; @@ -60,8 +59,13 @@ namespace vcpkg::Commands::CI void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { + static const std::string OPTION_EXCLUDE = "--exclude"; + static const std::string EXAMPLE = Help::create_example_string("ci x64-windows"); - args.check_and_get_optional_command_arguments({}); + + const ParsedArguments options = args.check_and_get_optional_command_arguments({}, {OPTION_EXCLUDE}); + const std::vector exclusions = Strings::split(options.settings.at(OPTION_EXCLUDE), ","); + const std::set exclusions_set(exclusions.cbegin(), exclusions.cend()); std::vector triplets; for (const std::string& triplet : args.command_arguments) @@ -74,10 +78,11 @@ namespace vcpkg::Commands::CI triplets.push_back(default_triplet); } + const std::vector ports = Install::get_all_port_names(paths); std::vector results; for (const Triplet& triplet : triplets) { - Install::InstallSummary summary = run_ci_on_triplet(triplet, paths); + Install::InstallSummary summary = run_ci_on_triplet(triplet, paths, ports, exclusions_set); results.push_back({triplet, std::move(summary)}); } diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 02b2ec785..9d264baa2 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -112,27 +112,21 @@ namespace vcpkg::Dependencies std::vector AnyParagraph::dependencies(const Triplet& triplet) const { - auto to_package_specs = [&](const std::vector& dependencies_as_string) { - return Util::fmap(dependencies_as_string, [&](const std::string s) { - return PackageSpec::from_name_and_triplet(s, triplet).value_or_exit(VCPKG_LINE_INFO); - }); - }; - - if (auto p = this->status_paragraph.get()) + if (const auto p = this->status_paragraph.get()) { - return to_package_specs(p->package.depends); + return PackageSpec::to_package_specs(p->package.depends, triplet); } - if (auto p = this->binary_control_file.get()) + if (const auto p = this->binary_control_file.get()) { auto deps = Util::fmap_flatten(p->features, [](const BinaryParagraph& pgh) { return pgh.depends; }); - deps.insert(deps.end(), p->core_paragraph.depends.begin(), p->core_paragraph.depends.end()); - return to_package_specs(deps); + deps.insert(deps.end(), p->core_paragraph.depends.cbegin(), p->core_paragraph.depends.cend()); + return PackageSpec::to_package_specs(deps, triplet); } - if (auto p = this->source_paragraph.get()) + if (const auto p = this->source_paragraph.get()) { - return to_package_specs(filter_dependencies(p->depends, triplet)); + return PackageSpec::to_package_specs(filter_dependencies(p->depends, triplet), triplet); } Checks::exit_with_message(VCPKG_LINE_INFO, @@ -163,7 +157,7 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const std::unordered_set& features, const RequestType& request_type) - : spec(spec), plan_type(InstallPlanType::ALREADY_INSTALLED), request_type(request_type), feature_list(features) + : spec(spec), plan_type(InstallPlanType::UNKNOWN), request_type(request_type), feature_list(features) { } diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index bd924fcba..76e943e8c 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -342,6 +342,12 @@ namespace vcpkg::Install } } + if (plan_type == InstallPlanType::EXCLUDED) + { + System::println(System::Color::warning, "Package %s is excluded", display_name); + return BuildResult::EXCLUDED; + } + Checks::unreachable(VCPKG_LINE_INFO); } @@ -352,6 +358,7 @@ namespace vcpkg::Install std::vector only_install_plans; std::vector new_plans; std::vector already_installed_plans; + std::vector excluded; const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { if (auto iplan = package.install_plan.get()) @@ -382,6 +389,7 @@ namespace vcpkg::Install already_installed_plans.emplace_back(install_action); break; case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break; + case InstallPlanType::EXCLUDED: excluded.emplace_back(install_action); break; default: Checks::unreachable(VCPKG_LINE_INFO); } } @@ -397,6 +405,15 @@ namespace vcpkg::Install std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(excluded.begin(), excluded.end(), &InstallPlanAction::compare_by_name); + + if (excluded.size() > 0) + { + const std::string excluded_string = Strings::join("\n", excluded, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname()); + }); + System::println("The following packages are excluded:\n%s", excluded_string); + } if (already_installed_plans.size() > 0) { @@ -538,7 +555,7 @@ namespace vcpkg::Install }; static const std::array INSTALL_SETTINGS; - static std::vector valid_arguments(const VcpkgPaths& paths) + std::vector get_all_port_names(const VcpkgPaths& paths) { auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); @@ -552,7 +569,7 @@ namespace vcpkg::Install SIZE_MAX, INSTALL_SWITCHES, INSTALL_SETTINGS, - &valid_arguments, + &get_all_port_names, }; void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) diff --git a/toolsrc/src/vcpkg/packagespec.cpp b/toolsrc/src/vcpkg/packagespec.cpp index 6e40d70f5..eeb9981af 100644 --- a/toolsrc/src/vcpkg/packagespec.cpp +++ b/toolsrc/src/vcpkg/packagespec.cpp @@ -92,6 +92,14 @@ namespace vcpkg return p; } + std::vector PackageSpec::to_package_specs(const std::vector& ports, + const Triplet& triplet) + { + return Util::fmap(ports, [&](const std::string s) { + return PackageSpec::from_name_and_triplet(s, triplet).value_or_exit(VCPKG_LINE_INFO); + }); + } + const std::string& PackageSpec::name() const { return this->m_name; } const Triplet& PackageSpec::triplet() const { return this->m_triplet; } -- cgit v1.2.3 From 79ebd26605e0f621f848206000a5b1c7239d5f37 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 26 Oct 2017 19:14:32 -0700 Subject: Remove VcpkgCmdArguments.check_and_get_optional_command_arguments() overload Also, use Util::Sets::contains() where possible. --- toolsrc/src/vcpkg/build.cpp | 7 +++---- toolsrc/src/vcpkg/commands.buildexternal.cpp | 2 +- toolsrc/src/vcpkg/commands.cache.cpp | 2 +- toolsrc/src/vcpkg/commands.contact.cpp | 2 +- toolsrc/src/vcpkg/commands.create.cpp | 2 +- toolsrc/src/vcpkg/commands.dependinfo.cpp | 2 +- toolsrc/src/vcpkg/commands.edit.cpp | 5 ++--- toolsrc/src/vcpkg/commands.env.cpp | 2 +- toolsrc/src/vcpkg/commands.hash.cpp | 2 +- toolsrc/src/vcpkg/commands.import.cpp | 2 +- toolsrc/src/vcpkg/commands.integrate.cpp | 2 +- toolsrc/src/vcpkg/commands.list.cpp | 7 +++---- toolsrc/src/vcpkg/commands.owns.cpp | 4 ++-- toolsrc/src/vcpkg/commands.portsdiff.cpp | 2 +- toolsrc/src/vcpkg/commands.search.cpp | 19 +++++++++---------- toolsrc/src/vcpkg/commands.version.cpp | 2 +- toolsrc/src/vcpkg/help.cpp | 2 +- toolsrc/src/vcpkg/install.cpp | 16 ++++++++-------- toolsrc/src/vcpkg/remove.cpp | 14 +++++++------- toolsrc/src/vcpkg/update.cpp | 2 +- 20 files changed, 47 insertions(+), 51 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index c26dcc591..30a6a791c 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -30,11 +30,11 @@ namespace vcpkg::Build::Command void perform_and_exit(const FullPackageSpec& full_spec, const fs::path& port_dir, - const std::unordered_set& options, + const ParsedArguments& options, const VcpkgPaths& paths) { const PackageSpec& spec = full_spec.package_spec; - if (options.find(OPTION_CHECKS_ONLY) != options.end()) + if (Util::Sets::contains(options.switches, OPTION_CHECKS_ONLY)) { const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet()); const auto build_info = Build::read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); @@ -107,8 +107,7 @@ namespace vcpkg::Build::Command const std::string command_argument = args.command_arguments.at(0); const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, EXAMPLE); Input::check_triplet(spec.package_spec.triplet(), paths); - const std::unordered_set options = - args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}); + const ParsedArguments options = args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}, {}); perform_and_exit(spec, paths.port_dir(spec.package_spec), options, paths); } } diff --git a/toolsrc/src/vcpkg/commands.buildexternal.cpp b/toolsrc/src/vcpkg/commands.buildexternal.cpp index 3991beb62..2cc7aabde 100644 --- a/toolsrc/src/vcpkg/commands.buildexternal.cpp +++ b/toolsrc/src/vcpkg/commands.buildexternal.cpp @@ -15,7 +15,7 @@ namespace vcpkg::Commands::BuildExternal const FullPackageSpec spec = Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, EXAMPLE); Input::check_triplet(spec.package_spec.triplet(), paths); - const std::unordered_set options = args.check_and_get_optional_command_arguments({}); + const ParsedArguments options = args.check_and_get_optional_command_arguments({}, {}); const fs::path port_dir = args.command_arguments.at(1); Build::Command::perform_and_exit(spec, port_dir, options, paths); diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp index 77f0a20f6..64a3169b1 100644 --- a/toolsrc/src/vcpkg/commands.cache.cpp +++ b/toolsrc/src/vcpkg/commands.cache.cpp @@ -32,7 +32,7 @@ namespace vcpkg::Commands::Cache "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s", Help::create_example_string("cache png")); args.check_max_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); const std::vector binary_paragraphs = read_all_binary_paragraphs(paths); if (binary_paragraphs.empty()) diff --git a/toolsrc/src/vcpkg/commands.contact.cpp b/toolsrc/src/vcpkg/commands.contact.cpp index 421b8a230..5694c1fa6 100644 --- a/toolsrc/src/vcpkg/commands.contact.cpp +++ b/toolsrc/src/vcpkg/commands.contact.cpp @@ -14,7 +14,7 @@ namespace vcpkg::Commands::Contact void perform_and_exit(const VcpkgCmdArguments& args) { args.check_exact_arg_count(0); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); System::println("Send an email to %s with any feedback.", email()); Checks::exit_success(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp index 85763f25e..f1acacd14 100644 --- a/toolsrc/src/vcpkg/commands.create.cpp +++ b/toolsrc/src/vcpkg/commands.create.cpp @@ -14,7 +14,7 @@ namespace vcpkg::Commands::Create R"###(create zlib2 http://zlib.net/zlib1211.zip "zlib1211-2.zip")###"); args.check_max_arg_count(3, EXAMPLE); args.check_min_arg_count(2, EXAMPLE); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); const std::string port_name = args.command_arguments.at(0); const std::string url = args.command_arguments.at(1); diff --git a/toolsrc/src/vcpkg/commands.dependinfo.cpp b/toolsrc/src/vcpkg/commands.dependinfo.cpp index 89c7e0c7f..e5554f7e2 100644 --- a/toolsrc/src/vcpkg/commands.dependinfo.cpp +++ b/toolsrc/src/vcpkg/commands.dependinfo.cpp @@ -13,7 +13,7 @@ namespace vcpkg::Commands::DependInfo { static const std::string EXAMPLE = Help::create_example_string(R"###(depend-info [pat])###"); args.check_max_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); std::vector> source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index 668ec9b1a..bf618e256 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -65,8 +65,7 @@ namespace vcpkg::Commands::Edit static const std::string EXAMPLE = Help::create_example_string("edit zlib"); args.check_exact_arg_count(1, EXAMPLE); - const std::unordered_set options = - args.check_and_get_optional_command_arguments({OPTION_BUILDTREES}); + const ParsedArguments options = args.check_and_get_optional_command_arguments({OPTION_BUILDTREES}, {}); const std::string port_name = args.command_arguments.at(0); const fs::path portpath = paths.ports / port_name; @@ -95,7 +94,7 @@ namespace vcpkg::Commands::Edit } const fs::path env_editor = *it; - if (options.find(OPTION_BUILDTREES) != options.cend()) + if (Util::Sets::contains(options.switches, OPTION_BUILDTREES)) { const auto buildtrees_current_dir = paths.buildtrees / port_name; diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp index 9f8ae5207..c0d26dac2 100644 --- a/toolsrc/src/vcpkg/commands.env.cpp +++ b/toolsrc/src/vcpkg/commands.env.cpp @@ -11,7 +11,7 @@ namespace vcpkg::Commands::Env { static const std::string EXAMPLE = Help::create_example_string(R"(env --triplet x64-windows)"); args.check_exact_arg_count(0, EXAMPLE); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 4bc58b509..51f6b9ad0 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -34,7 +34,7 @@ namespace vcpkg::Commands::Hash Help::create_example_string("hash boost_1_62_0.tar.bz2")); args.check_min_arg_count(1, EXAMPLE); args.check_max_arg_count(2, EXAMPLE); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); if (args.command_arguments.size() == 1) { diff --git a/toolsrc/src/vcpkg/commands.import.cpp b/toolsrc/src/vcpkg/commands.import.cpp index 119aee022..5e74b6d94 100644 --- a/toolsrc/src/vcpkg/commands.import.cpp +++ b/toolsrc/src/vcpkg/commands.import.cpp @@ -97,7 +97,7 @@ namespace vcpkg::Commands::Import static const std::string EXAMPLE = Help::create_example_string( R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)"); args.check_exact_arg_count(3, EXAMPLE); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); const fs::path control_file_path(args.command_arguments[0]); const fs::path include_directory(args.command_arguments[1]); diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 27e563cfa..604bd2c6e 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -359,7 +359,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console "%s", INTEGRATE_COMMAND_HELPSTRING); args.check_exact_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); #if defined(_WIN32) if (args.command_arguments[0] == Subcommand::INSTALL) diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp index d0e8e00b4..145d4c931 100644 --- a/toolsrc/src/vcpkg/commands.list.cpp +++ b/toolsrc/src/vcpkg/commands.list.cpp @@ -30,8 +30,7 @@ namespace vcpkg::Commands::List "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", Help::create_example_string("list png")); args.check_max_arg_count(1, EXAMPLE); - const std::unordered_set options = - args.check_and_get_optional_command_arguments({OPTION_FULLDESC}); + const ParsedArguments options = args.check_and_get_optional_command_arguments({OPTION_FULLDESC}, {}); const StatusParagraphs status_paragraphs = database_load_check(paths); std::vector installed_packages = get_installed_ports(status_paragraphs); @@ -52,7 +51,7 @@ namespace vcpkg::Commands::List { for (const StatusParagraph* status_paragraph : installed_packages) { - do_print(*status_paragraph, options.find(OPTION_FULLDESC) != options.cend()); + do_print(*status_paragraph, Util::Sets::contains(options.switches, OPTION_FULLDESC)); } } else @@ -66,7 +65,7 @@ namespace vcpkg::Commands::List continue; } - do_print(*status_paragraph, options.find(OPTION_FULLDESC) != options.cend()); + do_print(*status_paragraph, Util::Sets::contains(options.switches, OPTION_FULLDESC)); } } diff --git a/toolsrc/src/vcpkg/commands.owns.cpp b/toolsrc/src/vcpkg/commands.owns.cpp index 69079e829..b2db966e1 100644 --- a/toolsrc/src/vcpkg/commands.owns.cpp +++ b/toolsrc/src/vcpkg/commands.owns.cpp @@ -29,9 +29,9 @@ namespace vcpkg::Commands::Owns static const std::string EXAMPLE = Strings::format("The argument should be a pattern to search for. %s", Help::create_example_string("owns zlib.dll")); args.check_exact_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); - StatusParagraphs status_db = database_load_check(paths); + const StatusParagraphs status_db = database_load_check(paths); search_file(paths, args.command_arguments[0], status_db); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp index a8c043751..5008f3e8a 100644 --- a/toolsrc/src/vcpkg/commands.portsdiff.cpp +++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp @@ -120,7 +120,7 @@ namespace vcpkg::Commands::PortsDiff Help::create_example_string("portsdiff mybranchname")); args.check_min_arg_count(1, EXAMPLE); args.check_max_arg_count(2, EXAMPLE); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); const fs::path& git_exe = paths.get_git_exe(); diff --git a/toolsrc/src/vcpkg/commands.search.cpp b/toolsrc/src/vcpkg/commands.search.cpp index 3ba8707de..ad3046e6d 100644 --- a/toolsrc/src/vcpkg/commands.search.cpp +++ b/toolsrc/src/vcpkg/commands.search.cpp @@ -85,12 +85,13 @@ namespace vcpkg::Commands::Search "The argument should be a substring to search for, or no argument to display all libraries.\n%s", Help::create_example_string("search png")); args.check_max_arg_count(1, EXAMPLE); - const std::unordered_set options = - args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC}); + const ParsedArguments options = + args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC}, {}); + const bool full_description = Util::Sets::contains(options.switches, OPTION_FULLDESC); auto source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - if (options.find(OPTION_GRAPH) != options.cend()) + if (Util::Sets::contains(options.switches, OPTION_GRAPH)) { const std::string graph_as_string = create_graph_as_string(source_paragraphs); System::println(graph_as_string); @@ -101,12 +102,10 @@ namespace vcpkg::Commands::Search { for (const auto& source_control_file : source_paragraphs) { - do_print(*source_control_file->core_paragraph, options.find(OPTION_FULLDESC) != options.cend()); + do_print(*source_control_file->core_paragraph, full_description); for (auto&& feature_paragraph : source_control_file->feature_paragraphs) { - do_print(source_control_file->core_paragraph->name, - *feature_paragraph, - options.find(OPTION_FULLDESC) != options.cend()); + do_print(source_control_file->core_paragraph->name, *feature_paragraph, full_description); } } } @@ -120,10 +119,10 @@ namespace vcpkg::Commands::Search { auto&& sp = *source_control_file->core_paragraph; - bool contains_name = icontains(sp.name, args_zero); + const bool contains_name = icontains(sp.name, args_zero); if (contains_name || icontains(sp.description, args_zero)) { - do_print(sp, options.find(OPTION_FULLDESC) != options.cend()); + do_print(sp, full_description); } for (auto&& feature_paragraph : source_control_file->feature_paragraphs) @@ -131,7 +130,7 @@ namespace vcpkg::Commands::Search if (contains_name || icontains(feature_paragraph->name, args_zero) || icontains(feature_paragraph->description, args_zero)) { - do_print(sp.name, *feature_paragraph, options.find(OPTION_FULLDESC) != options.cend()); + do_print(sp.name, *feature_paragraph, full_description); } } } diff --git a/toolsrc/src/vcpkg/commands.version.cpp b/toolsrc/src/vcpkg/commands.version.cpp index 403c355b5..e8756a77d 100644 --- a/toolsrc/src/vcpkg/commands.version.cpp +++ b/toolsrc/src/vcpkg/commands.version.cpp @@ -65,7 +65,7 @@ namespace vcpkg::Commands::Version void perform_and_exit(const VcpkgCmdArguments& args) { args.check_exact_arg_count(0); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); System::println("Vcpkg package management program version %s\n" "\n" diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index 2a0578211..8783833f2 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -94,7 +94,7 @@ namespace vcpkg::Help void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { args.check_max_arg_count(1); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); if (args.command_arguments.empty()) { diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 76e943e8c..7bab740be 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -351,7 +351,7 @@ namespace vcpkg::Install Checks::unreachable(VCPKG_LINE_INFO); } - static void print_plan(const std::vector& action_plan, bool is_recursive) + static void print_plan(const std::vector& action_plan, const bool is_recursive) { std::vector remove_plans; std::vector rebuilt_plans; @@ -592,13 +592,13 @@ namespace vcpkg::Install } } - const std::unordered_set options = args.check_and_get_optional_command_arguments( - {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE, OPTION_KEEP_GOING}); - const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend(); - const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend(); - const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); - const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); - const KeepGoing keep_going = to_keep_going(options.find(OPTION_KEEP_GOING) != options.cend()); + const ParsedArguments options = args.check_and_get_optional_command_arguments( + {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE, OPTION_KEEP_GOING}, {}); + const bool dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN); + const bool use_head_version = Util::Sets::contains(options.switches, (OPTION_USE_HEAD_VERSION)); + const bool no_downloads = Util::Sets::contains(options.switches, (OPTION_NO_DOWNLOADS)); + const bool is_recursive = Util::Sets::contains(options.switches, (OPTION_RECURSE)); + const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING)); // create the plan StatusParagraphs status_db = database_load_check(paths); diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 6f555b9b8..156f23003 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -198,12 +198,12 @@ namespace vcpkg::Remove void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { static const std::string EXAMPLE = Help::create_example_string("remove zlib zlib:x64-windows curl boost"); - const std::unordered_set options = args.check_and_get_optional_command_arguments( - {OPTION_PURGE, OPTION_NO_PURGE, OPTION_RECURSE, OPTION_DRY_RUN, OPTION_OUTDATED}); + const ParsedArguments options = args.check_and_get_optional_command_arguments( + {OPTION_PURGE, OPTION_NO_PURGE, OPTION_RECURSE, OPTION_DRY_RUN, OPTION_OUTDATED}, {}); StatusParagraphs status_db = database_load_check(paths); std::vector specs; - if (options.find(OPTION_OUTDATED) != options.cend()) + if (Util::Sets::contains(options.switches, OPTION_OUTDATED)) { args.check_exact_arg_count(0, EXAMPLE); specs = Util::fmap(Update::find_outdated_packages(paths, status_db), @@ -226,8 +226,8 @@ namespace vcpkg::Remove Input::check_triplet(spec.triplet(), paths); } - const bool no_purge_was_passed = options.find(OPTION_NO_PURGE) != options.end(); - const bool purge_was_passed = options.find(OPTION_PURGE) != options.end(); + const bool no_purge_was_passed = Util::Sets::contains(options.switches, OPTION_NO_PURGE); + const bool purge_was_passed = Util::Sets::contains(options.switches, OPTION_PURGE); if (purge_was_passed && no_purge_was_passed) { System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); @@ -235,8 +235,8 @@ namespace vcpkg::Remove Checks::exit_fail(VCPKG_LINE_INFO); } const Purge purge = to_purge(purge_was_passed || !no_purge_was_passed); - const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); - const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend(); + const bool is_recursive = Util::Sets::contains(options.switches, OPTION_RECURSE); + const bool dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN); const std::vector remove_plan = Dependencies::create_remove_plan(specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !remove_plan.empty(), "Remove plan cannot be empty"); diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp index 168949bc1..7d565251e 100644 --- a/toolsrc/src/vcpkg/update.cpp +++ b/toolsrc/src/vcpkg/update.cpp @@ -41,7 +41,7 @@ namespace vcpkg::Update void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { args.check_exact_arg_count(0); - args.check_and_get_optional_command_arguments({}); + args.check_and_get_optional_command_arguments({}, {}); System::println("Using local portfile versions. To update the local portfiles, use `git pull`."); const StatusParagraphs status_db = database_load_check(paths); -- cgit v1.2.3 From 0796a9df0e4d171ef2c7ab4d0c16ef4dc496ee5c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 27 Oct 2017 18:53:36 -0700 Subject: [git] Update to 2.14.3 (was 2.14.2.3) --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 363319767..c6a92f813 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -150,10 +150,10 @@ namespace vcpkg fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array EXPECTED_VERSION = {2, 14, 2}; + static constexpr std::array EXPECTED_VERSION = {2, 14, 3}; static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.2.3-32-bit" / "cmd" / "git.exe"; + const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.3-32-bit" / "cmd" / "git.exe"; const std::vector from_path = Files::find_from_PATH("git"); std::vector candidate_paths; -- cgit v1.2.3 From 5f4221420701ff7d78e02b11622a00ee12a8e64a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 30 Oct 2017 23:06:04 -0700 Subject: [vcpkg] Enable pkg[*] as alias for all features. --- toolsrc/src/tests.installplan.cpp | 33 +++++++++++++++++++-------------- toolsrc/src/tests.packagespec.cpp | 34 ++++++++++++++++++++++++++++++++++ toolsrc/src/vcpkg/dependencies.cpp | 36 ++++++++++++++++++++++++++++++++---- 3 files changed, 85 insertions(+), 18 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.installplan.cpp b/toolsrc/src/tests.installplan.cpp index 347612abd..129926317 100644 --- a/toolsrc/src/tests.installplan.cpp +++ b/toolsrc/src/tests.installplan.cpp @@ -461,20 +461,6 @@ namespace UnitTest1 FullPackageSpec::to_feature_specs({spec_c_64, spec_a_86, spec_a_64, spec_c_86}), StatusParagraphs(std::move(status_paragraphs))); - /*Assert::AreEqual(size_t(8), install_plan.size()); - auto iterator_pos = [&](const PackageSpec& spec, size_t start) -> int { - auto it = std::find_if(install_plan.begin() + start, install_plan.end(), [&](auto& action) { - return action.spec == spec; - }); - Assert::IsTrue(it != install_plan.end()); - return (int)(it - install_plan.begin()); - }; - int a_64_1 = iterator_pos(spec_a_64.package_spec, 0), a_86_1 = iterator_pos(spec_a_86.package_spec, 0), - b_64 = iterator_pos(spec_b_64.package_spec, 0), b_86 = iterator_pos(spec_b_86.package_spec, 0), - c_64 = iterator_pos(spec_c_64.package_spec, 0), c_86 = iterator_pos(spec_c_86.package_spec, 0), - a_64_2 = iterator_pos(spec_a_64.package_spec, a_64_1 + 1), - a_86_2 = iterator_pos(spec_a_86.package_spec, a_86_1 + 1);*/ - remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); remove_plan_check(&install_plan[1], "a"); features_check(&install_plan[2], "b", {"core"}, Triplet::X64_WINDOWS); @@ -484,5 +470,24 @@ namespace UnitTest1 features_check(&install_plan[6], "a", {"a1", "core"}); features_check(&install_plan[7], "c", {"core"}); } + + TEST_METHOD(install_all_features_test) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}), {"core"}}; + + auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); + Assert::IsTrue(install_specs.has_value()); + if (!install_specs.has_value()) return; + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::IsTrue(install_plan.size() == 1); + features_check(&install_plan[0], "a", {"0", "1", "core"}, Triplet::X64_WINDOWS); + } }; } diff --git a/toolsrc/src/tests.packagespec.cpp b/toolsrc/src/tests.packagespec.cpp index cb5c41af0..25498a799 100644 --- a/toolsrc/src/tests.packagespec.cpp +++ b/toolsrc/src/tests.packagespec.cpp @@ -3,6 +3,7 @@ #include #include +#include #pragma comment(lib, "version") #pragma comment(lib, "winhttp") @@ -103,6 +104,39 @@ namespace UnitTest1 Assert::AreEqual("", spec->triplet.c_str()); } + TEST_METHOD(parsed_specifier_wildcard_feature) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[*]"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::IsTrue(spec->features.size() == 1); + Assert::AreEqual("*", spec->features[0].c_str()); + Assert::AreEqual("", spec->triplet.c_str()); + } + + TEST_METHOD(expand_wildcards) + { + auto zlib = + vcpkg::FullPackageSpec::from_string("zlib[0,1]", Triplet::X86_UWP).value_or_exit(VCPKG_LINE_INFO); + auto openssl = + vcpkg::FullPackageSpec::from_string("openssl[*]", Triplet::X86_UWP).value_or_exit(VCPKG_LINE_INFO); + auto specs = FullPackageSpec::to_feature_specs({zlib, openssl}); + Util::sort(specs); + auto spectargets = FeatureSpec::from_strings_and_triplet( + { + "openssl", + "zlib", + "openssl[*]", + "zlib[0]", + "zlib[1]", + }, + Triplet::X86_UWP); + Util::sort(spectargets); + Assert::IsTrue(specs.size() == spectargets.size()); + Assert::IsTrue(Util::all_equal(specs, spectargets)); + } + TEST_METHOD(utf8_to_utf16) { auto str = vcpkg::Strings::to_utf16("abc"); diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 9d264baa2..4c4a8a31c 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -157,7 +157,7 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const std::unordered_set& features, const RequestType& request_type) - : spec(spec), plan_type(InstallPlanType::UNKNOWN), request_type(request_type), feature_list(features) + : spec(spec), plan_type(InstallPlanType::ALREADY_INSTALLED), request_type(request_type), feature_list(features) { } @@ -605,10 +605,38 @@ namespace vcpkg::Dependencies { Cluster& spec_cluster = graph.get(spec.spec()); spec_cluster.request_type = RequestType::USER_REQUESTED; - auto res = mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + if (spec.feature() == "*") + { + if (auto p_scf = spec_cluster.source_control_file.value_or(nullptr)) + { + for (auto&& feature : p_scf->feature_paragraphs) + { + auto res = mark_plus(feature->name, spec_cluster, graph, graph_plan); + + Checks::check_exit(VCPKG_LINE_INFO, + res == MarkPlusResult::SUCCESS, + "Error: Unable to locate feature %s", + spec); + } + + auto res = mark_plus("core", spec_cluster, graph, graph_plan); - Checks::check_exit( - VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); + Checks::check_exit( + VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); + } + else + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "Error: Unable to handle '*' because can't find CONTROL for %s", spec.spec()); + } + } + else + { + auto res = mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + + Checks::check_exit( + VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); + } graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster}); } -- cgit v1.2.3 From 3457d89d41f19e933929cf4df88892f47cef297c Mon Sep 17 00:00:00 2001 From: sdcb Date: Tue, 31 Oct 2017 10:17:47 +0800 Subject: Using CP_UTF8 macro instead of magic numbers. --- toolsrc/src/vcpkg.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index b4c2d0fe2..2a73c5b0f 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -245,8 +245,8 @@ int main(const int argc, const char* const* const argv) GlobalState::g_init_console_cp = GetConsoleCP(); GlobalState::g_init_console_output_cp = GetConsoleOutputCP(); - SetConsoleCP(65001); - SetConsoleOutputCP(65001); + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); const std::string trimmed_command_line = trim_path_from_command_line(Strings::to_utf8(GetCommandLineW())); #endif -- cgit v1.2.3 From 33fc44a0e3ade2c7e9369723b2ee4965ee8795e6 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 31 Oct 2017 02:13:49 -0700 Subject: [vcpkg] Add optional Abi field to BinaryParagraph for future use. --- toolsrc/src/tests.paragraph.cpp | 30 ++++++++++++++++++++++++++++++ toolsrc/src/vcpkg/binaryparagraph.cpp | 4 ++++ 2 files changed, 34 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.paragraph.cpp b/toolsrc/src/tests.paragraph.cpp index d9301abd0..13052610f 100644 --- a/toolsrc/src/tests.paragraph.cpp +++ b/toolsrc/src/tests.paragraph.cpp @@ -190,6 +190,20 @@ namespace UnitTest1 Assert::AreEqual("c", pgh.depends[2].c_str()); } + TEST_METHOD(BinaryParagraph_Abi) + { + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Abi", "abcd123"}, + }); + + Assert::AreEqual(size_t(0), pgh.depends.size()); + Assert::IsTrue(pgh.abi == "abcd123"); + } + TEST_METHOD(parse_paragraphs_empty) { const char* str = ""; @@ -385,5 +399,21 @@ namespace UnitTest1 Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str()); } + + TEST_METHOD(BinaryParagraph_serialize_abi) + { + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", "a, b, c"}, + {"Abi", "123abc"}, + }); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(1), pghs.size()); + Assert::AreEqual("123abc", pghs[0]["Abi"].c_str()); + } }; } diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp index 3a493eb4c..c7136b713 100644 --- a/toolsrc/src/vcpkg/binaryparagraph.cpp +++ b/toolsrc/src/vcpkg/binaryparagraph.cpp @@ -16,6 +16,7 @@ namespace vcpkg namespace Fields { + static const std::string ABI = "Abi"; static const std::string FEATURE = "Feature"; static const std::string DESCRIPTION = "Description"; static const std::string MAINTAINER = "Maintainer"; @@ -47,6 +48,8 @@ namespace vcpkg this->description = parser.optional_field(Fields::DESCRIPTION); this->maintainer = parser.optional_field(Fields::MAINTAINER); + this->abi = parser.optional_field(Fields::ABI); + std::string multi_arch; parser.required_field(Fields::MULTI_ARCH, multi_arch); @@ -118,6 +121,7 @@ namespace vcpkg out_str.append("Multi-Arch: same\n"); if (!pgh.maintainer.empty()) out_str.append("Maintainer: ").append(pgh.maintainer).push_back('\n'); + if (!pgh.abi.empty()) out_str.append("Abi: ").append(pgh.abi).push_back('\n'); if (!pgh.description.empty()) out_str.append("Description: ").append(pgh.description).push_back('\n'); } } -- cgit v1.2.3 From 925fab565a76c23e76329193bc25158608bc9fc6 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 31 Oct 2017 03:04:28 -0700 Subject: [vcpkg] --head should only apply to USER_REQUESTED packages. --- toolsrc/src/vcpkg/commands.ci.cpp | 5 ++-- toolsrc/src/vcpkg/dependencies.cpp | 14 +++++++++ toolsrc/src/vcpkg/export.cpp | 4 ++- toolsrc/src/vcpkg/install.cpp | 59 +++++++++++++++++++------------------- 4 files changed, 49 insertions(+), 33 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 559dc4541..d012ff6dc 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -44,11 +44,12 @@ namespace vcpkg::Commands::CI const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; const std::vector action_plan = - Util::fmap(install_plan, [](InstallPlanAction& install_action) { + Util::fmap(install_plan, [&install_plan_options](InstallPlanAction& install_action) { + install_action.build_options = install_plan_options; return Dependencies::AnyAction(std::move(install_action)); }); - return Install::perform(action_plan, install_plan_options, Install::KeepGoing::YES, paths, status_db); + return Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db); } struct TripletAndSummary diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 4c4a8a31c..6f599afd4 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -133,6 +133,20 @@ namespace vcpkg::Dependencies "Cannot get dependencies because there was none of: source/binary/status paragraphs"); } + std::string to_output_string(RequestType request_type, + const CStringView s, + const Build::BuildPackageOptions& options) + { + const char* const from_head = options.use_head_version == Build::UseHeadVersion::YES ? " (from HEAD)" : ""; + + switch (request_type) + { + case RequestType::AUTO_SELECTED: return Strings::format(" * %s%s", s, from_head); + case RequestType::USER_REQUESTED: return Strings::format(" %s%s", s, from_head); + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + std::string to_output_string(RequestType request_type, const CStringView s) { switch (request_type) diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index f0a3b23d0..eb4f5db3c 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -68,6 +68,8 @@ namespace vcpkg::Export { static constexpr std::array ORDER = {ExportPlanType::ALREADY_BUILT, ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT}; + static constexpr Build::BuildPackageOptions build_options = {Build::UseHeadVersion::NO, + Build::AllowDownloads::YES}; for (const ExportPlanType plan_type : ORDER) { @@ -80,7 +82,7 @@ namespace vcpkg::Export std::vector cont = it->second; std::sort(cont.begin(), cont.end(), &ExportPlanAction::compare_by_name); const std::string as_string = Strings::join("\n", cont, [](const ExportPlanAction* p) { - return Dependencies::to_output_string(p->request_type, p->spec.to_string()); + return Dependencies::to_output_string(p->request_type, p->spec.to_string(), build_options); }); switch (plan_type) diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 7bab740be..b1f722d59 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -250,7 +250,6 @@ namespace vcpkg::Install BuildResult perform_install_plan_action(const VcpkgPaths& paths, const InstallPlanAction& action, - const Build::BuildPackageOptions& build_package_options, StatusParagraphs& status_db) { const InstallPlanType& plan_type = action.plan_type; @@ -259,7 +258,7 @@ namespace vcpkg::Install GlobalState::feature_packages ? action.displayname() : display_name; const bool is_user_requested = action.request_type == RequestType::USER_REQUESTED; - const bool use_head_version = to_bool(build_package_options.use_head_version); + const bool use_head_version = to_bool(action.build_options.use_head_version); if (plan_type == InstallPlanType::ALREADY_INSTALLED) { @@ -285,7 +284,7 @@ namespace vcpkg::Install *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), action.spec.triplet(), paths.port_dir(action.spec), - build_package_options, + action.build_options, action.feature_list}; return Build::build_package(paths, build_config, status_db); } @@ -295,7 +294,7 @@ namespace vcpkg::Install action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO), action.spec.triplet(), paths.port_dir(action.spec), - build_package_options}; + action.build_options}; return Build::build_package(paths, build_config, status_db); } }(); @@ -407,46 +406,38 @@ namespace vcpkg::Install std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name); std::sort(excluded.begin(), excluded.end(), &InstallPlanAction::compare_by_name); + static auto actions_to_output_string = [](const std::vector& v) { + return Strings::join("\n", v, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname(), p->build_options); + }); + }; + if (excluded.size() > 0) { - const std::string excluded_string = Strings::join("\n", excluded, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); - System::println("The following packages are excluded:\n%s", excluded_string); + System::println("The following packages are excluded:\n%s", actions_to_output_string(excluded)); } if (already_installed_plans.size() > 0) { - const std::string already_string = - Strings::join("\n", already_installed_plans, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); - System::println("The following packages are already installed:\n%s", already_string); + System::println("The following packages are already installed:\n%s", + actions_to_output_string(already_installed_plans)); } if (rebuilt_plans.size() > 0) { - const std::string rebuilt_string = Strings::join("\n", rebuilt_plans, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); - System::println("The following packages will be rebuilt:\n%s", rebuilt_string); + System::println("The following packages will be rebuilt:\n%s", actions_to_output_string(rebuilt_plans)); } if (new_plans.size() > 0) { - const std::string new_string = Strings::join("\n", new_plans, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); - System::println("The following packages will be built and installed:\n%s", new_string); + System::println("The following packages will be built and installed:\n%s", + actions_to_output_string(new_plans)); } if (only_install_plans.size() > 0) { - const std::string only_install_string = - Strings::join("\n", only_install_plans, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname()); - }); - System::println("The following packages will be directly installed:\n%s", only_install_string); + System::println("The following packages will be directly installed:\n%s", + actions_to_output_string(only_install_plans)); } if (has_non_user_requested_packages) @@ -489,7 +480,6 @@ namespace vcpkg::Install } InstallSummary perform(const std::vector& action_plan, - const Build::BuildPackageOptions& install_plan_options, const KeepGoing keep_going, const VcpkgPaths& paths, StatusParagraphs& status_db) @@ -513,8 +503,7 @@ namespace vcpkg::Install if (const auto install_action = action.install_plan.get()) { - const BuildResult result = - perform_install_plan_action(paths, *install_action, install_plan_options, status_db); + const BuildResult result = perform_install_plan_action(paths, *install_action, status_db); if (result != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO) { System::println(Build::create_user_troubleshooting_message(install_action->spec)); @@ -629,6 +618,16 @@ namespace vcpkg::Install install_plan, [](InstallPlanAction& install_action) { return AnyAction(std::move(install_action)); }); } + for (auto&& action : action_plan) + { + if (auto p_install = action.install_plan.get()) + { + p_install->build_options = install_plan_options; + if (p_install->request_type != RequestType::USER_REQUESTED) + p_install->build_options.use_head_version = Build::UseHeadVersion::NO; + } + } + // install plan will be empty if it is already installed - need to change this at status paragraph part Checks::check_exit(VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty"); @@ -650,7 +649,7 @@ namespace vcpkg::Install Checks::exit_success(VCPKG_LINE_INFO); } - const InstallSummary summary = perform(action_plan, install_plan_options, keep_going, paths, status_db); + const InstallSummary summary = perform(action_plan, keep_going, paths, status_db); System::println("\nTotal elapsed time: %s", summary.total_elapsed_time); -- cgit v1.2.3 From a705df80b0f8db81b201492b4012e23e08a53694 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 31 Oct 2017 03:47:35 -0700 Subject: [vcpkg] Fix bug where packages with uninstalled features appear to be uninstalled. --- toolsrc/src/tests.statusparagraphs.cpp | 85 ++++++++++++++++++++++++++++++++++ toolsrc/src/vcpkg/statusparagraphs.cpp | 26 ++++------- 2 files changed, 95 insertions(+), 16 deletions(-) create mode 100644 toolsrc/src/tests.statusparagraphs.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.statusparagraphs.cpp b/toolsrc/src/tests.statusparagraphs.cpp new file mode 100644 index 000000000..4cc1130b1 --- /dev/null +++ b/toolsrc/src/tests.statusparagraphs.cpp @@ -0,0 +1,85 @@ +#include + +#include +#include +#include +#include + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +using namespace vcpkg; +using namespace vcpkg::Paragraphs; + +namespace UnitTest1 +{ + class StatusParagraphsTests : public TestClass + { + TEST_METHOD(find_installed) + { + auto pghs = parse_paragraphs(R"( +Package: ffmpeg +Version: 3.3.3 +Architecture: x64-windows +Multi-Arch: same +Description: +Status: install ok installed +)"); + Assert::IsTrue(!!pghs); + if (!pghs) return; + + StatusParagraphs status_db(Util::fmap( + *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique(std::move(rpgh)); })); + + auto it = status_db.find_installed("ffmpeg", Triplet::X64_WINDOWS); + Assert::IsTrue(it != status_db.end()); + } + + TEST_METHOD(find_not_installed) + { + auto pghs = parse_paragraphs(R"( +Package: ffmpeg +Version: 3.3.3 +Architecture: x64-windows +Multi-Arch: same +Description: +Status: purge ok not-installed +)"); + Assert::IsTrue(!!pghs); + if (!pghs) return; + + StatusParagraphs status_db(Util::fmap( + *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique(std::move(rpgh)); })); + + auto it = status_db.find_installed("ffmpeg", Triplet::X64_WINDOWS); + Assert::IsTrue(it == status_db.end()); + } + + TEST_METHOD(find_with_feature_packages) + { + auto pghs = parse_paragraphs(R"( +Package: ffmpeg +Version: 3.3.3 +Architecture: x64-windows +Multi-Arch: same +Description: +Status: install ok installed + +Package: ffmpeg +Feature: openssl +Depends: openssl +Architecture: x64-windows +Multi-Arch: same +Description: +Status: purge ok not-installed +)"); + Assert::IsTrue(!!pghs); + if (!pghs) return; + + StatusParagraphs status_db(Util::fmap( + *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique(std::move(rpgh)); })); + + auto it = status_db.find_installed("ffmpeg", Triplet::X64_WINDOWS); + Assert::IsTrue(it != status_db.end()); + } + }; +} \ No newline at end of file diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp index 647ed6d3f..d4afc0427 100644 --- a/toolsrc/src/vcpkg/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -10,22 +10,6 @@ namespace vcpkg StatusParagraphs::StatusParagraphs(std::vector>&& ps) : paragraphs(std::move(ps)){}; - StatusParagraphs::const_iterator StatusParagraphs::find(const std::string& name, const Triplet& triplet) const - { - return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { - const PackageSpec& spec = pgh->package.spec; - return spec.name() == name && spec.triplet() == triplet; - }); - } - - StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, const Triplet& triplet) - { - return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { - const PackageSpec& spec = pgh->package.spec; - return spec.name() == name && spec.triplet() == triplet; - }); - } - std::vector*> StatusParagraphs::find_all(const std::string& name, const Triplet& triplet) { @@ -50,6 +34,16 @@ namespace vcpkg }); } + StatusParagraphs::const_iterator StatusParagraphs::find(const std::string& name, + const Triplet& triplet, + const std::string& feature) const + { + return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { + const PackageSpec& spec = pgh->package.spec; + return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature; + }); + } + StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name, const Triplet& triplet) const { -- cgit v1.2.3 From 7d0bcceaf028f28b0bc5ae666689f26d8de743a9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 31 Oct 2017 17:06:07 -0700 Subject: [findVSInstances] Data lines are now placed within tags. Text outside these tags is ignored This means we can print text in powershell now and it won't break vcpkg. --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index c6a92f813..8b9e6c598 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -320,6 +320,23 @@ namespace vcpkg std::string major_version() const { return version.substr(0, 2); } }; + static std::vector keep_data_lines(const std::string& data_blob) + { + static const std::regex DATA_LINE_REGEX(R"(::(.+?)(?=::))"); + + std::vector data_lines; + + const std::sregex_iterator it(data_blob.cbegin(), data_blob.cend(), DATA_LINE_REGEX); + const std::sregex_iterator end; + for (std::sregex_iterator i = it; i != end; ++i) + { + const std::smatch match = *i; + data_lines.push_back(match[1].str()); + } + + return data_lines; + } + static std::vector get_visual_studio_instances(const VcpkgPaths& paths) { const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; @@ -327,9 +344,11 @@ namespace vcpkg Checks::check_exit( VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect Visual Studio instances"); - const std::vector instances_as_strings = Strings::split(ec_data.output, "::"); - Checks::check_exit( - VCPKG_LINE_INFO, !instances_as_strings.empty(), "Could not detect any Visual Studio instances.\n"); + const std::vector instances_as_strings = keep_data_lines(ec_data.output); + Checks::check_exit(VCPKG_LINE_INFO, + !instances_as_strings.empty(), + "Could not detect any Visual Studio instances. Powershell returned: %s\n", + ec_data.output); std::vector output; for (const std::string& instance_as_string : instances_as_strings) -- cgit v1.2.3 From 47bf4b6b5caf44adeaf582e5137377fb9d2cc5c4 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 31 Oct 2017 17:23:09 -0700 Subject: [fetchDependency] Now also returns output in the form data --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 8b9e6c598..40f52af73 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -62,6 +62,23 @@ namespace vcpkg return nullopt; } + static std::vector keep_data_lines(const std::string& data_blob) + { + static const std::regex DATA_LINE_REGEX(R"(::(.+?)(?=::))"); + + std::vector data_lines; + + const std::sregex_iterator it(data_blob.cbegin(), data_blob.cend(), DATA_LINE_REGEX); + const std::sregex_iterator end; + for (std::sregex_iterator i = it; i != end; ++i) + { + const std::smatch match = *i; + data_lines.push_back(match[1].str()); + } + + return data_lines; + } + static fs::path fetch_dependency(const fs::path& scripts_folder, const std::string& tool_name, const fs::path& expected_downloaded_path, @@ -91,7 +108,11 @@ namespace vcpkg Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); } - const fs::path actual_downloaded_path = Strings::trim(std::string{rc.output}); + const std::vector dependency_path = keep_data_lines(rc.output); + Checks::check_exit( + VCPKG_LINE_INFO, dependency_path.size() == 1, "Expected dependency path, but got %s", rc.output); + + const fs::path actual_downloaded_path = Strings::trim(std::string{dependency_path.at(0)}); std::error_code ec; const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); Checks::check_exit(VCPKG_LINE_INFO, @@ -320,23 +341,6 @@ namespace vcpkg std::string major_version() const { return version.substr(0, 2); } }; - static std::vector keep_data_lines(const std::string& data_blob) - { - static const std::regex DATA_LINE_REGEX(R"(::(.+?)(?=::))"); - - std::vector data_lines; - - const std::sregex_iterator it(data_blob.cbegin(), data_blob.cend(), DATA_LINE_REGEX); - const std::sregex_iterator end; - for (std::sregex_iterator i = it; i != end; ++i) - { - const std::smatch match = *i; - data_lines.push_back(match[1].str()); - } - - return data_lines; - } - static std::vector get_visual_studio_instances(const VcpkgPaths& paths) { const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; -- cgit v1.2.3 From a5b54588eca1d57366f7052ee9ab30da4ba68066 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 31 Oct 2017 17:30:29 -0700 Subject: [git] Update to 2.15.0 (was 2.14.3) --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 40f52af73..5e43ee4c7 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -171,10 +171,10 @@ namespace vcpkg fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array EXPECTED_VERSION = {2, 14, 3}; + static constexpr std::array EXPECTED_VERSION = {2, 15, 0}; static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.3-32-bit" / "cmd" / "git.exe"; + const fs::path downloaded_copy = downloads_folder / "MinGit-2.15.0-32-bit" / "cmd" / "git.exe"; const std::vector from_path = Files::find_from_PATH("git"); std::vector candidate_paths; -- cgit v1.2.3 From 47090e68b8deeb5a38b638934b59fe3ddef0fa9f Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 1 Nov 2017 06:03:10 -0700 Subject: [vcpkg] Fix use of features in undocumented build command --- toolsrc/src/vcpkg/build.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 30a6a791c..c59b6f7d1 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -52,22 +52,20 @@ namespace vcpkg::Build::Command Checks::exit_fail(VCPKG_LINE_INFO); } - for (const std::string& str : full_spec.features) - { - System::println("%s \n", str); - } const auto& scf = source_control_file.value_or_exit(VCPKG_LINE_INFO); Checks::check_exit(VCPKG_LINE_INFO, spec.name() == scf->core_paragraph->name, - "The Name: field inside the CONTROL does not match the port directory: '%s' != '%s'", + "The Source field inside the CONTROL file does not match the port directory: '%s' != '%s'", scf->core_paragraph->name, spec.name()); const StatusParagraphs status_db = database_load_check(paths); const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; + const std::unordered_set features_as_set(full_spec.features.begin(), full_spec.features.end()); + const Build::BuildPackageConfig build_config{ - *scf->core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options}; + *scf, spec.triplet(), fs::path{port_dir}, build_package_options, features_as_set}; const auto build_timer = Chrono::ElapsedTime::create_started(); const auto result = Build::build_package(paths, build_config, status_db); @@ -107,6 +105,11 @@ namespace vcpkg::Build::Command const std::string command_argument = args.command_arguments.at(0); const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, EXAMPLE); Input::check_triplet(spec.package_spec.triplet(), paths); + if (!spec.features.empty() && !GlobalState::feature_packages) + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "Feature packages are experimentally available under the --featurepackages flag."); + } const ParsedArguments options = args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}, {}); perform_and_exit(spec, paths.port_dir(spec.package_spec), options, paths); } -- cgit v1.2.3 From 6a91d1ece10ce0aeda89c44611d5335a07b8e40d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 2 Nov 2017 15:20:42 -0700 Subject: [vcpkg] Refactor argument parsing to use common code paths. --- toolsrc/src/tests.arguments.cpp | 11 +- toolsrc/src/vcpkg/build.cpp | 29 ++++-- toolsrc/src/vcpkg/commands.autocomplete.cpp | 10 +- toolsrc/src/vcpkg/commands.buildexternal.cpp | 20 ++-- toolsrc/src/vcpkg/commands.cache.cpp | 16 ++- toolsrc/src/vcpkg/commands.ci.cpp | 20 +++- toolsrc/src/vcpkg/commands.contact.cpp | 12 ++- toolsrc/src/vcpkg/commands.cpp | 2 +- toolsrc/src/vcpkg/commands.create.cpp | 15 ++- toolsrc/src/vcpkg/commands.dependinfo.cpp | 12 ++- toolsrc/src/vcpkg/commands.edit.cpp | 18 ++-- toolsrc/src/vcpkg/commands.env.cpp | 12 ++- toolsrc/src/vcpkg/commands.hash.cpp | 15 ++- toolsrc/src/vcpkg/commands.import.cpp | 14 ++- toolsrc/src/vcpkg/commands.integrate.cpp | 13 +-- toolsrc/src/vcpkg/commands.list.cpp | 20 +++- toolsrc/src/vcpkg/commands.owns.cpp | 13 ++- toolsrc/src/vcpkg/commands.portsdiff.cpp | 15 ++- toolsrc/src/vcpkg/commands.search.cpp | 22 ++-- toolsrc/src/vcpkg/commands.version.cpp | 11 +- toolsrc/src/vcpkg/export.cpp | 80 ++++++++------- toolsrc/src/vcpkg/help.cpp | 11 +- toolsrc/src/vcpkg/install.cpp | 26 ++--- toolsrc/src/vcpkg/remove.cpp | 42 ++++---- toolsrc/src/vcpkg/update.cpp | 11 +- toolsrc/src/vcpkg/vcpkgcmdarguments.cpp | 147 ++++++++++++--------------- 26 files changed, 362 insertions(+), 255 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.arguments.cpp b/toolsrc/src/tests.arguments.cpp index 25bf0f085..0f082222d 100644 --- a/toolsrc/src/tests.arguments.cpp +++ b/toolsrc/src/tests.arguments.cpp @@ -34,9 +34,12 @@ namespace UnitTest1 TEST_METHOD(create_from_arg_sequence_valued_options) { + std::array settings = { {{"--a", ""}} }; + CommandStructure cmdstruct = { "", 0, SIZE_MAX, {{}, settings }, nullptr }; + std::vector t = {"--a=b", "command", "argument"}; auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); - auto opts = v.check_and_get_optional_command_arguments({}, {"--a"}); + auto opts = v.parse_arguments(cmdstruct); Assert::AreEqual("b", opts.settings["--a"].c_str()); Assert::AreEqual(size_t{1}, v.command_arguments.size()); Assert::AreEqual("argument", v.command_arguments[0].c_str()); @@ -45,9 +48,13 @@ namespace UnitTest1 TEST_METHOD(create_from_arg_sequence_valued_options2) { + std::array switches = { {{"--a", ""}, {"--c", ""}} }; + std::array settings = { { {"--b", ""}, {"--d", ""}} }; + CommandStructure cmdstruct = {"", 0, SIZE_MAX, {switches, settings}, nullptr}; + std::vector t = {"--a", "--b=c"}; auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); - auto opts = v.check_and_get_optional_command_arguments({"--a", "--c"}, {"--b", "--d"}); + auto opts = v.parse_arguments(cmdstruct); Assert::AreEqual("c", opts.settings["--b"].c_str()); Assert::IsTrue(opts.settings.find("--d") == opts.settings.end()); Assert::IsTrue(opts.switches.find("--a") != opts.switches.end()); diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index c59b6f7d1..8b4654aa8 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -28,10 +28,10 @@ namespace vcpkg::Build::Command static const std::string OPTION_CHECKS_ONLY = "--checks-only"; - void perform_and_exit(const FullPackageSpec& full_spec, - const fs::path& port_dir, - const ParsedArguments& options, - const VcpkgPaths& paths) + void perform_and_exit_ex(const FullPackageSpec& full_spec, + const fs::path& port_dir, + const ParsedArguments& options, + const VcpkgPaths& paths) { const PackageSpec& spec = full_spec.package_spec; if (Util::Sets::contains(options.switches, OPTION_CHECKS_ONLY)) @@ -97,21 +97,32 @@ namespace vcpkg::Build::Command Checks::exit_success(VCPKG_LINE_INFO); } + static const std::array BUILD_SWITCHES = {{ + {OPTION_CHECKS_ONLY, "Only run checks, do not rebuild package"}, + }}; + + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("build zlib:x64-windows"), + 1, + 1, + {BUILD_SWITCHES, {}}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string EXAMPLE = Help::create_example_string("build zlib:x64-windows"); // Build only takes a single package and all dependencies must already be installed - args.check_exact_arg_count(1, EXAMPLE); + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const std::string command_argument = args.command_arguments.at(0); - const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, EXAMPLE); + const FullPackageSpec spec = + Input::check_and_get_full_package_spec(command_argument, default_triplet, COMMAND_STRUCTURE.example_text); Input::check_triplet(spec.package_spec.triplet(), paths); if (!spec.features.empty() && !GlobalState::feature_packages) { Checks::exit_with_message( VCPKG_LINE_INFO, "Feature packages are experimentally available under the --featurepackages flag."); } - const ParsedArguments options = args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}, {}); - perform_and_exit(spec, paths.port_dir(spec.package_spec), options, paths); + perform_and_exit_ex(spec, paths.port_dir(spec.package_spec), options, paths); } } diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp index 410bfcd0d..0df7ec5eb 100644 --- a/toolsrc/src/vcpkg/commands.autocomplete.cpp +++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp @@ -120,7 +120,6 @@ namespace vcpkg::Commands::Autocomplete }; static constexpr CommandEntry COMMANDS[] = { - CommandEntry{"install", R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE}, CommandEntry{"install", R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE}, CommandEntry{"edit", R"###(^edit\s(.*\s|)(\S*)$)###", Edit::COMMAND_STRUCTURE}, CommandEntry{"remove", R"###(^remove\s(.*\s|)(\S*)$)###", Remove::COMMAND_STRUCTURE}, @@ -137,11 +136,16 @@ namespace vcpkg::Commands::Autocomplete const bool is_option = Strings::case_insensitive_ascii_starts_with(prefix, "-"); if (is_option) { - results = Util::fmap(command.structure.switches, [](auto&& s) -> std::string { return s; }); + results = + Util::fmap(command.structure.options.switches, [](const CommandSwitch& s) { return s.name; }); + + auto settings = Util::fmap(command.structure.options.settings, [](auto&& s) { return s.name; }); + results.insert(results.end(), settings.begin(), settings.end()); } else { - results = command.structure.valid_arguments(paths); + if (command.structure.valid_arguments != nullptr) + results = command.structure.valid_arguments(paths); } Util::unstable_keep_if(results, [&](const std::string& s) { diff --git a/toolsrc/src/vcpkg/commands.buildexternal.cpp b/toolsrc/src/vcpkg/commands.buildexternal.cpp index 2cc7aabde..82d03db48 100644 --- a/toolsrc/src/vcpkg/commands.buildexternal.cpp +++ b/toolsrc/src/vcpkg/commands.buildexternal.cpp @@ -7,17 +7,23 @@ namespace vcpkg::Commands::BuildExternal { + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)"), + 2, + 2, + {}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string EXAMPLE = - Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)"); - args.check_exact_arg_count(2, EXAMPLE); - const FullPackageSpec spec = - Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, EXAMPLE); + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); + + const FullPackageSpec spec = Input::check_and_get_full_package_spec( + args.command_arguments.at(0), default_triplet, COMMAND_STRUCTURE.example_text); Input::check_triplet(spec.package_spec.triplet(), paths); - const ParsedArguments options = args.check_and_get_optional_command_arguments({}, {}); const fs::path port_dir = args.command_arguments.at(1); - Build::Command::perform_and_exit(spec, port_dir, options, paths); + Build::Command::perform_and_exit_ex(spec, port_dir, options, paths); } } diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp index 64a3169b1..6fd123b7c 100644 --- a/toolsrc/src/vcpkg/commands.cache.cpp +++ b/toolsrc/src/vcpkg/commands.cache.cpp @@ -26,13 +26,19 @@ namespace vcpkg::Commands::Cache return output; } + const CommandStructure COMMAND_STRUCTURE = { + Strings::format( + "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s", + Help::create_example_string("cache png")), + 0, + 1, + {}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string EXAMPLE = Strings::format( - "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s", - Help::create_example_string("cache png")); - args.check_max_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); const std::vector binary_paragraphs = read_all_binary_paragraphs(paths); if (binary_paragraphs.empty()) diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index d012ff6dc..dce294004 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -58,13 +58,23 @@ namespace vcpkg::Commands::CI Install::InstallSummary summary; }; + static const std::string OPTION_EXCLUDE = "--exclude"; + + static const std::array CI_SETTINGS = {{ + {OPTION_EXCLUDE, "Comma separated list of ports to skip"}, + }}; + + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("ci x64-windows"), + 0, + SIZE_MAX, + {{}, CI_SETTINGS}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string OPTION_EXCLUDE = "--exclude"; - - static const std::string EXAMPLE = Help::create_example_string("ci x64-windows"); - - const ParsedArguments options = args.check_and_get_optional_command_arguments({}, {OPTION_EXCLUDE}); + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const std::vector exclusions = Strings::split(options.settings.at(OPTION_EXCLUDE), ","); const std::set exclusions_set(exclusions.cbegin(), exclusions.cend()); diff --git a/toolsrc/src/vcpkg/commands.contact.cpp b/toolsrc/src/vcpkg/commands.contact.cpp index 5694c1fa6..5d62faeea 100644 --- a/toolsrc/src/vcpkg/commands.contact.cpp +++ b/toolsrc/src/vcpkg/commands.contact.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace vcpkg::Commands::Contact { @@ -11,10 +12,17 @@ namespace vcpkg::Commands::Contact return S_EMAIL; } + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("contact"), + 0, + 0, + {}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args) { - args.check_exact_arg_count(0); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); System::println("Send an email to %s with any feedback.", email()); Checks::exit_success(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index 9d969ea28..15b10c7ea 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -13,7 +13,7 @@ namespace vcpkg::Commands Span> get_available_commands_type_a() { static std::vector> t = { - {"install", &Install::perform_and_exit}, + PackageNameAndFunction{"install", &Install::perform_and_exit}, {"ci", &CI::perform_and_exit}, {"remove", &Remove::perform_and_exit}, {"build", &Build::Command::perform_and_exit}, diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp index f1acacd14..c7183d257 100644 --- a/toolsrc/src/vcpkg/commands.create.cpp +++ b/toolsrc/src/vcpkg/commands.create.cpp @@ -8,13 +8,18 @@ namespace vcpkg::Commands::Create { + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string( + R"###(create zlib2 http://zlib.net/zlib1211.zip "zlib1211-2.zip")###"), + 2, + 3, + {}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string EXAMPLE = Help::create_example_string( - R"###(create zlib2 http://zlib.net/zlib1211.zip "zlib1211-2.zip")###"); - args.check_max_arg_count(3, EXAMPLE); - args.check_min_arg_count(2, EXAMPLE); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); const std::string port_name = args.command_arguments.at(0); const std::string url = args.command_arguments.at(1); diff --git a/toolsrc/src/vcpkg/commands.dependinfo.cpp b/toolsrc/src/vcpkg/commands.dependinfo.cpp index e5554f7e2..bb300d96e 100644 --- a/toolsrc/src/vcpkg/commands.dependinfo.cpp +++ b/toolsrc/src/vcpkg/commands.dependinfo.cpp @@ -9,11 +9,17 @@ namespace vcpkg::Commands::DependInfo { + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string(R"###(depend-info [pat])###"), + 0, + 1, + {}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string EXAMPLE = Help::create_example_string(R"###(depend-info [pat])###"); - args.check_max_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); std::vector> source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index bf618e256..e40e394fb 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -34,11 +34,6 @@ namespace vcpkg::Commands::Edit static const std::string OPTION_BUILDTREES = "--buildtrees"; - static const std::array SWITCHES = { - OPTION_BUILDTREES, - }; - static const std::array SETTINGS; - static std::vector valid_arguments(const VcpkgPaths& paths) { auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); @@ -47,12 +42,15 @@ namespace vcpkg::Commands::Edit [](auto&& pgh) -> std::string { return pgh->core_paragraph->name; }); } + static const std::array EDIT_SWITCHES = {{ + {OPTION_BUILDTREES, "Open editor into the port-specific buildtree subfolder"}, + }}; + const CommandStructure COMMAND_STRUCTURE = { - "edit zlib", + Help::create_example_string("edit zlib"), 1, 1, - SWITCHES, - SETTINGS, + {EDIT_SWITCHES, {}}, &valid_arguments, }; @@ -63,9 +61,7 @@ namespace vcpkg::Commands::Edit auto& fs = paths.get_filesystem(); - static const std::string EXAMPLE = Help::create_example_string("edit zlib"); - args.check_exact_arg_count(1, EXAMPLE); - const ParsedArguments options = args.check_and_get_optional_command_arguments({OPTION_BUILDTREES}, {}); + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const std::string port_name = args.command_arguments.at(0); const fs::path portpath = paths.ports / port_name; diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp index c0d26dac2..98b5aced9 100644 --- a/toolsrc/src/vcpkg/commands.env.cpp +++ b/toolsrc/src/vcpkg/commands.env.cpp @@ -7,11 +7,17 @@ namespace vcpkg::Commands::Env { + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("env --triplet x64-windows"), + 0, + 0, + {}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string EXAMPLE = Help::create_example_string(R"(env --triplet x64-windows)"); - args.check_exact_arg_count(0, EXAMPLE); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 51f6b9ad0..a5940ea1e 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -28,13 +28,18 @@ namespace vcpkg::Commands::Hash System::println(hash); } + const CommandStructure COMMAND_STRUCTURE = { + Strings::format("The argument should be a file path\n%s", + Help::create_example_string("hash boost_1_62_0.tar.bz2")), + 1, + 2, + {}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args) { - static const std::string EXAMPLE = Strings::format("The argument should be a file path\n%s", - Help::create_example_string("hash boost_1_62_0.tar.bz2")); - args.check_min_arg_count(1, EXAMPLE); - args.check_max_arg_count(2, EXAMPLE); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); if (args.command_arguments.size() == 1) { diff --git a/toolsrc/src/vcpkg/commands.import.cpp b/toolsrc/src/vcpkg/commands.import.cpp index 5e74b6d94..24394207b 100644 --- a/toolsrc/src/vcpkg/commands.import.cpp +++ b/toolsrc/src/vcpkg/commands.import.cpp @@ -92,12 +92,18 @@ namespace vcpkg::Commands::Import fs.write_contents(control_file_path, Strings::serialize(control_file_data)); } + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string( + R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)"), + 3, + 3, + {}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string EXAMPLE = Help::create_example_string( - R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)"); - args.check_exact_arg_count(3, EXAMPLE); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); const fs::path control_file_path(args.command_arguments[0]); const fs::path include_directory(args.command_arguments[1]); diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 604bd2c6e..31b9ec722 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -333,10 +333,6 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console static const std::string PROJECT = "project"; } - static const std::array INSTALL_SWITCHES; - - static const std::array INSTALL_SETTINGS; - static std::vector valid_arguments(const VcpkgPaths&) { return {Subcommand::INSTALL, Subcommand::REMOVE, Subcommand::PROJECT}; @@ -348,18 +344,13 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console INTEGRATE_COMMAND_HELPSTRING), 1, 1, - INSTALL_SWITCHES, - INSTALL_SETTINGS, + {}, &valid_arguments, }; void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string EXAMPLE = Strings::format("Commands:\n" - "%s", - INTEGRATE_COMMAND_HELPSTRING); - args.check_exact_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); #if defined(_WIN32) if (args.command_arguments[0] == Subcommand::INSTALL) diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp index 145d4c931..1f2387843 100644 --- a/toolsrc/src/vcpkg/commands.list.cpp +++ b/toolsrc/src/vcpkg/commands.list.cpp @@ -24,13 +24,23 @@ namespace vcpkg::Commands::List } } + static const std::array LIST_SWITCHES = {{ + {OPTION_FULLDESC, "Do not truncate long text"}, + }}; + + const CommandStructure COMMAND_STRUCTURE = { + Strings::format( + "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", + Help::create_example_string("list png")), + 0, + 1, + {LIST_SWITCHES, {}}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string EXAMPLE = Strings::format( - "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", - Help::create_example_string("list png")); - args.check_max_arg_count(1, EXAMPLE); - const ParsedArguments options = args.check_and_get_optional_command_arguments({OPTION_FULLDESC}, {}); + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const StatusParagraphs status_paragraphs = database_load_check(paths); std::vector installed_packages = get_installed_ports(status_paragraphs); diff --git a/toolsrc/src/vcpkg/commands.owns.cpp b/toolsrc/src/vcpkg/commands.owns.cpp index b2db966e1..52249187b 100644 --- a/toolsrc/src/vcpkg/commands.owns.cpp +++ b/toolsrc/src/vcpkg/commands.owns.cpp @@ -23,13 +23,18 @@ namespace vcpkg::Commands::Owns } } } + const CommandStructure COMMAND_STRUCTURE = { + Strings::format("The argument should be a pattern to search for. %s", + Help::create_example_string("owns zlib.dll")), + 1, + 1, + {}, + nullptr, + }; void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string EXAMPLE = Strings::format("The argument should be a pattern to search for. %s", - Help::create_example_string("owns zlib.dll")); - args.check_exact_arg_count(1, EXAMPLE); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); const StatusParagraphs status_db = database_load_check(paths); search_file(paths, args.command_arguments[0], status_db); diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp index 5008f3e8a..0277c8bdb 100644 --- a/toolsrc/src/vcpkg/commands.portsdiff.cpp +++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp @@ -114,13 +114,18 @@ namespace vcpkg::Commands::PortsDiff VCPKG_LINE_INFO, output.output == VALID_COMMIT_OUTPUT, "Invalid commit id %s", git_commit_id); } + const CommandStructure COMMAND_STRUCTURE = { + Strings::format("The argument should be a branch/tag/hash to checkout.\n%s", + Help::create_example_string("portsdiff mybranchname")), + 1, + 2, + {}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string EXAMPLE = Strings::format("The argument should be a branch/tag/hash to checkout.\n%s", - Help::create_example_string("portsdiff mybranchname")); - args.check_min_arg_count(1, EXAMPLE); - args.check_max_arg_count(2, EXAMPLE); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); const fs::path& git_exe = paths.get_git_exe(); diff --git a/toolsrc/src/vcpkg/commands.search.cpp b/toolsrc/src/vcpkg/commands.search.cpp index ad3046e6d..01291ddfb 100644 --- a/toolsrc/src/vcpkg/commands.search.cpp +++ b/toolsrc/src/vcpkg/commands.search.cpp @@ -79,14 +79,24 @@ namespace vcpkg::Commands::Search } } + static std::array SEARCH_SWITCHES = {{ + {OPTION_GRAPH, "Open editor into the port-specific buildtree subfolder"}, + {OPTION_FULLDESC, "Do not truncate long text"}, + }}; + + const CommandStructure COMMAND_STRUCTURE = { + Strings::format( + "The argument should be a substring to search for, or no argument to display all libraries.\n%s", + Help::create_example_string("search png")), + 0, + 1, + {SEARCH_SWITCHES, {}}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string EXAMPLE = Strings::format( - "The argument should be a substring to search for, or no argument to display all libraries.\n%s", - Help::create_example_string("search png")); - args.check_max_arg_count(1, EXAMPLE); - const ParsedArguments options = - args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC}, {}); + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const bool full_description = Util::Sets::contains(options.switches, OPTION_FULLDESC); auto source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); diff --git a/toolsrc/src/vcpkg/commands.version.cpp b/toolsrc/src/vcpkg/commands.version.cpp index e8756a77d..3f44cf1a2 100644 --- a/toolsrc/src/vcpkg/commands.version.cpp +++ b/toolsrc/src/vcpkg/commands.version.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #define STRINGIFY(...) #__VA_ARGS__ @@ -61,11 +62,17 @@ namespace vcpkg::Commands::Version } } } + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("version"), + 0, + 0, + {}, + nullptr, + }; void perform_and_exit(const VcpkgCmdArguments& args) { - args.check_exact_arg_count(0); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); System::println("Vcpkg package management program version %s\n" "\n" diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index eb4f5db3c..bbeecefed 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -257,51 +257,57 @@ namespace vcpkg::Export std::vector specs; }; + static const std::string OPTION_DRY_RUN = "--dry-run"; + static const std::string OPTION_RAW = "--raw"; + static const std::string OPTION_NUGET = "--nuget"; + static const std::string OPTION_IFW = "--ifw"; + static const std::string OPTION_ZIP = "--zip"; + static const std::string OPTION_SEVEN_ZIP = "--7zip"; + static const std::string OPTION_NUGET_ID = "--nuget-id"; + static const std::string OPTION_NUGET_VERSION = "--nuget-version"; + static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url"; + static const std::string OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path"; + static const std::string OPTION_IFW_REPOSITORY_DIR_PATH = "--ifw-repository-directory-path"; + static const std::string OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path"; + static const std::string OPTION_IFW_INSTALLER_FILE_PATH = "--ifw-installer-file-path"; + + static const std::array EXPORT_SWITCHES = {{ + {OPTION_DRY_RUN, "Do not actually export"}, + {OPTION_RAW, "Export to an uncompressed directory"}, + {OPTION_NUGET, "Export a NuGet package"}, + {OPTION_IFW, "Export to an IFW-based installer"}, + {OPTION_ZIP, "Export to a zip file"}, + {OPTION_SEVEN_ZIP, "Export to a 7zip (.7z) file"}, + }}; + static const std::array EXPORT_SETTINGS = {{ + {OPTION_NUGET_ID, "Specify the id for the exported NuGet package"}, + {OPTION_NUGET_VERSION, "Specify the version for the exported NuGet package"}, + {OPTION_IFW_REPOSITORY_URL, ""}, + {OPTION_IFW_PACKAGES_DIR_PATH, ""}, + {OPTION_IFW_REPOSITORY_DIR_PATH, ""}, + {OPTION_IFW_CONFIG_FILE_PATH, ""}, + {OPTION_IFW_INSTALLER_FILE_PATH, ""}, + }}; + + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("export zlib zlib:x64-windows boost --nuget"), + 0, + SIZE_MAX, + {EXPORT_SWITCHES, EXPORT_SETTINGS}, + nullptr, + }; + static ExportArguments handle_export_command_arguments(const VcpkgCmdArguments& args, const Triplet& default_triplet) { ExportArguments ret; - static const std::string OPTION_DRY_RUN = "--dry-run"; - static const std::string OPTION_RAW = "--raw"; - static const std::string OPTION_NUGET = "--nuget"; - static const std::string OPTION_IFW = "--ifw"; - static const std::string OPTION_ZIP = "--zip"; - static const std::string OPTION_SEVEN_ZIP = "--7zip"; - static const std::string OPTION_NUGET_ID = "--nuget-id"; - static const std::string OPTION_NUGET_VERSION = "--nuget-version"; - static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url"; - static const std::string OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path"; - static const std::string OPTION_IFW_REPOSITORY_DIR_PATH = "--ifw-repository-directory-path"; - static const std::string OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path"; - static const std::string OPTION_IFW_INSTALLER_FILE_PATH = "--ifw-installer-file-path"; + const auto options = args.parse_arguments(COMMAND_STRUCTURE); // input sanitization - static const std::string EXAMPLE = Help::create_example_string("export zlib zlib:x64-windows boost --nuget"); - args.check_min_arg_count(1, EXAMPLE); - ret.specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); + return Input::check_and_get_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text); }); - - const auto options = args.check_and_get_optional_command_arguments( - { - OPTION_DRY_RUN, - OPTION_RAW, - OPTION_NUGET, - OPTION_IFW, - OPTION_ZIP, - OPTION_SEVEN_ZIP, - }, - { - OPTION_NUGET_ID, - OPTION_NUGET_VERSION, - OPTION_IFW_REPOSITORY_URL, - OPTION_IFW_PACKAGES_DIR_PATH, - OPTION_IFW_REPOSITORY_DIR_PATH, - OPTION_IFW_CONFIG_FILE_PATH, - OPTION_IFW_INSTALLER_FILE_PATH, - }); ret.dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); ret.raw = options.switches.find(OPTION_RAW) != options.switches.cend(); ret.nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); @@ -313,7 +319,7 @@ namespace vcpkg::Export { System::println(System::Color::error, "Must provide at least one export type: --raw --nuget --ifw --zip --7zip"); - System::print(EXAMPLE); + System::print(COMMAND_STRUCTURE.example_text); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index 8783833f2..5d4cf99a4 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -91,10 +91,17 @@ namespace vcpkg::Help System::println(create_example_string(command_and_arguments)); } + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("help"), + 0, + 1, + {}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - args.check_max_arg_count(1); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); if (args.command_arguments.empty()) { diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index b1f722d59..20ffd3164 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -535,13 +535,13 @@ namespace vcpkg::Install static const std::string OPTION_RECURSE = "--recurse"; static const std::string OPTION_KEEP_GOING = "--keep-going"; - static const std::array INSTALL_SWITCHES = { - OPTION_DRY_RUN, - OPTION_USE_HEAD_VERSION, - OPTION_NO_DOWNLOADS, - OPTION_RECURSE, - OPTION_KEEP_GOING, - }; + static const std::array INSTALL_SWITCHES = {{ + {OPTION_DRY_RUN, "Do not actually build or install"}, + {OPTION_USE_HEAD_VERSION, "Install the libraries on the command line using the latest upstream sources"}, + {OPTION_NO_DOWNLOADS, "Do not download new sources"}, + {OPTION_RECURSE, "Allow removal of packages as part of installation"}, + {OPTION_KEEP_GOING, "Continue installing packages on failure"}, + }}; static const std::array INSTALL_SETTINGS; std::vector get_all_port_names(const VcpkgPaths& paths) @@ -553,22 +553,20 @@ namespace vcpkg::Install } const CommandStructure COMMAND_STRUCTURE = { - "install zlib zlib:x64-windows curl boost", + Help::create_example_string("install zlib zlib:x64-windows curl boost"), 1, SIZE_MAX, - INSTALL_SWITCHES, - INSTALL_SETTINGS, + {INSTALL_SWITCHES, {}}, &get_all_port_names, }; void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { // input sanitization - static const std::string EXAMPLE = Help::create_example_string("install zlib zlib:x64-windows curl boost"); - args.check_min_arg_count(1, EXAMPLE); + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_full_package_spec(arg, default_triplet, EXAMPLE); + return Input::check_and_get_full_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text); }); for (auto&& spec : specs) @@ -581,8 +579,6 @@ namespace vcpkg::Install } } - const ParsedArguments options = args.check_and_get_optional_command_arguments( - {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE, OPTION_KEEP_GOING}, {}); const bool dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN); const bool use_head_version = Util::Sets::contains(options.switches, (OPTION_USE_HEAD_VERSION)); const bool no_downloads = Util::Sets::contains(options.switches, (OPTION_NO_DOWNLOADS)); diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 156f23003..7f40fb16e 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -169,14 +169,13 @@ namespace vcpkg::Remove static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_OUTDATED = "--outdated"; - static const std::array SWITCHES = { - OPTION_PURGE, - OPTION_NO_PURGE, - OPTION_RECURSE, - OPTION_DRY_RUN, - OPTION_OUTDATED, - }; - static const std::array SETTINGS; + static const std::array SWITCHES = {{ + {OPTION_PURGE, "Remove the cached copy of the package (default)"}, + {OPTION_NO_PURGE, "Do not remove the cached copy of the package"}, + {OPTION_RECURSE, "Allow removal of packages not explicitly specified on the command line"}, + {OPTION_DRY_RUN, "Print the packages to be removed, but do not remove them"}, + {OPTION_OUTDATED, "Select all packages with versions that do not match the portfiles"}, + }}; static std::vector valid_arguments(const VcpkgPaths& paths) { @@ -187,25 +186,26 @@ namespace vcpkg::Remove } const CommandStructure COMMAND_STRUCTURE = { - "remove zlib zlib:x64-windows curl boost", - 1, + Help::create_example_string("remove zlib zlib:x64-windows curl boost"), + 0, SIZE_MAX, - SWITCHES, - SETTINGS, + {SWITCHES, {}}, &valid_arguments, }; void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string EXAMPLE = Help::create_example_string("remove zlib zlib:x64-windows curl boost"); - const ParsedArguments options = args.check_and_get_optional_command_arguments( - {OPTION_PURGE, OPTION_NO_PURGE, OPTION_RECURSE, OPTION_DRY_RUN, OPTION_OUTDATED}, {}); + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); StatusParagraphs status_db = database_load_check(paths); std::vector specs; if (Util::Sets::contains(options.switches, OPTION_OUTDATED)) { - args.check_exact_arg_count(0, EXAMPLE); + if (args.command_arguments.size() != 0) + { + System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'"); + Checks::exit_fail(VCPKG_LINE_INFO); + } specs = Util::fmap(Update::find_outdated_packages(paths, status_db), [](auto&& outdated) { return outdated.spec; }); @@ -217,9 +217,13 @@ namespace vcpkg::Remove } else { - args.check_min_arg_count(1, EXAMPLE); + if (args.command_arguments.size() < 1) + { + System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'"); + Checks::exit_fail(VCPKG_LINE_INFO); + } specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); + return Input::check_and_get_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text); }); for (auto&& spec : specs) @@ -231,7 +235,7 @@ namespace vcpkg::Remove if (purge_was_passed && no_purge_was_passed) { System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); - System::print(EXAMPLE); + System::print(COMMAND_STRUCTURE.example_text); Checks::exit_fail(VCPKG_LINE_INFO); } const Purge purge = to_purge(purge_was_passed || !no_purge_was_passed); diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp index 7d565251e..61a3f89c5 100644 --- a/toolsrc/src/vcpkg/update.cpp +++ b/toolsrc/src/vcpkg/update.cpp @@ -38,10 +38,17 @@ namespace vcpkg::Update return output; } + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("update"), + 0, + 0, + {}, + nullptr, + }; + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - args.check_exact_arg_count(0); - args.check_and_get_optional_command_arguments({}, {}); + args.parse_arguments(COMMAND_STRUCTURE); System::println("Using local portfile versions. To update the local portfiles, use `git pull`."); const StatusParagraphs status_db = database_load_check(paths); diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp index 209f6a3f2..35cdbc12e 100644 --- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp +++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp @@ -45,11 +45,8 @@ namespace vcpkg option_field = new_setting; } -#if defined(_WIN32) - VcpkgCmdArguments VcpkgCmdArguments::create_from_command_line(const int argc, const wchar_t* const* const argv) -#else - VcpkgCmdArguments VcpkgCmdArguments::create_from_command_line(const int argc, const char* const* const argv) -#endif + VcpkgCmdArguments VcpkgCmdArguments::create_from_command_line(const int argc, + const CommandLineCharType* const* const argv) { std::vector v; for (int i = 1; i < argc; ++i) @@ -158,46 +155,83 @@ namespace vcpkg return args; } - ParsedArguments VcpkgCmdArguments::check_and_get_optional_command_arguments( - const std::vector& valid_switches, const std::vector& valid_settings) const + ParsedArguments VcpkgCmdArguments::parse_arguments(const CommandStructure& command_structure) const { bool failed = false; ParsedArguments output; + const size_t actual_arg_count = command_arguments.size(); + + if (command_structure.minimum_arity == command_structure.maximum_arity) + { + if (actual_arg_count != command_structure.minimum_arity) + { + System::println(System::Color::error, + "Error: '%s' requires %u arguments, but %u were provided.", + this->command, + command_structure.minimum_arity, + actual_arg_count); + failed = true; + } + } + else + { + if (actual_arg_count < command_structure.minimum_arity) + { + System::println(System::Color::error, + "Error: '%s' requires at least %u arguments, but %u were provided", + this->command, + command_structure.minimum_arity, + actual_arg_count); + failed = true; + } + if (actual_arg_count > command_structure.maximum_arity) + { + System::println(System::Color::error, + "Error: '%s' requires at most %u arguments, but %u were provided", + this->command, + command_structure.maximum_arity, + actual_arg_count); + failed = true; + } + } + auto options_copy = this->optional_command_arguments; - for (const std::string& option : valid_switches) + for (auto&& option : command_structure.options.switches) { - const auto it = options_copy.find(option); + const auto it = options_copy.find(option.name); if (it != options_copy.end()) { if (it->second.has_value()) { // Having a string value indicates it was passed like '--a=xyz' - System::println(System::Color::error, "The option '%s' does not accept an argument.", option); + System::println( + System::Color::error, "Error: The option '%s' does not accept an argument.", option.name); failed = true; } else { - output.switches.insert(option); + output.switches.insert(option.name); options_copy.erase(it); } } } - for (const std::string& option : valid_settings) + for (auto&& option : command_structure.options.settings) { - const auto it = options_copy.find(option); + const auto it = options_copy.find(option.name); if (it != options_copy.end()) { if (!it->second.has_value()) { // Not having a string value indicates it was passed like '--a' - System::println(System::Color::error, "The option '%s' must be passed an argument.", option); + System::println( + System::Color::error, "Error: The option '%s' must be passed an argument.", option.name); failed = true; } else { - output.settings.emplace(option, it->second.value_or_exit(VCPKG_LINE_INFO)); + output.settings.emplace(option.name, it->second.value_or_exit(VCPKG_LINE_INFO)); options_copy.erase(it); } } @@ -210,83 +244,32 @@ namespace vcpkg { System::println(" %s", option.first); } - System::println("\nValid options are:", this->command); - for (auto&& option : valid_switches) + System::println(); + failed = true; + } + + if (failed) + { + if (!command_structure.example_text.empty()) { - System::println(" %s", option); + System::println("%s", command_structure.example_text); } - for (auto&& option : valid_settings) + + System::println("Options:", this->command); + for (auto&& option : command_structure.options.switches) { - System::println(" %s=...", option); + System::println(" %-40s %s", option.name, option.short_help_text); + } + for (auto&& option : command_structure.options.settings) + { + System::println(" %-40s %s", (option.name + "=..."), option.short_help_text); } System::println(" --triplet "); System::println(" --vcpkg-root "); Checks::exit_fail(VCPKG_LINE_INFO); } - if (failed) Checks::exit_fail(VCPKG_LINE_INFO); return output; } - - void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count) const - { - return check_max_arg_count(expected_arg_count, ""); - } - - void VcpkgCmdArguments::check_min_arg_count(const size_t expected_arg_count) const - { - return check_min_arg_count(expected_arg_count, ""); - } - - void VcpkgCmdArguments::check_exact_arg_count(const size_t expected_arg_count) const - { - return check_exact_arg_count(expected_arg_count, ""); - } - - void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count, const std::string& example_text) const - { - const size_t actual_arg_count = command_arguments.size(); - if (actual_arg_count > expected_arg_count) - { - System::println(System::Color::error, - "Error: `%s` requires at most %u arguments, but %u were provided", - this->command, - expected_arg_count, - actual_arg_count); - System::print(example_text); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - - void VcpkgCmdArguments::check_min_arg_count(const size_t expected_arg_count, const std::string& example_text) const - { - const size_t actual_arg_count = command_arguments.size(); - if (actual_arg_count < expected_arg_count) - { - System::println(System::Color::error, - "Error: `%s` requires at least %u arguments, but %u were provided", - this->command, - expected_arg_count, - actual_arg_count); - System::print(example_text); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - - void VcpkgCmdArguments::check_exact_arg_count(const size_t expected_arg_count, - const std::string& example_text) const - { - const size_t actual_arg_count = command_arguments.size(); - if (actual_arg_count != expected_arg_count) - { - System::println(System::Color::error, - "Error: `%s` requires %u arguments, but %u were provided", - this->command, - expected_arg_count, - actual_arg_count); - System::print(example_text); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } } -- cgit v1.2.3 From 2feea0828ba94d2a365e8825fe799ed12acc6e6c Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 2 Nov 2017 18:17:21 -0700 Subject: [vcpkg] Improve `vcpkg help` -- now has per-command help! --- toolsrc/src/vcpkg/export.cpp | 3 +- toolsrc/src/vcpkg/help.cpp | 116 ++++++++++++++++++-------------- toolsrc/src/vcpkg/vcpkgcmdarguments.cpp | 40 ++++++----- 3 files changed, 91 insertions(+), 68 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index bbeecefed..625dff8b1 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -289,7 +290,7 @@ namespace vcpkg::Export {OPTION_IFW_INSTALLER_FILE_PATH, ""}, }}; - const CommandStructure COMMAND_STRUCTURE = { + const CommandStructure vcpkg::Export::COMMAND_STRUCTURE = { Help::create_example_string("export zlib zlib:x64-windows boost --nuget"), 0, SIZE_MAX, diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index 5d4cf99a4..c83f0277b 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -2,15 +2,68 @@ #include #include +#include +#include +#include +#include namespace vcpkg::Help { - void help_topics() + struct Topic + { + using topic_function = void (*)(const VcpkgPaths& paths); + + constexpr Topic(CStringView n, topic_function fn) : name(n), print(fn) {} + + CStringView name; + topic_function print; + }; + + template + static void command_topic_fn(const VcpkgPaths&) + { + display_usage(S); + } + + static void integrate_topic_fn(const VcpkgPaths&) + { + System::print("Commands:\n" + "%s", + Commands::Integrate::INTEGRATE_COMMAND_HELPSTRING); + } + + static void help_topics(const VcpkgPaths&); + + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("help"), + 0, + 1, + {}, + nullptr, + }; + + static constexpr std::array topics = {{ + {"create", command_topic_fn}, + {"edit", command_topic_fn}, + {"env", command_topic_fn}, + {"export", command_topic_fn}, + {"help", command_topic_fn}, + {"install", command_topic_fn}, + {"integrate", integrate_topic_fn}, + {"list", command_topic_fn}, + {"owns", command_topic_fn}, + {"remove", command_topic_fn}, + {"search", command_topic_fn}, + {"topics", help_topics}, + }}; + + static void help_topics(const VcpkgPaths&) { System::println("Available help topics:\n" " triplet\n" - " integrate\n" - " export"); + " integrate" + "%s", + Strings::join("", topics, [](const Topic& topic) { return std::string("\n ") + topic.name; })); } void help_topic_valid_triplet(const VcpkgPaths& paths) @@ -22,21 +75,6 @@ namespace vcpkg::Help } } - void help_topic_export() - { - System::println("Summary:\n" - " vcpkg export [options] ...\n" - "\n" - "Options:\n" - " --7zip Export to a 7zip (.7z) file\n" - " --dry-run Do not actually export\n" - " --nuget Export a NuGet package\n" - " --nuget-id= Specify the id for the exported NuGet package\n" - " --nuget-version= Specify the version for the exported NuGet package\n" - " --raw Export to an uncompressed directory\n" - " --zip Export to a zip file"); - } - void print_usage() { System::println( @@ -86,19 +124,6 @@ namespace vcpkg::Help return cs; } - void print_example(const std::string& command_and_arguments) - { - System::println(create_example_string(command_and_arguments)); - } - - const CommandStructure COMMAND_STRUCTURE = { - Help::create_example_string("help"), - 0, - 1, - {}, - nullptr, - }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { args.parse_arguments(COMMAND_STRUCTURE); @@ -112,27 +137,18 @@ namespace vcpkg::Help if (topic == "triplet" || topic == "triplets" || topic == "triple") { help_topic_valid_triplet(paths); + Checks::exit_success(VCPKG_LINE_INFO); } - else if (topic == "export") - { - help_topic_export(); - } - else if (topic == "integrate") - { - System::print("Commands:\n" - "%s", - Commands::Integrate::INTEGRATE_COMMAND_HELPSTRING); - } - else if (topic == "topics") - { - help_topics(); - } - else + + auto it_topic = Util::find_if(topics, [&](const Topic& t) { return t.name == topic; }); + if (it_topic != topics.end()) { - System::println(System::Color::error, "Error: unknown topic %s", topic); - help_topics(); - Checks::exit_fail(VCPKG_LINE_INFO); + it_topic->print(paths); + Checks::exit_success(VCPKG_LINE_INFO); } - Checks::exit_success(VCPKG_LINE_INFO); + + System::println(System::Color::error, "Error: unknown topic %s", topic); + help_topics(paths); + Checks::exit_fail(VCPKG_LINE_INFO); } } diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp index 35cdbc12e..671a89892 100644 --- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp +++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp @@ -250,26 +250,32 @@ namespace vcpkg if (failed) { - if (!command_structure.example_text.empty()) - { - System::println("%s", command_structure.example_text); - } - - System::println("Options:", this->command); - for (auto&& option : command_structure.options.switches) - { - System::println(" %-40s %s", option.name, option.short_help_text); - } - for (auto&& option : command_structure.options.settings) - { - System::println(" %-40s %s", (option.name + "=..."), option.short_help_text); - } - System::println(" --triplet "); - System::println(" --vcpkg-root "); - + display_usage(command_structure); Checks::exit_fail(VCPKG_LINE_INFO); } return output; } + + void display_usage(const CommandStructure& command_structure) + { + if (!command_structure.example_text.empty()) + { + System::println("%s", command_structure.example_text); + } + + System::println("Options:"); + for (auto&& option : command_structure.options.switches) + { + System::println(" %-40s %s", option.name, option.short_help_text); + } + for (auto&& option : command_structure.options.settings) + { + System::println(" %-40s %s", (option.name + "=..."), option.short_help_text); + } + System::println(" %-40s %s", "--triplet ", "Set the default triplet for unqualified packages"); + System::println(" %-40s %s", + "--vcpkg-root ", + "Specify the vcpkg directory to use instead of current directory or tool directory"); + } } -- cgit v1.2.3 From 115cd5f69f1060d3662355a3276948cd77b7fa31 Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Fri, 3 Nov 2017 20:31:13 +0300 Subject: [vcpkg-help-export-ifw] Add settings description --- toolsrc/src/vcpkg/export.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 625dff8b1..9b86863eb 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -283,11 +283,11 @@ namespace vcpkg::Export static const std::array EXPORT_SETTINGS = {{ {OPTION_NUGET_ID, "Specify the id for the exported NuGet package"}, {OPTION_NUGET_VERSION, "Specify the version for the exported NuGet package"}, - {OPTION_IFW_REPOSITORY_URL, ""}, - {OPTION_IFW_PACKAGES_DIR_PATH, ""}, - {OPTION_IFW_REPOSITORY_DIR_PATH, ""}, - {OPTION_IFW_CONFIG_FILE_PATH, ""}, - {OPTION_IFW_INSTALLER_FILE_PATH, ""}, + {OPTION_IFW_REPOSITORY_URL, "Specify the remote repository URL for the online installer"}, + {OPTION_IFW_PACKAGES_DIR_PATH, "Specify the temporary directory path for the repacked packages"}, + {OPTION_IFW_REPOSITORY_DIR_PATH, "Specify the directory path for the exported repository"}, + {OPTION_IFW_CONFIG_FILE_PATH, "Specify the temporary file path for the installer configuration"}, + {OPTION_IFW_INSTALLER_FILE_PATH, "Specify the file path for the exported installer"}, }}; const CommandStructure vcpkg::Export::COMMAND_STRUCTURE = { -- cgit v1.2.3 From 57934e5bbe485e904b47d49b3609d4000a4ca952 Mon Sep 17 00:00:00 2001 From: bjornpiltz Date: Thu, 2 Nov 2017 10:48:52 +0100 Subject: Print error message when there is a syntax error in triplet file As it is now vcpkg fails silently (actually, it outputs two empty lines). --- toolsrc/src/vcpkg/build.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 8b4654aa8..ca0712a06 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -489,7 +489,7 @@ namespace vcpkg::Build {"CMAKE_TRIPLET_FILE", triplet_file_path}, }); const auto ec_data = System::cmd_execute_and_capture_output(cmd_launch_cmake); - Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0); + Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, ec_data.output); const std::vector lines = Strings::split(ec_data.output, "\n"); -- cgit v1.2.3 From 3b90bc07ce6fb8639fbb0a142bdbbd458e85462a Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 3 Nov 2017 18:25:54 -0700 Subject: [cmake] Update to 3.9.5 (was 3.9.4) --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 5e43ee4c7..c17b029c0 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -125,10 +125,10 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array EXPECTED_VERSION = {3, 9, 4}; + static constexpr std::array EXPECTED_VERSION = {3, 9, 5}; static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - const fs::path downloaded_copy = downloads_folder / "cmake-3.9.4-win32-x86" / "bin" / "cmake.exe"; + const fs::path downloaded_copy = downloads_folder / "cmake-3.9.5-win32-x86" / "bin" / "cmake.exe"; const std::vector from_path = Files::find_from_PATH("cmake"); std::vector candidate_paths; -- cgit v1.2.3 From 61c0a337842b50d4b914893030193f3a1faaedf4 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 4 Nov 2017 16:40:11 -0700 Subject: Improve error messages around calling powershell scripts --- toolsrc/src/vcpkg/base/system.cpp | 28 +++++++++++++++++++++-- toolsrc/src/vcpkg/vcpkgpaths.cpp | 47 ++++++++++++++++----------------------- 2 files changed, 45 insertions(+), 30 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index a1bc9daf6..47096ed63 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -269,7 +270,9 @@ namespace vcpkg::System #endif } - ExitCodeAndOutput powershell_execute_and_capture_output(const fs::path& script_path, const CStringView args) + std::string powershell_execute_and_capture_output(const std::string& title, + const fs::path& script_path, + const CStringView args) { // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned const std::string cmd = Strings::format( @@ -277,6 +280,27 @@ namespace vcpkg::System auto rc = System::cmd_execute_and_capture_output(cmd); + if (rc.exit_code) + { + System::println(Color::error, + "%s\n" + "Could not run:\n" + " '%s'\n" + "Error message was:\n" + " %s", + title, + script_path.generic_string(), + rc.output); + + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_property("error", "powershell script failed"); + locked_metrics->track_property("title", title); + } + + Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); + } + // Remove newline from all output. // Powershell returns newlines when it hits the column count of the console. // For example, this is 80 in cmd on Windows 7. If the expected output is longer than 80 lines, we get @@ -285,7 +309,7 @@ namespace vcpkg::System // and then strip all newlines here. rc.output = Strings::replace_all(std::move(rc.output), "\n", ""); - return rc; + return rc.output; } void println() { putchar('\n'); } diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index c17b029c0..a553f4199 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -91,26 +91,13 @@ namespace vcpkg tool_name, version_as_string); const fs::path script = scripts_folder / "fetchDependency.ps1"; - const System::ExitCodeAndOutput rc = - System::powershell_execute_and_capture_output(script, Strings::format("-Dependency %s", tool_name)); - if (rc.exit_code) - { - System::println(System::Color::error, - "Launching powershell failed or was denied when trying to fetch %s version %s.\n" - "(No sufficient installed version was found)", - tool_name, - version_as_string); - { - auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_property("error", "powershell install failed"); - locked_metrics->track_property("dependency", tool_name); - } - Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); - } + const std::string title = "Fetching %s version %s (No sufficient installed version was found)"; + const std::string output = + System::powershell_execute_and_capture_output(title, script, Strings::format("-Dependency %s", tool_name)); - const std::vector dependency_path = keep_data_lines(rc.output); + const std::vector dependency_path = keep_data_lines(output); Checks::check_exit( - VCPKG_LINE_INFO, dependency_path.size() == 1, "Expected dependency path, but got %s", rc.output); + VCPKG_LINE_INFO, dependency_path.size() == 1, "Expected dependency path, but got %s", output); const fs::path actual_downloaded_path = Strings::trim(std::string{dependency_path.at(0)}); std::error_code ec; @@ -344,17 +331,21 @@ namespace vcpkg static std::vector get_visual_studio_instances(const VcpkgPaths& paths) { const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; - const System::ExitCodeAndOutput ec_data = System::powershell_execute_and_capture_output(script); - Checks::check_exit( - VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect Visual Studio instances"); + const std::string output = + System::powershell_execute_and_capture_output("Detecting Visual Studio instances", script); - const std::vector instances_as_strings = keep_data_lines(ec_data.output); + const std::vector instances_as_strings = keep_data_lines(output); Checks::check_exit(VCPKG_LINE_INFO, !instances_as_strings.empty(), - "Could not detect any Visual Studio instances. Powershell returned: %s\n", - ec_data.output); - - std::vector output; + "Could not detect any Visual Studio instances.\n" + "Powershell script:\n" + " %s\n" + "returned:\n" + "%s", + script.generic_string(), + output); + + std::vector instances; for (const std::string& instance_as_string : instances_as_strings) { const std::vector split = Strings::split(instance_as_string, "::"); @@ -364,10 +355,10 @@ namespace vcpkg "Expected: PreferenceWeight::ReleaseType::Version::PathToVisualStudio\n" "Actual : %s\n", instance_as_string); - output.push_back({split.at(3), split.at(2), split.at(1), split.at(0)}); + instances.push_back({split.at(3), split.at(2), split.at(1), split.at(0)}); } - return output; + return instances; } static std::vector find_toolset_instances(const VcpkgPaths& paths) -- cgit v1.2.3 From eb99b0c705b78e6c278e0a3782a8324e9d304e69 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 6 Nov 2017 14:22:10 -0800 Subject: [vcpkg] Add tests for remove plans. --- toolsrc/src/tests.installplan.cpp | 493 --------------------------------- toolsrc/src/tests.plan.cpp | 561 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 561 insertions(+), 493 deletions(-) delete mode 100644 toolsrc/src/tests.installplan.cpp create mode 100644 toolsrc/src/tests.plan.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.installplan.cpp b/toolsrc/src/tests.installplan.cpp deleted file mode 100644 index 129926317..000000000 --- a/toolsrc/src/tests.installplan.cpp +++ /dev/null @@ -1,493 +0,0 @@ -#include -#include - -#include - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -using namespace vcpkg; - -namespace Microsoft::VisualStudio::CppUnitTestFramework -{ - template<> - inline std::wstring ToString(const vcpkg::Dependencies::InstallPlanType& t) - { - switch (t) - { - case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; - case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; - case Dependencies::InstallPlanType::INSTALL: return L"INSTALL"; - case Dependencies::InstallPlanType::EXCLUDED: return L"EXCLUDED"; - case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; - default: return ToString(static_cast(t)); - } - } - - template<> - inline std::wstring ToString(const vcpkg::Dependencies::RequestType& t) - { - switch (t) - { - case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED"; - case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED"; - case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN"; - default: return ToString(static_cast(t)); - } - } -} - -namespace UnitTest1 -{ - class InstallPlanTests : public TestClass - { - static std::unique_ptr make_control_file( - const char* name, - const char* depends, - const std::vector>& features = {}) - { - using Pgh = std::unordered_map; - std::vector scf_pghs; - scf_pghs.push_back(Pgh{ - {"Source", name}, - {"Version", "0"}, - {"Build-Depends", depends}, - }); - for (auto&& feature : features) - { - scf_pghs.push_back(Pgh{ - {"Feature", feature.first}, - {"Description", "feature"}, - {"Build-Depends", feature.second}, - }); - } - auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(scf_pghs)); - Assert::IsTrue(m_pgh.has_value()); - return std::move(*m_pgh.get()); - } - - static void features_check(Dependencies::AnyAction* install_action, - std::string pkg_name, - std::vector vec, - const Triplet& triplet = Triplet::X86_WINDOWS) - { - const auto& plan = install_action->install_plan.value_or_exit(VCPKG_LINE_INFO); - const auto& feature_list = plan.feature_list; - - Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); - - Assert::AreEqual(pkg_name.c_str(), - (*plan.any_paragraph.source_control_file.get())->core_paragraph->name.c_str()); - Assert::AreEqual(size_t(vec.size()), feature_list.size()); - - for (auto&& feature_name : vec) - { - if (feature_name == "core" || feature_name == "") - { - Assert::IsTrue(Util::find(feature_list, "core") != feature_list.end() || - Util::find(feature_list, "") != feature_list.end()); - continue; - } - Assert::IsTrue(Util::find(feature_list, feature_name) != feature_list.end()); - } - } - - static void remove_plan_check(Dependencies::AnyAction* remove_action, - std::string pkg_name, - const Triplet& triplet = Triplet::X86_WINDOWS) - { - const auto& plan = remove_action->remove_plan.value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); - Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); - } - - static std::unique_ptr make_status_pgh(const char* name, const char* depends = "") - { - using Pgh = std::unordered_map; - return std::make_unique(Pgh{{"Package", name}, - {"Version", "1"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", depends}, - {"Status", "install ok installed"}}); - } - static std::unique_ptr make_status_feature_pgh(const char* name, - const char* feature, - const char* depends = "") - { - using Pgh = std::unordered_map; - return std::make_unique(Pgh{{"Package", name}, - {"Version", "1"}, - {"Feature", feature}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", depends}, - {"Status", "install ok installed"}}); - } - struct PackageSpecMap - { - std::unordered_map map; - Triplet triplet; - PackageSpecMap(const Triplet& t) { triplet = t; } - - PackageSpec emplace(const char* name, - const char* depends = "", - const std::vector>& features = {}) - { - return emplace(std::move(*make_control_file(name, depends, features))); - } - PackageSpec emplace(vcpkg::SourceControlFile&& scf) - { - auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph->name, triplet); - Assert::IsTrue(spec.has_value()); - map.emplace(scf.core_paragraph->name, std::move(scf)); - return PackageSpec{*spec.get()}; - } - }; - - TEST_METHOD(basic_install_scheme) - { - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.emplace("a", "b"); - auto spec_b = spec_map.emplace("b", "c"); - auto spec_c = spec_map.emplace("c"); - - Dependencies::MapPortFile map_port(spec_map.map); - auto install_plan = - Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(3), install_plan.size()); - Assert::AreEqual("c", install_plan[0].spec.name().c_str()); - Assert::AreEqual("b", install_plan[1].spec.name().c_str()); - Assert::AreEqual("a", install_plan[2].spec.name().c_str()); - } - - TEST_METHOD(multiple_install_scheme) - { - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.emplace("a", "d"); - auto spec_b = spec_map.emplace("b", "d, e"); - auto spec_c = spec_map.emplace("c", "e, h"); - auto spec_d = spec_map.emplace("d", "f, g, h"); - auto spec_e = spec_map.emplace("e", "g"); - auto spec_f = spec_map.emplace("f"); - auto spec_g = spec_map.emplace("g"); - auto spec_h = spec_map.emplace("h"); - - Dependencies::MapPortFile map_port(spec_map.map); - auto install_plan = Dependencies::create_install_plan( - map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); - - auto iterator_pos = [&](const PackageSpec& spec) -> int { - auto it = std::find_if( - install_plan.begin(), install_plan.end(), [&](auto& action) { return action.spec == spec; }); - Assert::IsTrue(it != install_plan.end()); - return (int)(it - install_plan.begin()); - }; - - int a_pos = iterator_pos(spec_a), b_pos = iterator_pos(spec_b), c_pos = iterator_pos(spec_c), - d_pos = iterator_pos(spec_d), e_pos = iterator_pos(spec_e), f_pos = iterator_pos(spec_f), - g_pos = iterator_pos(spec_g), h_pos = iterator_pos(spec_h); - - Assert::IsTrue(a_pos > d_pos); - Assert::IsTrue(b_pos > e_pos); - Assert::IsTrue(b_pos > d_pos); - Assert::IsTrue(c_pos > e_pos); - Assert::IsTrue(c_pos > h_pos); - Assert::IsTrue(d_pos > f_pos); - Assert::IsTrue(d_pos > g_pos); - Assert::IsTrue(d_pos > h_pos); - Assert::IsTrue(e_pos > g_pos); - } - - TEST_METHOD(existing_package_scheme) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.emplace("a")}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(1), install_plan.size()); - auto p = install_plan[0].install_plan.get(); - Assert::IsNotNull(p); - Assert::AreEqual("a", p->spec.name().c_str()); - Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type); - Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p->request_type); - } - - TEST_METHOD(user_requested_package_scheme) - { - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b")}; - auto spec_b = FullPackageSpec{spec_map.emplace("b")}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(2), install_plan.size()); - auto p = install_plan[0].install_plan.get(); - Assert::IsNotNull(p); - Assert::AreEqual("b", p->spec.name().c_str()); - Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type); - Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type); - - auto p2 = install_plan[1].install_plan.get(); - Assert::IsNotNull(p2); - Assert::AreEqual("a", p2->spec.name().c_str()); - Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type); - Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p2->request_type); - } - - TEST_METHOD(long_install_scheme) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("j", "k")); - status_paragraphs.push_back(make_status_pgh("k")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = spec_map.emplace("a", "b, c, d, e, f, g, h, j, k"); - auto spec_b = spec_map.emplace("b", "c, d, e, f, g, h, j, k"); - auto spec_c = spec_map.emplace("c", "d, e, f, g, h, j, k"); - auto spec_d = spec_map.emplace("d", "e, f, g, h, j, k"); - auto spec_e = spec_map.emplace("e", "f, g, h, j, k"); - auto spec_f = spec_map.emplace("f", "g, h, j, k"); - auto spec_g = spec_map.emplace("g", "h, j, k"); - auto spec_h = spec_map.emplace("h", "j, k"); - auto spec_j = spec_map.emplace("j", "k"); - auto spec_k = spec_map.emplace("k"); - - Dependencies::MapPortFile map_port(spec_map.map); - auto install_plan = - Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(8), install_plan.size()); - Assert::AreEqual("h", install_plan[0].spec.name().c_str()); - Assert::AreEqual("g", install_plan[1].spec.name().c_str()); - Assert::AreEqual("f", install_plan[2].spec.name().c_str()); - Assert::AreEqual("e", install_plan[3].spec.name().c_str()); - Assert::AreEqual("d", install_plan[4].spec.name().c_str()); - Assert::AreEqual("c", install_plan[5].spec.name().c_str()); - Assert::AreEqual("b", install_plan[6].spec.name().c_str()); - Assert::AreEqual("a", install_plan[7].spec.name().c_str()); - } - - TEST_METHOD(basic_feature_test_1) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a", "b, b[b1]")); - status_paragraphs.push_back(make_status_pgh("b")); - status_paragraphs.push_back(make_status_feature_pgh("b", "b1")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(4), install_plan.size()); - remove_plan_check(&install_plan[0], "a"); - remove_plan_check(&install_plan[1], "b"); - features_check(&install_plan[2], "b", {"b1", "core", "b1"}); - features_check(&install_plan[3], "a", {"a1", "core"}); - } - - TEST_METHOD(basic_feature_test_2) - { - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(2), install_plan.size()); - features_check(&install_plan[0], "b", {"b1", "b2", "core"}); - features_check(&install_plan[1], "a", {"a1", "core"}); - } - - TEST_METHOD(basic_feature_test_3) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_c, spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(4), install_plan.size()); - remove_plan_check(&install_plan[0], "a"); - features_check(&install_plan[1], "b", {"core"}); - features_check(&install_plan[2], "a", {"a1", "core"}); - features_check(&install_plan[3], "c", {"core"}); - } - - TEST_METHOD(basic_feature_test_4) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.push_back(make_status_feature_pgh("a", "a1", "")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}})}; - auto spec_b = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_c}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(1), install_plan.size()); - features_check(&install_plan[0], "c", {"core"}); - } - - TEST_METHOD(basic_feature_test_5) - { - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = - FullPackageSpec{spec_map.emplace("a", "", {{"a1", "b[b1]"}, {"a2", "b[b2]"}, {"a3", "a[a2]"}}), {"a3"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}})}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(2), install_plan.size()); - features_check(&install_plan[0], "b", {"core", "b2"}); - features_check(&install_plan[1], "a", {"core", "a3", "a2"}); - } - - TEST_METHOD(basic_feature_test_6) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("b")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[core]"), {"core"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a, spec_b}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(3), install_plan.size()); - remove_plan_check(&install_plan[0], "b"); - features_check(&install_plan[1], "b", {"core", "b1"}); - features_check(&install_plan[2], "a", {"core"}); - } - - TEST_METHOD(basic_feature_test_7) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("x", "b")); - status_paragraphs.push_back(make_status_pgh("b")); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = FullPackageSpec{spec_map.emplace("a")}; - auto spec_x = FullPackageSpec{spec_map.emplace("x", "a"), {"core"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_b}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(5), install_plan.size()); - remove_plan_check(&install_plan[0], "x"); - remove_plan_check(&install_plan[1], "b"); - - // TODO: order here may change but A < X, and B anywhere - features_check(&install_plan[2], "b", {"core", "b1"}); - features_check(&install_plan[3], "a", {"core"}); - features_check(&install_plan[4], "x", {"core"}); - } - - TEST_METHOD(basic_feature_test_8) - { - std::vector> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.back()->package.spec = - PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); - - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; - auto spec_b_64 = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - spec_map.triplet = Triplet::X86_WINDOWS; - auto spec_a_86 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; - auto spec_b_86 = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c_86 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({spec_c_64, spec_a_86, spec_a_64, spec_c_86}), - StatusParagraphs(std::move(status_paragraphs))); - - remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); - remove_plan_check(&install_plan[1], "a"); - features_check(&install_plan[2], "b", {"core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[3], "a", {"a1", "core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[4], "c", {"core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[5], "b", {"core"}); - features_check(&install_plan[6], "a", {"a1", "core"}); - features_check(&install_plan[7], "c", {"core"}); - } - - TEST_METHOD(install_all_features_test) - { - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}), {"core"}}; - - auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); - Assert::IsTrue(install_specs.has_value()); - if (!install_specs.has_value()) return; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::IsTrue(install_plan.size() == 1); - features_check(&install_plan[0], "a", {"0", "1", "core"}, Triplet::X64_WINDOWS); - } - }; -} diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp new file mode 100644 index 000000000..d62178bdf --- /dev/null +++ b/toolsrc/src/tests.plan.cpp @@ -0,0 +1,561 @@ +#include +#include + +#include + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +using namespace vcpkg; + +namespace Microsoft::VisualStudio::CppUnitTestFramework +{ + template<> + inline std::wstring ToString(const vcpkg::Dependencies::InstallPlanType& t) + { + switch (t) + { + case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; + case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; + case Dependencies::InstallPlanType::INSTALL: return L"INSTALL"; + case Dependencies::InstallPlanType::EXCLUDED: return L"EXCLUDED"; + case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; + default: return ToString(static_cast(t)); + } + } + + template<> + inline std::wstring ToString(const vcpkg::Dependencies::RequestType& t) + { + switch (t) + { + case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED"; + case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED"; + case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN"; + default: return ToString(static_cast(t)); + } + } +} + +namespace UnitTest1 +{ + static std::unique_ptr make_control_file( + const char* name, + const char* depends, + const std::vector>& features = {}) + { + using Pgh = std::unordered_map; + std::vector scf_pghs; + scf_pghs.push_back(Pgh{ + { "Source", name }, + { "Version", "0" }, + { "Build-Depends", depends }, + }); + for (auto&& feature : features) + { + scf_pghs.push_back(Pgh{ + { "Feature", feature.first }, + { "Description", "feature" }, + { "Build-Depends", feature.second }, + }); + } + auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(scf_pghs)); + Assert::IsTrue(m_pgh.has_value()); + return std::move(*m_pgh.get()); + } + + static void features_check(Dependencies::AnyAction* install_action, + std::string pkg_name, + std::vector vec, + const Triplet& triplet = Triplet::X86_WINDOWS) + { + const auto& plan = install_action->install_plan.value_or_exit(VCPKG_LINE_INFO); + const auto& feature_list = plan.feature_list; + + Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); + + Assert::AreEqual(pkg_name.c_str(), + (*plan.any_paragraph.source_control_file.get())->core_paragraph->name.c_str()); + Assert::AreEqual(size_t(vec.size()), feature_list.size()); + + for (auto&& feature_name : vec) + { + if (feature_name == "core" || feature_name == "") + { + Assert::IsTrue(Util::find(feature_list, "core") != feature_list.end() || + Util::find(feature_list, "") != feature_list.end()); + continue; + } + Assert::IsTrue(Util::find(feature_list, feature_name) != feature_list.end()); + } + } + + static void remove_plan_check(Dependencies::AnyAction* remove_action, + std::string pkg_name, + const Triplet& triplet = Triplet::X86_WINDOWS) + { + const auto& plan = remove_action->remove_plan.value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); + Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); + } + + static std::unique_ptr make_status_pgh(const char* name, const char* depends = "") + { + using Pgh = std::unordered_map; + return std::make_unique(Pgh{ { "Package", name }, + { "Version", "1" }, + { "Architecture", "x86-windows" }, + { "Multi-Arch", "same" }, + { "Depends", depends }, + { "Status", "install ok installed" } }); + } + static std::unique_ptr make_status_feature_pgh(const char* name, + const char* feature, + const char* depends = "") + { + using Pgh = std::unordered_map; + return std::make_unique(Pgh{ { "Package", name }, + { "Version", "1" }, + { "Feature", feature }, + { "Architecture", "x86-windows" }, + { "Multi-Arch", "same" }, + { "Depends", depends }, + { "Status", "install ok installed" } }); + } + struct PackageSpecMap + { + std::unordered_map map; + Triplet triplet; + PackageSpecMap(const Triplet& t) { triplet = t; } + + PackageSpec emplace(const char* name, + const char* depends = "", + const std::vector>& features = {}) + { + return emplace(std::move(*make_control_file(name, depends, features))); + } + PackageSpec emplace(vcpkg::SourceControlFile&& scf) + { + auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph->name, triplet); + Assert::IsTrue(spec.has_value()); + map.emplace(scf.core_paragraph->name, std::move(scf)); + return PackageSpec{ *spec.get() }; + } + }; + + class InstallPlanTests : public TestClass + { + TEST_METHOD(basic_install_scheme) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "b"); + auto spec_b = spec_map.emplace("b", "c"); + auto spec_c = spec_map.emplace("c"); + + Dependencies::MapPortFile map_port(spec_map.map); + auto install_plan = + Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(3), install_plan.size()); + Assert::AreEqual("c", install_plan[0].spec.name().c_str()); + Assert::AreEqual("b", install_plan[1].spec.name().c_str()); + Assert::AreEqual("a", install_plan[2].spec.name().c_str()); + } + + TEST_METHOD(multiple_install_scheme) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "d"); + auto spec_b = spec_map.emplace("b", "d, e"); + auto spec_c = spec_map.emplace("c", "e, h"); + auto spec_d = spec_map.emplace("d", "f, g, h"); + auto spec_e = spec_map.emplace("e", "g"); + auto spec_f = spec_map.emplace("f"); + auto spec_g = spec_map.emplace("g"); + auto spec_h = spec_map.emplace("h"); + + Dependencies::MapPortFile map_port(spec_map.map); + auto install_plan = Dependencies::create_install_plan( + map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); + + auto iterator_pos = [&](const PackageSpec& spec) -> int { + auto it = std::find_if( + install_plan.begin(), install_plan.end(), [&](auto& action) { return action.spec == spec; }); + Assert::IsTrue(it != install_plan.end()); + return (int)(it - install_plan.begin()); + }; + + int a_pos = iterator_pos(spec_a), b_pos = iterator_pos(spec_b), c_pos = iterator_pos(spec_c), + d_pos = iterator_pos(spec_d), e_pos = iterator_pos(spec_e), f_pos = iterator_pos(spec_f), + g_pos = iterator_pos(spec_g), h_pos = iterator_pos(spec_h); + + Assert::IsTrue(a_pos > d_pos); + Assert::IsTrue(b_pos > e_pos); + Assert::IsTrue(b_pos > d_pos); + Assert::IsTrue(c_pos > e_pos); + Assert::IsTrue(c_pos > h_pos); + Assert::IsTrue(d_pos > f_pos); + Assert::IsTrue(d_pos > g_pos); + Assert::IsTrue(d_pos > h_pos); + Assert::IsTrue(e_pos > g_pos); + } + + TEST_METHOD(existing_package_scheme) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.emplace("a")}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(1), install_plan.size()); + auto p = install_plan[0].install_plan.get(); + Assert::IsNotNull(p); + Assert::AreEqual("a", p->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type); + Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p->request_type); + } + + TEST_METHOD(user_requested_package_scheme) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b")}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(2), install_plan.size()); + auto p = install_plan[0].install_plan.get(); + Assert::IsNotNull(p); + Assert::AreEqual("b", p->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type); + Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type); + + auto p2 = install_plan[1].install_plan.get(); + Assert::IsNotNull(p2); + Assert::AreEqual("a", p2->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type); + Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p2->request_type); + } + + TEST_METHOD(long_install_scheme) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("j", "k")); + status_paragraphs.push_back(make_status_pgh("k")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = spec_map.emplace("a", "b, c, d, e, f, g, h, j, k"); + auto spec_b = spec_map.emplace("b", "c, d, e, f, g, h, j, k"); + auto spec_c = spec_map.emplace("c", "d, e, f, g, h, j, k"); + auto spec_d = spec_map.emplace("d", "e, f, g, h, j, k"); + auto spec_e = spec_map.emplace("e", "f, g, h, j, k"); + auto spec_f = spec_map.emplace("f", "g, h, j, k"); + auto spec_g = spec_map.emplace("g", "h, j, k"); + auto spec_h = spec_map.emplace("h", "j, k"); + auto spec_j = spec_map.emplace("j", "k"); + auto spec_k = spec_map.emplace("k"); + + Dependencies::MapPortFile map_port(spec_map.map); + auto install_plan = + Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(8), install_plan.size()); + Assert::AreEqual("h", install_plan[0].spec.name().c_str()); + Assert::AreEqual("g", install_plan[1].spec.name().c_str()); + Assert::AreEqual("f", install_plan[2].spec.name().c_str()); + Assert::AreEqual("e", install_plan[3].spec.name().c_str()); + Assert::AreEqual("d", install_plan[4].spec.name().c_str()); + Assert::AreEqual("c", install_plan[5].spec.name().c_str()); + Assert::AreEqual("b", install_plan[6].spec.name().c_str()); + Assert::AreEqual("a", install_plan[7].spec.name().c_str()); + } + + TEST_METHOD(basic_feature_test_1) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a", "b, b[b1]")); + status_paragraphs.push_back(make_status_pgh("b")); + status_paragraphs.push_back(make_status_feature_pgh("b", "b1")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(4), install_plan.size()); + remove_plan_check(&install_plan[0], "a"); + remove_plan_check(&install_plan[1], "b"); + features_check(&install_plan[2], "b", {"b1", "core", "b1"}); + features_check(&install_plan[3], "a", {"a1", "core"}); + } + + TEST_METHOD(basic_feature_test_2) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(2), install_plan.size()); + features_check(&install_plan[0], "b", {"b1", "b2", "core"}); + features_check(&install_plan[1], "a", {"a1", "core"}); + } + + TEST_METHOD(basic_feature_test_3) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_c, spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(4), install_plan.size()); + remove_plan_check(&install_plan[0], "a"); + features_check(&install_plan[1], "b", {"core"}); + features_check(&install_plan[2], "a", {"a1", "core"}); + features_check(&install_plan[3], "c", {"core"}); + } + + TEST_METHOD(basic_feature_test_4) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.push_back(make_status_feature_pgh("a", "a1", "")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}})}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_c}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(1), install_plan.size()); + features_check(&install_plan[0], "c", {"core"}); + } + + TEST_METHOD(basic_feature_test_5) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = + FullPackageSpec{spec_map.emplace("a", "", {{"a1", "b[b1]"}, {"a2", "b[b2]"}, {"a3", "a[a2]"}}), {"a3"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}})}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(2), install_plan.size()); + features_check(&install_plan[0], "b", {"core", "b2"}); + features_check(&install_plan[1], "a", {"core", "a3", "a2"}); + } + + TEST_METHOD(basic_feature_test_6) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("b")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[core]"), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a, spec_b}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(3), install_plan.size()); + remove_plan_check(&install_plan[0], "b"); + features_check(&install_plan[1], "b", {"core", "b1"}); + features_check(&install_plan[2], "a", {"core"}); + } + + TEST_METHOD(basic_feature_test_7) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("x", "b")); + status_paragraphs.push_back(make_status_pgh("b")); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = FullPackageSpec{spec_map.emplace("a")}; + auto spec_x = FullPackageSpec{spec_map.emplace("x", "a"), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_b}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(5), install_plan.size()); + remove_plan_check(&install_plan[0], "x"); + remove_plan_check(&install_plan[1], "b"); + + // TODO: order here may change but A < X, and B anywhere + features_check(&install_plan[2], "b", {"core", "b1"}); + features_check(&install_plan[3], "a", {"core"}); + features_check(&install_plan[4], "x", {"core"}); + } + + TEST_METHOD(basic_feature_test_8) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.spec = + PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + spec_map.triplet = Triplet::X86_WINDOWS; + auto spec_a_86 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b_86 = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c_86 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({spec_c_64, spec_a_86, spec_a_64, spec_c_86}), + StatusParagraphs(std::move(status_paragraphs))); + + remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); + remove_plan_check(&install_plan[1], "a"); + features_check(&install_plan[2], "b", {"core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[3], "a", {"a1", "core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[4], "c", {"core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[5], "b", {"core"}); + features_check(&install_plan[6], "a", {"a1", "core"}); + features_check(&install_plan[7], "c", {"core"}); + } + + TEST_METHOD(install_all_features_test) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}), {"core"}}; + + auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); + Assert::IsTrue(install_specs.has_value()); + if (!install_specs.has_value()) return; + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::IsTrue(install_plan.size() == 1); + features_check(&install_plan[0], "a", {"0", "1", "core"}, Triplet::X64_WINDOWS); + } + }; + + static PackageSpec unsafe_pspec(std::string name, Triplet t = Triplet::X86_WINDOWS) + { + auto m_ret = PackageSpec::from_name_and_triplet(name, t); + Assert::IsTrue(m_ret.has_value()); + return m_ret.value_or_exit(VCPKG_LINE_INFO); + } + + class RemovePlanTests : public TestClass + { + TEST_METHOD(basic_remove_scheme) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan({ unsafe_pspec("a") }, status_db); + + Assert::AreEqual(size_t(1), remove_plan.size()); + Assert::AreEqual("a", remove_plan[0].spec.name().c_str()); + } + + TEST_METHOD(recurse_remove_scheme) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b", "a")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan({ unsafe_pspec("a") }, status_db); + + Assert::AreEqual(size_t(2), remove_plan.size()); + Assert::AreEqual("b", remove_plan[0].spec.name().c_str()); + Assert::AreEqual("a", remove_plan[1].spec.name().c_str()); + } + + TEST_METHOD(features_depend_remove_scheme) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b")); + pghs.push_back(make_status_feature_pgh("b", "0", "a")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan({ unsafe_pspec("a") }, status_db); + + Assert::AreEqual(size_t(2), remove_plan.size()); + Assert::AreEqual("b", remove_plan[0].spec.name().c_str()); + Assert::AreEqual("a", remove_plan[1].spec.name().c_str()); + } + + TEST_METHOD(features_depend_remove_scheme_once_removed) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("expat")); + pghs.push_back(make_status_pgh("vtk", "expat")); + pghs.push_back(make_status_pgh("opencv")); + pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan({ unsafe_pspec("expat") }, status_db); + + Assert::AreEqual(size_t(3), remove_plan.size()); + Assert::AreEqual("opencv", remove_plan[0].spec.name().c_str()); + Assert::AreEqual("vtk", remove_plan[1].spec.name().c_str()); + Assert::AreEqual("expat", remove_plan[2].spec.name().c_str()); + } + }; +} -- cgit v1.2.3 From e2575e8c961e90b5dd35ef37c0b241b6cdb2914a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 6 Nov 2017 14:29:57 -0800 Subject: [vcpkg] Reformat tests.plan.cpp and add :x64 version of test --- toolsrc/src/tests.plan.cpp | 97 +++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 39 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index d62178bdf..9cf3cfd8e 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -39,23 +39,21 @@ namespace Microsoft::VisualStudio::CppUnitTestFramework namespace UnitTest1 { static std::unique_ptr make_control_file( - const char* name, - const char* depends, - const std::vector>& features = {}) + const char* name, const char* depends, const std::vector>& features = {}) { using Pgh = std::unordered_map; std::vector scf_pghs; scf_pghs.push_back(Pgh{ - { "Source", name }, - { "Version", "0" }, - { "Build-Depends", depends }, + {"Source", name}, + {"Version", "0"}, + {"Build-Depends", depends}, }); for (auto&& feature : features) { scf_pghs.push_back(Pgh{ - { "Feature", feature.first }, - { "Description", "feature" }, - { "Build-Depends", feature.second }, + {"Feature", feature.first}, + {"Description", "feature"}, + {"Build-Depends", feature.second}, }); } auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(scf_pghs)); @@ -64,9 +62,9 @@ namespace UnitTest1 } static void features_check(Dependencies::AnyAction* install_action, - std::string pkg_name, - std::vector vec, - const Triplet& triplet = Triplet::X86_WINDOWS) + std::string pkg_name, + std::vector vec, + const Triplet& triplet = Triplet::X86_WINDOWS) { const auto& plan = install_action->install_plan.value_or_exit(VCPKG_LINE_INFO); const auto& feature_list = plan.feature_list; @@ -74,7 +72,7 @@ namespace UnitTest1 Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); Assert::AreEqual(pkg_name.c_str(), - (*plan.any_paragraph.source_control_file.get())->core_paragraph->name.c_str()); + (*plan.any_paragraph.source_control_file.get())->core_paragraph->name.c_str()); Assert::AreEqual(size_t(vec.size()), feature_list.size()); for (auto&& feature_name : vec) @@ -82,7 +80,7 @@ namespace UnitTest1 if (feature_name == "core" || feature_name == "") { Assert::IsTrue(Util::find(feature_list, "core") != feature_list.end() || - Util::find(feature_list, "") != feature_list.end()); + Util::find(feature_list, "") != feature_list.end()); continue; } Assert::IsTrue(Util::find(feature_list, feature_name) != feature_list.end()); @@ -90,36 +88,39 @@ namespace UnitTest1 } static void remove_plan_check(Dependencies::AnyAction* remove_action, - std::string pkg_name, - const Triplet& triplet = Triplet::X86_WINDOWS) + std::string pkg_name, + const Triplet& triplet = Triplet::X86_WINDOWS) { const auto& plan = remove_action->remove_plan.value_or_exit(VCPKG_LINE_INFO); Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); } - static std::unique_ptr make_status_pgh(const char* name, const char* depends = "") + static std::unique_ptr make_status_pgh(const char* name, + const char* depends = "", + const char* triplet = "x86-windows") { using Pgh = std::unordered_map; - return std::make_unique(Pgh{ { "Package", name }, - { "Version", "1" }, - { "Architecture", "x86-windows" }, - { "Multi-Arch", "same" }, - { "Depends", depends }, - { "Status", "install ok installed" } }); + return std::make_unique(Pgh{{"Package", name}, + {"Version", "1"}, + {"Architecture", triplet}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Status", "install ok installed"}}); } static std::unique_ptr make_status_feature_pgh(const char* name, - const char* feature, - const char* depends = "") + const char* feature, + const char* depends = "", + const char* triplet = "x86-windows") { using Pgh = std::unordered_map; - return std::make_unique(Pgh{ { "Package", name }, - { "Version", "1" }, - { "Feature", feature }, - { "Architecture", "x86-windows" }, - { "Multi-Arch", "same" }, - { "Depends", depends }, - { "Status", "install ok installed" } }); + return std::make_unique(Pgh{{"Package", name}, + {"Version", "1"}, + {"Feature", feature}, + {"Architecture", triplet}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Status", "install ok installed"}}); } struct PackageSpecMap { @@ -128,8 +129,8 @@ namespace UnitTest1 PackageSpecMap(const Triplet& t) { triplet = t; } PackageSpec emplace(const char* name, - const char* depends = "", - const std::vector>& features = {}) + const char* depends = "", + const std::vector>& features = {}) { return emplace(std::move(*make_control_file(name, depends, features))); } @@ -138,7 +139,7 @@ namespace UnitTest1 auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph->name, triplet); Assert::IsTrue(spec.has_value()); map.emplace(scf.core_paragraph->name, std::move(scf)); - return PackageSpec{ *spec.get() }; + return PackageSpec{*spec.get()}; } }; @@ -506,7 +507,7 @@ namespace UnitTest1 pghs.push_back(make_status_pgh("a")); StatusParagraphs status_db(std::move(pghs)); - auto remove_plan = Dependencies::create_remove_plan({ unsafe_pspec("a") }, status_db); + auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); Assert::AreEqual(size_t(1), remove_plan.size()); Assert::AreEqual("a", remove_plan[0].spec.name().c_str()); @@ -519,7 +520,7 @@ namespace UnitTest1 pghs.push_back(make_status_pgh("b", "a")); StatusParagraphs status_db(std::move(pghs)); - auto remove_plan = Dependencies::create_remove_plan({ unsafe_pspec("a") }, status_db); + auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); Assert::AreEqual(size_t(2), remove_plan.size()); Assert::AreEqual("b", remove_plan[0].spec.name().c_str()); @@ -534,7 +535,7 @@ namespace UnitTest1 pghs.push_back(make_status_feature_pgh("b", "0", "a")); StatusParagraphs status_db(std::move(pghs)); - auto remove_plan = Dependencies::create_remove_plan({ unsafe_pspec("a") }, status_db); + auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); Assert::AreEqual(size_t(2), remove_plan.size()); Assert::AreEqual("b", remove_plan[0].spec.name().c_str()); @@ -550,7 +551,25 @@ namespace UnitTest1 pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk")); StatusParagraphs status_db(std::move(pghs)); - auto remove_plan = Dependencies::create_remove_plan({ unsafe_pspec("expat") }, status_db); + auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("expat")}, status_db); + + Assert::AreEqual(size_t(3), remove_plan.size()); + Assert::AreEqual("opencv", remove_plan[0].spec.name().c_str()); + Assert::AreEqual("vtk", remove_plan[1].spec.name().c_str()); + Assert::AreEqual("expat", remove_plan[2].spec.name().c_str()); + } + + TEST_METHOD(features_depend_remove_scheme_once_removed_x64) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("expat", "", "x64")); + pghs.push_back(make_status_pgh("vtk", "expat", "x64")); + pghs.push_back(make_status_pgh("opencv", "", "x64")); + pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk", "x64")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan( + {unsafe_pspec("expat", Triplet::from_canonical_name("x64"))}, status_db); Assert::AreEqual(size_t(3), remove_plan.size()); Assert::AreEqual("opencv", remove_plan[0].spec.name().c_str()); -- cgit v1.2.3 From 192087563d08d659c219700358803c748a71f72e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 9 Nov 2017 21:42:03 -0800 Subject: Join declaration and assignment. Add const --- toolsrc/src/vcpkg/build.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index ca0712a06..b0ca3501b 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -317,9 +317,8 @@ namespace vcpkg::Build {"FEATURES", features}, }); - std::string command; const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); - command = Strings::format(R"(%s && %s)", cmd_set_environment, cmd_launch_cmake); + const std::string command = Strings::format(R"(%s && %s)", cmd_set_environment, cmd_launch_cmake); const auto timer = Chrono::ElapsedTime::create_started(); -- cgit v1.2.3 From ecd21d6cb429a91076c0fc1bb3c6d4af447343e8 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 11 Nov 2017 19:47:56 -0800 Subject: [vcpkg-tests] Use PCH. [vcpkg-update] Fix feature packages with update command. Fixes #2003. --- toolsrc/src/tests.arguments.cpp | 3 +- toolsrc/src/tests.dependencies.cpp | 4 +- toolsrc/src/tests.packagespec.cpp | 24 +-------- toolsrc/src/tests.paragraph.cpp | 6 +-- toolsrc/src/tests.pch.cpp | 1 + toolsrc/src/tests.plan.cpp | 60 +-------------------- toolsrc/src/tests.statusparagraphs.cpp | 7 +-- toolsrc/src/tests.update.cpp | 96 ++++++++++++++++++++++++++++++++++ toolsrc/src/tests.utils.cpp | 62 ++++++++++++++++++++++ toolsrc/src/vcpkg/remove.cpp | 7 ++- toolsrc/src/vcpkg/update.cpp | 17 ++++-- toolsrc/src/vcpkg/versiont.cpp | 13 +++-- 12 files changed, 192 insertions(+), 108 deletions(-) create mode 100644 toolsrc/src/tests.pch.cpp create mode 100644 toolsrc/src/tests.update.cpp create mode 100644 toolsrc/src/tests.utils.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.arguments.cpp b/toolsrc/src/tests.arguments.cpp index 0f082222d..c87281fa8 100644 --- a/toolsrc/src/tests.arguments.cpp +++ b/toolsrc/src/tests.arguments.cpp @@ -1,5 +1,4 @@ -#include -#include +#include "tests.pch.h" #pragma comment(lib, "version") #pragma comment(lib, "winhttp") diff --git a/toolsrc/src/tests.dependencies.cpp b/toolsrc/src/tests.dependencies.cpp index 3f6e0dd10..f82fad4e4 100644 --- a/toolsrc/src/tests.dependencies.cpp +++ b/toolsrc/src/tests.dependencies.cpp @@ -1,6 +1,4 @@ -#include -#include -#include +#include "tests.pch.h" #pragma comment(lib, "version") #pragma comment(lib, "winhttp") diff --git a/toolsrc/src/tests.packagespec.cpp b/toolsrc/src/tests.packagespec.cpp index 25498a799..32ad81227 100644 --- a/toolsrc/src/tests.packagespec.cpp +++ b/toolsrc/src/tests.packagespec.cpp @@ -1,32 +1,12 @@ -#include -#include -#include +#include "tests.pch.h" -#include -#include +#include #pragma comment(lib, "version") #pragma comment(lib, "winhttp") using namespace Microsoft::VisualStudio::CppUnitTestFramework; -namespace Microsoft::VisualStudio::CppUnitTestFramework -{ - template<> - inline std::wstring ToString(const vcpkg::PackageSpecParseResult& t) - { - return ToString(static_cast(t)); - } - - template<> - inline std::wstring ToString(const vcpkg::PackageSpec& t) - { - return ToString(t.to_string()); - } -} - -namespace Strings = vcpkg::Strings; - namespace UnitTest1 { using namespace vcpkg; diff --git a/toolsrc/src/tests.paragraph.cpp b/toolsrc/src/tests.paragraph.cpp index 13052610f..9cddd7bdb 100644 --- a/toolsrc/src/tests.paragraph.cpp +++ b/toolsrc/src/tests.paragraph.cpp @@ -1,8 +1,4 @@ -#include -#include -#include - -#include +#include "tests.pch.h" #pragma comment(lib, "version") #pragma comment(lib, "winhttp") diff --git a/toolsrc/src/tests.pch.cpp b/toolsrc/src/tests.pch.cpp new file mode 100644 index 000000000..bdddab76a --- /dev/null +++ b/toolsrc/src/tests.pch.cpp @@ -0,0 +1 @@ +#include "tests.pch.h" diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 9cf3cfd8e..122a4ffef 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -1,41 +1,11 @@ -#include -#include +#include "tests.pch.h" -#include +#include using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace vcpkg; -namespace Microsoft::VisualStudio::CppUnitTestFramework -{ - template<> - inline std::wstring ToString(const vcpkg::Dependencies::InstallPlanType& t) - { - switch (t) - { - case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; - case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; - case Dependencies::InstallPlanType::INSTALL: return L"INSTALL"; - case Dependencies::InstallPlanType::EXCLUDED: return L"EXCLUDED"; - case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; - default: return ToString(static_cast(t)); - } - } - - template<> - inline std::wstring ToString(const vcpkg::Dependencies::RequestType& t) - { - switch (t) - { - case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED"; - case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED"; - case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN"; - default: return ToString(static_cast(t)); - } - } -} - namespace UnitTest1 { static std::unique_ptr make_control_file( @@ -96,32 +66,6 @@ namespace UnitTest1 Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); } - static std::unique_ptr make_status_pgh(const char* name, - const char* depends = "", - const char* triplet = "x86-windows") - { - using Pgh = std::unordered_map; - return std::make_unique(Pgh{{"Package", name}, - {"Version", "1"}, - {"Architecture", triplet}, - {"Multi-Arch", "same"}, - {"Depends", depends}, - {"Status", "install ok installed"}}); - } - static std::unique_ptr make_status_feature_pgh(const char* name, - const char* feature, - const char* depends = "", - const char* triplet = "x86-windows") - { - using Pgh = std::unordered_map; - return std::make_unique(Pgh{{"Package", name}, - {"Version", "1"}, - {"Feature", feature}, - {"Architecture", triplet}, - {"Multi-Arch", "same"}, - {"Depends", depends}, - {"Status", "install ok installed"}}); - } struct PackageSpecMap { std::unordered_map map; diff --git a/toolsrc/src/tests.statusparagraphs.cpp b/toolsrc/src/tests.statusparagraphs.cpp index 4cc1130b1..ed6eaa764 100644 --- a/toolsrc/src/tests.statusparagraphs.cpp +++ b/toolsrc/src/tests.statusparagraphs.cpp @@ -1,9 +1,4 @@ -#include - -#include -#include -#include -#include +#include "tests.pch.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; diff --git a/toolsrc/src/tests.update.cpp b/toolsrc/src/tests.update.cpp new file mode 100644 index 000000000..06ae797f4 --- /dev/null +++ b/toolsrc/src/tests.update.cpp @@ -0,0 +1,96 @@ +#include "tests.pch.h" + +#include + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +using namespace vcpkg; +using namespace vcpkg::Update; + +namespace UnitTest1 +{ + class UpdateTests : public TestClass + { + TEST_METHOD(find_outdated_packages_basic) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.version = "2"; + + StatusParagraphs status_db(std::move(status_paragraphs)); + + std::map port_versions; + port_versions["a"] = VersionT("0"); + + auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + &OutdatedPackage::compare_by_name); + + Assert::AreEqual(size_t(1), pkgs.size()); + Assert::AreEqual("2", pkgs[0].version_diff.left.to_string().c_str()); + Assert::AreEqual("0", pkgs[0].version_diff.right.to_string().c_str()); + } + + TEST_METHOD(find_outdated_packages_features) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.version = "2"; + + status_paragraphs.push_back(make_status_feature_pgh("a", "b")); + status_paragraphs.back()->package.version = "2"; + + StatusParagraphs status_db(std::move(status_paragraphs)); + + std::map port_versions; + port_versions["a"] = VersionT("0"); + + auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + &OutdatedPackage::compare_by_name); + + Assert::AreEqual(size_t(1), pkgs.size()); + Assert::AreEqual("2", pkgs[0].version_diff.left.to_string().c_str()); + Assert::AreEqual("0", pkgs[0].version_diff.right.to_string().c_str()); + } + + TEST_METHOD(find_outdated_packages_features_2) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.version = "2"; + + status_paragraphs.push_back(make_status_feature_pgh("a", "b")); + status_paragraphs.back()->package.version = "0"; + status_paragraphs.back()->state = InstallState::NOT_INSTALLED; + status_paragraphs.back()->want = Want::PURGE; + + StatusParagraphs status_db(std::move(status_paragraphs)); + + std::map port_versions; + port_versions["a"] = VersionT("0"); + + auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + &OutdatedPackage::compare_by_name); + + Assert::AreEqual(size_t(1), pkgs.size()); + Assert::AreEqual("2", pkgs[0].version_diff.left.to_string().c_str()); + Assert::AreEqual("0", pkgs[0].version_diff.right.to_string().c_str()); + } + + TEST_METHOD(find_outdated_packages_none) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.version = "2"; + + StatusParagraphs status_db(std::move(status_paragraphs)); + + std::map port_versions; + port_versions["a"] = VersionT("2"); + + auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + &OutdatedPackage::compare_by_name); + + Assert::AreEqual(size_t(0), pkgs.size()); + } + }; +} diff --git a/toolsrc/src/tests.utils.cpp b/toolsrc/src/tests.utils.cpp new file mode 100644 index 000000000..b9fb51a59 --- /dev/null +++ b/toolsrc/src/tests.utils.cpp @@ -0,0 +1,62 @@ +#include "tests.pch.h" + +#include "tests.utils.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; +using namespace vcpkg; + +namespace Microsoft::VisualStudio::CppUnitTestFramework +{ + std::wstring ToString(const vcpkg::Dependencies::InstallPlanType& t) + { + switch (t) + { + case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; + case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; + case Dependencies::InstallPlanType::INSTALL: return L"INSTALL"; + case Dependencies::InstallPlanType::EXCLUDED: return L"EXCLUDED"; + case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; + default: return ToString(static_cast(t)); + } + } + + std::wstring ToString(const vcpkg::Dependencies::RequestType& t) + { + switch (t) + { + case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED"; + case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED"; + case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN"; + default: return ToString(static_cast(t)); + } + } + + std::wstring ToString(const vcpkg::PackageSpecParseResult& t) { return ToString(static_cast(t)); } + + std::wstring ToString(const vcpkg::PackageSpec& t) { return ToString(t.to_string()); } +} + +std::unique_ptr make_status_pgh(const char* name, const char* depends, const char* triplet) +{ + using Pgh = std::unordered_map; + return std::make_unique(Pgh{{"Package", name}, + {"Version", "1"}, + {"Architecture", triplet}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Status", "install ok installed"}}); +} +std::unique_ptr make_status_feature_pgh(const char* name, + const char* feature, + const char* depends, + const char* triplet) +{ + using Pgh = std::unordered_map; + return std::make_unique(Pgh{{"Package", name}, + {"Version", "1"}, + {"Feature", feature}, + {"Architecture", triplet}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Status", "install ok installed"}}); +} diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 7f40fb16e..8ae0bc881 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -206,8 +207,10 @@ namespace vcpkg::Remove System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'"); Checks::exit_fail(VCPKG_LINE_INFO); } - specs = Util::fmap(Update::find_outdated_packages(paths, status_db), - [](auto&& outdated) { return outdated.spec; }); + specs = Util::fmap( + Update::find_outdated_packages( + Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports), status_db), + [](auto&& outdated) { return outdated.spec; }); if (specs.empty()) { diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp index 61a3f89c5..29baef91e 100644 --- a/toolsrc/src/vcpkg/update.cpp +++ b/toolsrc/src/vcpkg/update.cpp @@ -14,15 +14,20 @@ namespace vcpkg::Update return left.spec.name() < right.spec.name(); } - std::vector find_outdated_packages(const VcpkgPaths& paths, const StatusParagraphs& status_db) + std::vector find_outdated_packages(const std::map& src_names_to_versions, + const StatusParagraphs& status_db) { - const std::map src_names_to_versions = - Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports); const std::vector installed_packages = get_installed_ports(status_db); std::vector output; for (const StatusParagraph* pgh : installed_packages) { + if (!pgh->package.feature.empty()) + { + // Skip feature packages; only consider master packages for needing updates. + continue; + } + const auto it = src_names_to_versions.find(pgh->package.spec.name()); if (it == src_names_to_versions.end()) { @@ -53,8 +58,10 @@ namespace vcpkg::Update const StatusParagraphs status_db = database_load_check(paths); - const auto outdated_packages = - SortedVector(find_outdated_packages(paths, status_db), &OutdatedPackage::compare_by_name); + const auto outdated_packages = SortedVector( + find_outdated_packages(Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports), + status_db), + &OutdatedPackage::compare_by_name); if (outdated_packages.empty()) { diff --git a/toolsrc/src/vcpkg/versiont.cpp b/toolsrc/src/vcpkg/versiont.cpp index 1c52d674a..91f7e23ef 100644 --- a/toolsrc/src/vcpkg/versiont.cpp +++ b/toolsrc/src/vcpkg/versiont.cpp @@ -7,13 +7,16 @@ namespace vcpkg { VersionT::VersionT() : value("0.0.0") {} VersionT::VersionT(const std::string& value) : value(value) {} - std::string VersionT::to_string() const { return value; } - bool operator==(const VersionT& left, const VersionT& right) { return left.value == right.value; } - bool operator!=(const VersionT& left, const VersionT& right) { return left.value != right.value; } - std::string to_printf_arg(const VersionT& version) { return version.value; } + const std::string& VersionT::to_string() const { return value; } + bool operator==(const VersionT& left, const VersionT& right) { return left.to_string() == right.to_string(); } + bool operator!=(const VersionT& left, const VersionT& right) { return left.to_string() != right.to_string(); } + std::string to_printf_arg(const VersionT& version) { return version.to_string(); } VersionDiff::VersionDiff() : left(), right() {} VersionDiff::VersionDiff(const VersionT& left, const VersionT& right) : left(left), right(right) {} - std::string VersionDiff::to_string() const { return Strings::format("%s -> %s", left.value, right.value); } + std::string VersionDiff::to_string() const + { + return Strings::format("%s -> %s", left.to_string(), right.to_string()); + } } -- cgit v1.2.3 From e4d38bb874fe47317e1dd4128c013af882408bbf Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 11 Nov 2017 21:45:37 -0800 Subject: [vcpkg-ci] Fix crash when not passed --exclude. Added Util::Maps::maybe_find. Added Optional. --- toolsrc/src/vcpkg/commands.ci.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index dce294004..ee25f272a 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -75,8 +75,14 @@ namespace vcpkg::Commands::CI void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); - const std::vector exclusions = Strings::split(options.settings.at(OPTION_EXCLUDE), ","); - const std::set exclusions_set(exclusions.cbegin(), exclusions.cend()); + + std::set exclusions_set; + auto maybe_exclusions = Util::Maps::maybe_find(options.settings, OPTION_EXCLUDE); + if (auto p_exclusions = maybe_exclusions.get()) + { + auto exclusions = Strings::split(*p_exclusions, ","); + exclusions_set.insert(exclusions.begin(), exclusions.end()); + } std::vector triplets; for (const std::string& triplet : args.command_arguments) -- cgit v1.2.3 From 6ece1871b1c4249c667d6f1ca096fcb12861303f Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 11 Nov 2017 22:10:38 -0800 Subject: [vcpkg] Simplify code -- Maps::maybe_find is not very useful compared to iterators. --- toolsrc/src/vcpkg/commands.ci.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index ee25f272a..65adade1a 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -77,10 +77,10 @@ namespace vcpkg::Commands::CI const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); std::set exclusions_set; - auto maybe_exclusions = Util::Maps::maybe_find(options.settings, OPTION_EXCLUDE); - if (auto p_exclusions = maybe_exclusions.get()) + auto it_exclusions = options.settings.find(OPTION_EXCLUDE); + if (it_exclusions != options.settings.end()) { - auto exclusions = Strings::split(*p_exclusions, ","); + auto exclusions = Strings::split(it_exclusions->second, ","); exclusions_set.insert(exclusions.begin(), exclusions.end()); } -- cgit v1.2.3 From e4786a054d53d1c7f3f1ae24ce6004733af61a43 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 11 Nov 2017 22:40:53 -0800 Subject: Improve error message --- toolsrc/src/vcpkg/postbuildlint.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp index 0063f8d98..d83d656cf 100644 --- a/toolsrc/src/vcpkg/postbuildlint.cpp +++ b/toolsrc/src/vcpkg/postbuildlint.cpp @@ -74,8 +74,9 @@ namespace vcpkg::PostBuildLint const fs::path include_dir = package_dir / "include"; if (!fs.exists(include_dir) || fs.is_empty(include_dir)) { - System::println(System::Color::warning, - "The folder /include is empty. This indicates the library was not correctly installed."); + System::println( + System::Color::warning, + "The folder /include is empty or not present. This indicates the library was not correctly installed."); return LintStatus::ERROR_DETECTED; } -- cgit v1.2.3 From 415789b42e5fd43ac984902cd72848f6ef6b450a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 13 Nov 2017 21:36:29 -0800 Subject: [vcpkg-metrics] Replace SQM with MAC hash. --- toolsrc/src/vcpkg.cpp | 59 +++++++++++++++++++++++++++---------------- toolsrc/src/vcpkg/metrics.cpp | 36 +++++++++++++++++++++++--- 2 files changed, 69 insertions(+), 26 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 2a73c5b0f..5642f937c 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -157,6 +157,7 @@ static void load_config() CoTaskMemFree(localappdatapath); } + std::string user_id, user_time, user_mac; try { auto maybe_pghs = Paragraphs::get_paragraphs(Files::get_real_filesystem(), localappdata / "vcpkg" / "config"); @@ -173,39 +174,54 @@ static void load_config() keys.insert(p); } - auto user_id = keys["User-Id"]; - auto user_time = keys["User-Since"]; - if (!user_id.empty() && !user_time.empty()) - { - Metrics::g_metrics.lock()->set_user_information(user_id, user_time); - return; - } + user_id = keys["User-Id"]; + user_time = keys["User-Since"]; + user_mac = keys["Mac-Hash"]; } } catch (...) { } + bool write_config = false; + // config file not found, could not be read, or invalid - std::string user_id, user_time; + if (user_id.empty() || user_time.empty()) { - auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->init_user_information(user_id, user_time); - locked_metrics->set_user_information(user_id, user_time); + ::vcpkg::Metrics::Metrics::init_user_information(user_id, user_time); + write_config = true; } - try + + if (user_mac.empty()) { - std::error_code ec; - auto& fs = Files::get_real_filesystem(); - fs.create_directory(localappdata / "vcpkg", ec); - fs.write_contents(localappdata / "vcpkg" / "config", - Strings::format("User-Id: %s\n" - "User-Since: %s\n", - user_id, - user_time)); + user_mac = Metrics::get_MAC_user(); + write_config = true; } - catch (...) + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->set_user_information(user_id, user_time); + locked_metrics->track_property("user_mac", user_mac); + } + + if (write_config) + { + try + { + std::error_code ec; + auto& fs = Files::get_real_filesystem(); + fs.create_directory(localappdata / "vcpkg", ec); + fs.write_contents(localappdata / "vcpkg" / "config", + Strings::format("User-Id: %s\n" + "User-Since: %s\n" + "Mac-Hash: %s\n", + user_id, + user_time, + user_mac)); + } + catch (...) + { + } } #endif } @@ -259,7 +275,6 @@ int main(const int argc, const char* const* const argv) #endif } load_config(); - Metrics::g_metrics.lock()->track_property("sqmuser", Metrics::get_SQM_user()); const VcpkgCmdArguments args = VcpkgCmdArguments::create_from_command_line(argc, argv); diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 8f2575886..d7e18a176 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -233,12 +233,40 @@ namespace vcpkg::Metrics bool get_compiled_metrics_enabled() { return DISABLE_METRICS == 0; } - std::string get_SQM_user() + static fs::path get_vcpkg_root() + { + return Files::get_real_filesystem().find_file_recursively_up( + fs::stdfs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root"); + } + + std::string get_MAC_user() { #if defined(_WIN32) - auto hkcu_sqmclient = - System::get_registry_string(HKEY_CURRENT_USER, R"(Software\Microsoft\SQMClient)", "UserId"); - return hkcu_sqmclient.value_or("{}"); + auto getmac = System::cmd_execute_and_capture_output("getmac"); + + if (getmac.exit_code != 0) return "0"; + + std::regex mac_regex("([a-fA-F0-9]{2}(-[a-fA-F0-9]{2}){5})"); + std::sregex_iterator next(getmac.output.begin(), getmac.output.end(), mac_regex); + std::sregex_iterator last; + + while (next != last) + { + auto match = *next; + if (match[0] != "00-00-00-00-00-00") + { + std::string matchstr = match[0]; + auto hash_result = System::powershell_execute_and_capture_output( + "SHA256Hash", get_vcpkg_root() / "SHA256Hash.ps1", Strings::format("-Value \"%s\"", matchstr)); + Util::erase_remove_if(hash_result, + [](char ch) { return !(ch >= 'A' && ch <= 'F') && !(ch >= '0' && ch <= '9'); }); + hash_result = Strings::ascii_to_lowercase(hash_result); + return hash_result; + } + ++next; + } + + return "0"; #else return "{}"; #endif -- cgit v1.2.3 From 71289ee5e8e5286fde47ec563bfdcdb2cb9c369d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 13 Nov 2017 23:06:04 -0800 Subject: [vcpkg-contact] Add --survey so users can easily provide feedback --- toolsrc/src/vcpkg/commands.contact.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.contact.cpp b/toolsrc/src/vcpkg/commands.contact.cpp index 5d62faeea..07dcea80e 100644 --- a/toolsrc/src/vcpkg/commands.contact.cpp +++ b/toolsrc/src/vcpkg/commands.contact.cpp @@ -12,19 +12,29 @@ namespace vcpkg::Commands::Contact return S_EMAIL; } + static const CommandSwitch switches[] = {{"--survey", "Launch default browser to the current vcpkg survey"}}; + const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("contact"), 0, 0, - {}, + {switches, {}}, nullptr, }; void perform_and_exit(const VcpkgCmdArguments& args) { - args.parse_arguments(COMMAND_STRUCTURE); + auto parsed_args = args.parse_arguments(COMMAND_STRUCTURE); - System::println("Send an email to %s with any feedback.", email()); + if (Util::Sets::contains(parsed_args.switches, switches[0].name)) + { + System::cmd_execute("start https://aka.ms/NPS_vcpkg"); + System::println("Default browser launched to https://aka.ms/NPS_vcpkg, thank you for your feedback!"); + } + else + { + System::println("Send an email to %s with any feedback.", email()); + } Checks::exit_success(VCPKG_LINE_INFO); } } -- cgit v1.2.3 From ca1aa816d2af1b600f68b1c965bed5bd180d829a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 14 Nov 2017 15:27:12 -0800 Subject: [vcpkg-ci] Clean up buildtrees during build to avoid consuming 200+ Gb of SSD --- toolsrc/src/vcpkg/commands.ci.cpp | 2 +- toolsrc/src/vcpkg/install.cpp | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 65adade1a..3c1c443f0 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -49,7 +49,7 @@ namespace vcpkg::Commands::CI return Dependencies::AnyAction(std::move(install_action)); }); - return Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db); + return Install::perform(action_plan, Install::KeepGoing::YES, Install::CleanBuildtrees::YES, paths, status_db); } struct TripletAndSummary diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 20ffd3164..88ef5c73d 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -481,6 +481,7 @@ namespace vcpkg::Install InstallSummary perform(const std::vector& action_plan, const KeepGoing keep_going, + const CleanBuildtrees clean_buildtrees, const VcpkgPaths& paths, StatusParagraphs& status_db) { @@ -504,6 +505,21 @@ namespace vcpkg::Install if (const auto install_action = action.install_plan.get()) { const BuildResult result = perform_install_plan_action(paths, *install_action, status_db); + if (clean_buildtrees == CleanBuildtrees::YES) + { + auto& fs = paths.get_filesystem(); + auto buildtrees_dir = paths.buildtrees / install_action->spec.name(); + auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir); + for (auto&& file : buildtree_files) + { + if (fs.is_directory(file) && file.filename() != "src") + { + std::error_code ec; + fs.remove_all(file, ec); + } + } + } + if (result != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO) { System::println(Build::create_user_troubleshooting_message(install_action->spec)); @@ -645,7 +661,7 @@ namespace vcpkg::Install Checks::exit_success(VCPKG_LINE_INFO); } - const InstallSummary summary = perform(action_plan, keep_going, paths, status_db); + const InstallSummary summary = perform(action_plan, keep_going, Install::CleanBuildtrees::NO, paths, status_db); System::println("\nTotal elapsed time: %s", summary.total_elapsed_time); -- cgit v1.2.3 From 34b4db1fb45df541b8a2c7592a57ac6a8fd0b900 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 16 Nov 2017 17:42:15 -0800 Subject: [vcpkg] Output autodetected CMake usage information after install. --- toolsrc/src/vcpkg/install.cpp | 140 +++++++++++++++++++++++++++++++++++------- 1 file changed, 119 insertions(+), 21 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 88ef5c73d..7edcafb1f 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -247,10 +247,11 @@ namespace vcpkg::Install } using Build::BuildResult; + using Build::BuildResults; - BuildResult perform_install_plan_action(const VcpkgPaths& paths, - const InstallPlanAction& action, - StatusParagraphs& status_db) + BuildResults perform_install_plan_action(const VcpkgPaths& paths, + const InstallPlanAction& action, + StatusParagraphs& status_db) { const InstallPlanType& plan_type = action.plan_type; const std::string display_name = action.spec.to_string(); @@ -267,7 +268,7 @@ namespace vcpkg::Install System::Color::warning, "Package %s is already installed -- not building from HEAD", display_name); else System::println(System::Color::success, "Package %s is already installed", display_name); - return BuildResult::SUCCEEDED; + return {BuildResult::SUCCEEDED, nullptr}; } if (plan_type == InstallPlanType::BUILD_AND_INSTALL) @@ -302,21 +303,21 @@ namespace vcpkg::Install if (result.code != Build::BuildResult::SUCCEEDED) { System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); - return result.code; + return {result.code, nullptr}; } System::println("Building package %s... done", display_name_with_features); - const BinaryControlFile bcf = - Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); + auto bcf = std::make_unique( + Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO)); System::println("Installing package %s... ", display_name_with_features); - const auto install_result = install_package(paths, bcf, &status_db); + const auto install_result = install_package(paths, *bcf, &status_db); switch (install_result) { case InstallResult::SUCCESS: System::println(System::Color::success, "Installing package %s... done", display_name); - return BuildResult::SUCCEEDED; - case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS; + return {BuildResult::SUCCEEDED, std::move(bcf)}; + case InstallResult::FILE_CONFLICTS: return {BuildResult::FILE_CONFLICTS, nullptr}; default: Checks::unreachable(VCPKG_LINE_INFO); } } @@ -335,8 +336,8 @@ namespace vcpkg::Install { case InstallResult::SUCCESS: System::println(System::Color::success, "Installing package %s... done", display_name); - return BuildResult::SUCCEEDED; - case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS; + return {BuildResult::SUCCEEDED, nullptr}; + case InstallResult::FILE_CONFLICTS: return {BuildResult::FILE_CONFLICTS, nullptr}; default: Checks::unreachable(VCPKG_LINE_INFO); } } @@ -344,7 +345,7 @@ namespace vcpkg::Install if (plan_type == InstallPlanType::EXCLUDED) { System::println(System::Color::warning, "Package %s is excluded", display_name); - return BuildResult::EXCLUDED; + return {BuildResult::EXCLUDED, nullptr}; } Checks::unreachable(VCPKG_LINE_INFO); @@ -458,7 +459,8 @@ namespace vcpkg::Install for (const SpecSummary& result : this->results) { - System::println(" %s: %s: %s", result.spec, Build::to_string(result.result), result.timing); + System::println( + " %s: %s: %s", result.spec, Build::to_string(result.build_result.result_code), result.timing); } std::map summary; @@ -469,7 +471,7 @@ namespace vcpkg::Install for (const SpecSummary& r : this->results) { - summary[r.result]++; + summary[r.build_result.result_code]++; } System::println("\nSUMMARY"); @@ -500,11 +502,11 @@ namespace vcpkg::Install const std::string display_name = spec.to_string(); System::println("Starting package %d/%d: %s", counter, package_count, display_name); - results.push_back(SpecSummary{spec}); + results.emplace_back(spec, &action); if (const auto install_action = action.install_plan.get()) { - const BuildResult result = perform_install_plan_action(paths, *install_action, status_db); + Build::BuildResults result = perform_install_plan_action(paths, *install_action, status_db); if (clean_buildtrees == CleanBuildtrees::YES) { auto& fs = paths.get_filesystem(); @@ -520,13 +522,13 @@ namespace vcpkg::Install } } - if (result != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO) + if (result.result_code != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO) { System::println(Build::create_user_troubleshooting_message(install_action->spec)); Checks::exit_fail(VCPKG_LINE_INFO); } - results.back().result = result; + results.back().build_result = std::move(result); } else if (const auto remove_action = action.remove_plan.get()) { @@ -542,7 +544,7 @@ namespace vcpkg::Install System::println("Elapsed time for package %s: %s", display_name, build_timer.to_string()); } - return InstallSummary{results, timer.to_string()}; + return InstallSummary{std::move(results), timer.to_string()}; } static const std::string OPTION_DRY_RUN = "--dry-run"; @@ -576,6 +578,69 @@ namespace vcpkg::Install &get_all_port_names, }; + static void print_cmake_information(const BinaryParagraph& bpgh, const VcpkgPaths& paths) + { + static const std::regex cmake_library_regex("^add_library\\(([^\\s\\$\\)]+)\\s"); + + auto& fs = paths.get_filesystem(); + + auto files = fs.read_lines(paths.listfile_path(bpgh)); + if (auto p_lines = files.get()) + { + for (auto&& suffix : *p_lines) + { + if (Strings::case_insensitive_ascii_find(suffix, "/share/") != suffix.end()) + { + std::vector library_targets; + + // File is inside the share folder + auto path = paths.installed / suffix; + auto maybe_contents = fs.read_contents(path); + if (auto p_contents = maybe_contents.get()) + { + std::sregex_iterator next(p_contents->begin(), p_contents->end(), cmake_library_regex); + std::sregex_iterator last; + + while (next != last) + { + auto match = *next; + library_targets.push_back(match[1]); + ++next; + } + } + + if (library_targets.empty()) + { + } + else if (library_targets.size() <= 4) + { + System::println("\nThe package %s provides CMake targets:\n" + "\n" + " find_package(%s REQUIRED)\n" + " target_link_libraries(main PRIVATE %s)", + bpgh.spec, + path.parent_path().filename().u8string(), + Strings::join(" ", library_targets)); + } + else + { + auto omitted = library_targets.size() - 4; + library_targets.erase(library_targets.begin() + 4, library_targets.end()); + System::println("\nThe package %s provides CMake targets:\n" + "\n" + " find_package(%s REQUIRED)\n" + " # Note: %d targets were omitted\n" + " target_link_libraries(main PRIVATE %s)", + bpgh.spec, + path.parent_path().filename().u8string(), + omitted, + Strings::join(" ", library_targets)); + } + } + } + } + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { // input sanitization @@ -670,8 +735,41 @@ namespace vcpkg::Install summary.print(); } + auto& fs = paths.get_filesystem(); + + for (auto&& result : summary.results) + { + if (!result.action) continue; + if (auto p_install_action = result.action->install_plan.get()) + { + if (p_install_action->request_type != RequestType::USER_REQUESTED) continue; + auto bpgh = result.get_binary_paragraph(); + if (!bpgh) continue; + print_cmake_information(*bpgh, paths); + } + } + Checks::exit_success(VCPKG_LINE_INFO); } - SpecSummary::SpecSummary(const PackageSpec& spec) : spec(spec), result(BuildResult::NULLVALUE), timing("0") {} + SpecSummary::SpecSummary(const PackageSpec& spec, const Dependencies::AnyAction* action) + : spec(spec), build_result{BuildResult::NULLVALUE, nullptr}, timing("0"), action(action) + { + } + + const BinaryParagraph* SpecSummary::get_binary_paragraph() const + { + if (build_result.binary_control_file) return &build_result.binary_control_file->core_paragraph; + if (action) + if (auto p_install_plan = action->install_plan.get()) + { + if (auto p_bcf = p_install_plan->any_paragraph.binary_control_file.get()) + return &p_bcf->core_paragraph; + else if (auto p_status = p_install_plan->any_paragraph.status_paragraph.get()) + { + return &p_status->package; + } + } + return nullptr; + } } -- cgit v1.2.3 From 468e9e70e644eb26258434c9e27e34935eb3e06d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 16 Nov 2017 19:29:32 -0800 Subject: [vcpkg] Refactor to remove Build::BuildResults -- too similar to ExtendedBuildResult --- toolsrc/src/vcpkg/build.cpp | 66 ++++++++++++++++++---------- toolsrc/src/vcpkg/commands.ci.cpp | 8 +++- toolsrc/src/vcpkg/install.cpp | 90 ++++++++++++++++----------------------- 3 files changed, 86 insertions(+), 78 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index b0ca3501b..e3787a97e 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -220,26 +220,25 @@ namespace vcpkg::Build tonull); } - static void create_binary_feature_control_file(const SourceParagraph& source_paragraph, - const FeatureParagraph& feature_paragraph, - const Triplet& triplet, - BinaryControlFile& bcf) + static BinaryParagraph create_binary_feature_control_file(const SourceParagraph& source_paragraph, + const FeatureParagraph& feature_paragraph, + const Triplet& triplet) { - BinaryParagraph bpgh(source_paragraph, feature_paragraph, triplet); - bcf.features.emplace_back(std::move(bpgh)); + return BinaryParagraph(source_paragraph, feature_paragraph, triplet); } - static void create_binary_control_file(const SourceParagraph& source_paragraph, - const Triplet& triplet, - const BuildInfo& build_info, - BinaryControlFile& bcf) + static std::unique_ptr create_binary_control_file(const SourceParagraph& source_paragraph, + const Triplet& triplet, + const BuildInfo& build_info) { + auto bcf = std::make_unique(); BinaryParagraph bpgh(source_paragraph, triplet); if (const auto p_ver = build_info.version.get()) { bpgh.version = *p_ver; } - bcf.core_paragraph = std::move(bpgh); + bcf->core_paragraph = std::move(bpgh); + return bcf; } static void write_binary_control_file(const VcpkgPaths& paths, BinaryControlFile bcf) @@ -311,8 +310,9 @@ namespace vcpkg::Build {"CURRENT_PORT_DIR", config.port_dir / "/."}, {"TARGET_TRIPLET", triplet.canonical_name()}, {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, - {"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, - {"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, + {"VCPKG_USE_HEAD_VERSION", + Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, + {"_VCPKG_NO_DOWNLOADS", !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, {"GIT", git_exe_path}, {"FEATURES", features}, }); @@ -333,20 +333,18 @@ namespace vcpkg::Build { locked_metrics->track_property("error", "build failed"); locked_metrics->track_property("build_error", spec_string); - return {BuildResult::BUILD_FAILED, {}}; + return BuildResult::BUILD_FAILED; } } const BuildInfo build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); - BinaryControlFile bcf; - - create_binary_control_file(config.src, triplet, build_info, bcf); + auto bcf = create_binary_control_file(config.src, triplet, build_info); if (error_count != 0) { - return {BuildResult::POST_BUILD_CHECKS_FAILED, {}}; + return BuildResult::POST_BUILD_CHECKS_FAILED; } if (GlobalState::feature_packages) { @@ -357,18 +355,31 @@ namespace vcpkg::Build for (auto&& f_pgh : config.scf->feature_paragraphs) { if (f_pgh->name == feature) - create_binary_feature_control_file(*config.scf->core_paragraph, *f_pgh, triplet, bcf); + bcf->features.push_back( + create_binary_feature_control_file(*config.scf->core_paragraph, *f_pgh, triplet)); } } } } - write_binary_control_file(paths, bcf); + write_binary_control_file(paths, *bcf); - // const fs::path port_buildtrees_dir = paths.buildtrees / spec.name; - // delete_directory(port_buildtrees_dir); + if (config.build_package_options.clean_buildtrees == CleanBuildtrees::YES) + { + auto& fs = paths.get_filesystem(); + auto buildtrees_dir = paths.buildtrees / spec.name(); + auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir); + for (auto&& file : buildtree_files) + { + if (fs.is_directory(file) && file.filename() != "src") + { + std::error_code ec; + fs.remove_all(file, ec); + } + } + } - return {BuildResult::SUCCEEDED, {}}; + return {BuildResult::SUCCEEDED, std::move(bcf)}; } const std::string& to_string(const BuildResult build_result) @@ -549,4 +560,13 @@ namespace vcpkg::Build return pre_build_info; } + ExtendedBuildResult::ExtendedBuildResult(BuildResult code) : code(code) {} + ExtendedBuildResult::ExtendedBuildResult(BuildResult code, std::unique_ptr&& bcf) + : code(code), binary_control_file(std::move(bcf)) + { + } + ExtendedBuildResult::ExtendedBuildResult(BuildResult code, std::vector&& unmet_deps) + : code(code), unmet_dependencies(std::move(unmet_deps)) + { + } } diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 3c1c443f0..8f79b83e1 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -41,7 +41,11 @@ namespace vcpkg::Commands::CI Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); - const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; + const Build::BuildPackageOptions install_plan_options = { + Build::UseHeadVersion::NO, + Build::AllowDownloads::YES, + Build::CleanBuildtrees::YES, + }; const std::vector action_plan = Util::fmap(install_plan, [&install_plan_options](InstallPlanAction& install_action) { @@ -49,7 +53,7 @@ namespace vcpkg::Commands::CI return Dependencies::AnyAction(std::move(install_action)); }); - return Install::perform(action_plan, Install::KeepGoing::YES, Install::CleanBuildtrees::YES, paths, status_db); + return Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db); } struct TripletAndSummary diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 7edcafb1f..cc006811b 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -247,11 +247,11 @@ namespace vcpkg::Install } using Build::BuildResult; - using Build::BuildResults; + using Build::ExtendedBuildResult; - BuildResults perform_install_plan_action(const VcpkgPaths& paths, - const InstallPlanAction& action, - StatusParagraphs& status_db) + ExtendedBuildResult perform_install_plan_action(const VcpkgPaths& paths, + const InstallPlanAction& action, + StatusParagraphs& status_db) { const InstallPlanType& plan_type = action.plan_type; const std::string display_name = action.spec.to_string(); @@ -259,7 +259,7 @@ namespace vcpkg::Install GlobalState::feature_packages ? action.displayname() : display_name; const bool is_user_requested = action.request_type == RequestType::USER_REQUESTED; - const bool use_head_version = to_bool(action.build_options.use_head_version); + const bool use_head_version = Util::Enum::to_bool(action.build_options.use_head_version); if (plan_type == InstallPlanType::ALREADY_INSTALLED) { @@ -268,9 +268,22 @@ namespace vcpkg::Install System::Color::warning, "Package %s is already installed -- not building from HEAD", display_name); else System::println(System::Color::success, "Package %s is already installed", display_name); - return {BuildResult::SUCCEEDED, nullptr}; + return BuildResult::SUCCEEDED; } + auto aux_install = [&](const std::string& name, const BinaryControlFile& bcf) -> BuildResult { + System::println("Installing package %s... ", name); + const auto install_result = install_package(paths, bcf, &status_db); + switch (install_result) + { + case InstallResult::SUCCESS: + System::println(System::Color::success, "Installing package %s... done", name); + return BuildResult::SUCCEEDED; + case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + }; + if (plan_type == InstallPlanType::BUILD_AND_INSTALL) { if (use_head_version) @@ -278,7 +291,7 @@ namespace vcpkg::Install else System::println("Building package %s... ", display_name_with_features); - const auto result = [&]() -> Build::ExtendedBuildResult { + auto result = [&]() -> Build::ExtendedBuildResult { if (GlobalState::feature_packages) { const Build::BuildPackageConfig build_config{ @@ -303,23 +316,15 @@ namespace vcpkg::Install if (result.code != Build::BuildResult::SUCCEEDED) { System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); - return {result.code, nullptr}; + return result; } System::println("Building package %s... done", display_name_with_features); auto bcf = std::make_unique( Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO)); - System::println("Installing package %s... ", display_name_with_features); - const auto install_result = install_package(paths, *bcf, &status_db); - switch (install_result) - { - case InstallResult::SUCCESS: - System::println(System::Color::success, "Installing package %s... done", display_name); - return {BuildResult::SUCCEEDED, std::move(bcf)}; - case InstallResult::FILE_CONFLICTS: return {BuildResult::FILE_CONFLICTS, nullptr}; - default: Checks::unreachable(VCPKG_LINE_INFO); - } + auto code = aux_install(display_name_with_features, *bcf); + return {code, std::move(bcf)}; } if (plan_type == InstallPlanType::INSTALL) @@ -329,23 +334,15 @@ namespace vcpkg::Install System::println( System::Color::warning, "Package %s is already built -- not building from HEAD", display_name); } - System::println("Installing package %s... ", display_name); - const auto install_result = install_package( - paths, action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO), &status_db); - switch (install_result) - { - case InstallResult::SUCCESS: - System::println(System::Color::success, "Installing package %s... done", display_name); - return {BuildResult::SUCCEEDED, nullptr}; - case InstallResult::FILE_CONFLICTS: return {BuildResult::FILE_CONFLICTS, nullptr}; - default: Checks::unreachable(VCPKG_LINE_INFO); - } + auto code = aux_install(display_name_with_features, + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO)); + return code; } if (plan_type == InstallPlanType::EXCLUDED) { System::println(System::Color::warning, "Package %s is excluded", display_name); - return {BuildResult::EXCLUDED, nullptr}; + return BuildResult::EXCLUDED; } Checks::unreachable(VCPKG_LINE_INFO); @@ -459,8 +456,7 @@ namespace vcpkg::Install for (const SpecSummary& result : this->results) { - System::println( - " %s: %s: %s", result.spec, Build::to_string(result.build_result.result_code), result.timing); + System::println(" %s: %s: %s", result.spec, Build::to_string(result.build_result.code), result.timing); } std::map summary; @@ -471,7 +467,7 @@ namespace vcpkg::Install for (const SpecSummary& r : this->results) { - summary[r.build_result.result_code]++; + summary[r.build_result.code]++; } System::println("\nSUMMARY"); @@ -483,7 +479,6 @@ namespace vcpkg::Install InstallSummary perform(const std::vector& action_plan, const KeepGoing keep_going, - const CleanBuildtrees clean_buildtrees, const VcpkgPaths& paths, StatusParagraphs& status_db) { @@ -506,23 +501,9 @@ namespace vcpkg::Install if (const auto install_action = action.install_plan.get()) { - Build::BuildResults result = perform_install_plan_action(paths, *install_action, status_db); - if (clean_buildtrees == CleanBuildtrees::YES) - { - auto& fs = paths.get_filesystem(); - auto buildtrees_dir = paths.buildtrees / install_action->spec.name(); - auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir); - for (auto&& file : buildtree_files) - { - if (fs.is_directory(file) && file.filename() != "src") - { - std::error_code ec; - fs.remove_all(file, ec); - } - } - } + auto result = perform_install_plan_action(paths, *install_action, status_db); - if (result.result_code != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO) + if (result.code != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO) { System::println(Build::create_user_troubleshooting_message(install_action->spec)); Checks::exit_fail(VCPKG_LINE_INFO); @@ -669,8 +650,11 @@ namespace vcpkg::Install // create the plan StatusParagraphs status_db = database_load_check(paths); - const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), - Build::to_allow_downloads(!no_downloads)}; + const Build::BuildPackageOptions install_plan_options = { + Util::Enum::to_enum(use_head_version), + Util::Enum::to_enum(!no_downloads), + Build::CleanBuildtrees::NO, + }; // Note: action_plan will hold raw pointers to SourceControlFiles from this map std::unordered_map scf_map; @@ -726,7 +710,7 @@ namespace vcpkg::Install Checks::exit_success(VCPKG_LINE_INFO); } - const InstallSummary summary = perform(action_plan, keep_going, Install::CleanBuildtrees::NO, paths, status_db); + const InstallSummary summary = perform(action_plan, keep_going, paths, status_db); System::println("\nTotal elapsed time: %s", summary.total_elapsed_time); -- cgit v1.2.3 From 1b2f75be941e9eed5986c10eb99fd6049490daec Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 16 Nov 2017 23:54:55 -0800 Subject: [vcpkg] Support \share\\usage to handle libraries which are found through built-in Find Modules. --- toolsrc/src/vcpkg/install.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index cc006811b..f48b04d68 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -565,6 +565,17 @@ namespace vcpkg::Install auto& fs = paths.get_filesystem(); + auto usage_file = paths.installed / bpgh.spec.triplet().canonical_name() / "share" / bpgh.spec.name() / "usage"; + if (fs.exists(usage_file)) + { + auto maybe_contents = fs.read_contents(usage_file); + if (auto p_contents = maybe_contents.get()) + { + System::println(*p_contents); + } + return; + } + auto files = fs.read_lines(paths.listfile_path(bpgh)); if (auto p_lines = files.get()) { @@ -595,10 +606,10 @@ namespace vcpkg::Install } else if (library_targets.size() <= 4) { - System::println("\nThe package %s provides CMake targets:\n" + System::println("The package %s provides CMake targets:\n" "\n" " find_package(%s REQUIRED)\n" - " target_link_libraries(main PRIVATE %s)", + " target_link_libraries(main PRIVATE %s)\n", bpgh.spec, path.parent_path().filename().u8string(), Strings::join(" ", library_targets)); @@ -607,11 +618,11 @@ namespace vcpkg::Install { auto omitted = library_targets.size() - 4; library_targets.erase(library_targets.begin() + 4, library_targets.end()); - System::println("\nThe package %s provides CMake targets:\n" + System::println("The package %s provides CMake targets:\n" "\n" " find_package(%s REQUIRED)\n" " # Note: %d targets were omitted\n" - " target_link_libraries(main PRIVATE %s)", + " target_link_libraries(main PRIVATE %s)\n", bpgh.spec, path.parent_path().filename().u8string(), omitted, @@ -712,7 +723,7 @@ namespace vcpkg::Install const InstallSummary summary = perform(action_plan, keep_going, paths, status_db); - System::println("\nTotal elapsed time: %s", summary.total_elapsed_time); + System::println("\nTotal elapsed time: %s\n", summary.total_elapsed_time); if (keep_going == KeepGoing::YES) { -- cgit v1.2.3 From 1313a418cfe26d29c7b4ec2f871d93a07e884d10 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 20 Nov 2017 18:17:24 -0800 Subject: Introduce PowershellParameter to add '' to parameter values. Also place that and CMakeVariable in System.h --- toolsrc/src/vcpkg/base/system.cpp | 41 ++++++++++++++++++++++++++++++++++- toolsrc/src/vcpkg/build.cpp | 12 +++++----- toolsrc/src/vcpkg/commands.create.cpp | 3 +-- toolsrc/src/vcpkg/export.cpp | 3 ++- toolsrc/src/vcpkg/metrics.cpp | 5 +++-- toolsrc/src/vcpkg/vcpkglib.cpp | 24 +------------------- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 7 files changed, 55 insertions(+), 37 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 47096ed63..56b725f6b 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -72,6 +72,43 @@ namespace vcpkg::System return supported_architectures; } + CMakeVariable::CMakeVariable(const CStringView varname, const char* varvalue) + : s(Strings::format(R"("-D%s=%s")", varname, varvalue)) + { + } + CMakeVariable::CMakeVariable(const CStringView varname, const std::string& varvalue) + : CMakeVariable(varname, varvalue.c_str()) + { + } + CMakeVariable::CMakeVariable(const CStringView varname, const fs::path& path) + : CMakeVariable(varname, path.generic_u8string()) + { + } + + std::string make_cmake_cmd(const fs::path& cmake_exe, + const fs::path& cmake_script, + const std::vector& pass_variables) + { + const std::string cmd_cmake_pass_variables = Strings::join(" ", pass_variables, [](auto&& v) { return v.s; }); + return Strings::format( + R"("%s" %s -P "%s")", cmake_exe.u8string(), cmd_cmake_pass_variables, cmake_script.generic_u8string()); + } + + PowershellParameter::PowershellParameter(const CStringView varname, const char* varvalue) + : s(Strings::format(R"(-%s '%s')", varname, varvalue)) + { + } + + PowershellParameter::PowershellParameter(const CStringView varname, const std::string& varvalue) + : PowershellParameter(varname, varvalue.c_str()) + { + } + + PowershellParameter::PowershellParameter(const CStringView varname, const fs::path& path) + : PowershellParameter(varname, path.generic_u8string()) + { + } + int cmd_execute_clean(const CStringView cmd_line) { #if defined(_WIN32) @@ -272,8 +309,10 @@ namespace vcpkg::System std::string powershell_execute_and_capture_output(const std::string& title, const fs::path& script_path, - const CStringView args) + const std::vector& parameters) { + const std::string args = Strings::join(" ", parameters, [](auto&& v) { return v.s; }); + // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned const std::string cmd = Strings::format( R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args); diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index e3787a97e..804573d91 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -301,7 +301,7 @@ namespace vcpkg::Build const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); - const std::string cmd_launch_cmake = make_cmake_cmd( + const std::string cmd_launch_cmake = System::make_cmake_cmd( cmake_exe_path, ports_cmake_script_path, { @@ -493,11 +493,11 @@ namespace vcpkg::Build const fs::path ports_cmake_script_path = paths.scripts / "get_triplet_environment.cmake"; const fs::path triplet_file_path = paths.triplets / (triplet.canonical_name() + ".cmake"); - const auto cmd_launch_cmake = make_cmake_cmd(cmake_exe_path, - ports_cmake_script_path, - { - {"CMAKE_TRIPLET_FILE", triplet_file_path}, - }); + const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path, + ports_cmake_script_path, + { + {"CMAKE_TRIPLET_FILE", triplet_file_path}, + }); const auto ec_data = System::cmd_execute_and_capture_output(cmd_launch_cmake); Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, ec_data.output); diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp index c7183d257..44f5f7928 100644 --- a/toolsrc/src/vcpkg/commands.create.cpp +++ b/toolsrc/src/vcpkg/commands.create.cpp @@ -4,7 +4,6 @@ #include #include #include -#include namespace vcpkg::Commands::Create { @@ -25,7 +24,7 @@ namespace vcpkg::Commands::Create const fs::path& cmake_exe = paths.get_cmake_exe(); - std::vector cmake_args{{"CMD", "CREATE"}, {"PORT", port_name}, {"URL", url}}; + std::vector cmake_args{{"CMD", "CREATE"}, {"PORT", port_name}, {"URL", url}}; if (args.command_arguments.size() >= 3) { diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 9b86863eb..f237c72f8 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -369,7 +369,8 @@ namespace vcpkg::Export static void print_next_step_info(const fs::path& prefix) { const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; - const CMakeVariable cmake_variable = CMakeVariable("CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); + const System::CMakeVariable cmake_variable = + System::CMakeVariable("CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); System::println("\n" "To use the exported libraries in CMake projects use:" "\n" diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index d7e18a176..15bcb4516 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -255,9 +255,10 @@ namespace vcpkg::Metrics auto match = *next; if (match[0] != "00-00-00-00-00-00") { - std::string matchstr = match[0]; + const std::string matchstr = match[0]; + const System::PowershellParameter value("Value", matchstr); auto hash_result = System::powershell_execute_and_capture_output( - "SHA256Hash", get_vcpkg_root() / "SHA256Hash.ps1", Strings::format("-Value \"%s\"", matchstr)); + "SHA256Hash", get_vcpkg_root() / "SHA256Hash.ps1", {value}); Util::erase_remove_if(hash_result, [](char ch) { return !(ch >= 'A' && ch <= 'F') && !(ch >= '0' && ch <= '9'); }); hash_result = Strings::ascii_to_lowercase(hash_result); diff --git a/toolsrc/src/vcpkg/vcpkglib.cpp b/toolsrc/src/vcpkg/vcpkglib.cpp index 38b130f6f..5b2cec4d0 100644 --- a/toolsrc/src/vcpkg/vcpkglib.cpp +++ b/toolsrc/src/vcpkg/vcpkglib.cpp @@ -212,29 +212,7 @@ namespace vcpkg return installed_files; } - CMakeVariable::CMakeVariable(const CStringView varname, const char* varvalue) - : s(Strings::format(R"("-D%s=%s")", varname, varvalue)) - { - } - CMakeVariable::CMakeVariable(const CStringView varname, const std::string& varvalue) - : CMakeVariable(varname, varvalue.c_str()) - { - } - CMakeVariable::CMakeVariable(const CStringView varname, const fs::path& path) - : CMakeVariable(varname, path.generic_u8string()) - { - } - - std::string make_cmake_cmd(const fs::path& cmake_exe, - const fs::path& cmake_script, - const std::vector& pass_variables) - { - const std::string cmd_cmake_pass_variables = Strings::join(" ", pass_variables, [](auto&& v) { return v.s; }); - return Strings::format( - R"("%s" %s -P "%s")", cmake_exe.u8string(), cmd_cmake_pass_variables, cmake_script.generic_u8string()); - } - - std::string shorten_text(const std::string& desc, size_t length) + std::string shorten_text(const std::string& desc, const size_t length) { Checks::check_exit(VCPKG_LINE_INFO, length >= 3); auto simple_desc = std::regex_replace(desc, std::regex("\\s+"), " "); diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index a553f4199..460979693 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -92,8 +92,8 @@ namespace vcpkg version_as_string); const fs::path script = scripts_folder / "fetchDependency.ps1"; const std::string title = "Fetching %s version %s (No sufficient installed version was found)"; - const std::string output = - System::powershell_execute_and_capture_output(title, script, Strings::format("-Dependency %s", tool_name)); + const System::PowershellParameter dependency_param("Dependency", tool_name); + const std::string output = System::powershell_execute_and_capture_output(title, script, {dependency_param}); const std::vector dependency_path = keep_data_lines(output); Checks::check_exit( -- cgit v1.2.3 From 7c07ff813b0528fdd37f8835b99bc2e449fcf10c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 20 Nov 2017 18:22:55 -0800 Subject: Fix path --- toolsrc/src/vcpkg/metrics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 15bcb4516..69160705c 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -258,7 +258,7 @@ namespace vcpkg::Metrics const std::string matchstr = match[0]; const System::PowershellParameter value("Value", matchstr); auto hash_result = System::powershell_execute_and_capture_output( - "SHA256Hash", get_vcpkg_root() / "SHA256Hash.ps1", {value}); + "SHA256Hash", get_vcpkg_root() / "scripts" / "SHA256Hash.ps1", {value}); Util::erase_remove_if(hash_result, [](char ch) { return !(ch >= 'A' && ch <= 'F') && !(ch >= '0' && ch <= '9'); }); hash_result = Strings::ascii_to_lowercase(hash_result); -- cgit v1.2.3 From 786d53c002c044e9340e43070b393d69e14e78be Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 20 Nov 2017 19:15:47 -0800 Subject: Fix `vcpkg integrate install` for unicode usernames --- toolsrc/src/vcpkg/commands.integrate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 31b9ec722..f13a999fa 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -139,7 +139,7 @@ namespace vcpkg::Commands::Integrate static fs::path get_appdata_targets_path() { static const fs::path LOCAL_APP_DATA = - fs::path(System::get_environment_variable("LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO)); + fs::u8path(System::get_environment_variable("LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO)); return LOCAL_APP_DATA / "vcpkg" / "vcpkg.user.targets"; } #endif -- cgit v1.2.3 From 480f50a7b0e050885fa79eb6c2ffc85e0a4e7649 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 21 Nov 2017 19:58:38 -0800 Subject: [vcpkg] Improve cmake targets output --- toolsrc/src/vcpkg/install.cpp | 51 +++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index f48b04d68..249e36e0f 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -579,15 +579,17 @@ namespace vcpkg::Install auto files = fs.read_lines(paths.listfile_path(bpgh)); if (auto p_lines = files.get()) { + std::map> library_targets; + for (auto&& suffix : *p_lines) { - if (Strings::case_insensitive_ascii_find(suffix, "/share/") != suffix.end()) + if (Strings::case_insensitive_ascii_find(suffix, "/share/") != suffix.end() && + suffix.substr(suffix.size() - 6) == ".cmake") { - std::vector library_targets; - // File is inside the share folder auto path = paths.installed / suffix; auto maybe_contents = fs.read_contents(path); + auto find_package_name = path.parent_path().filename().u8string(); if (auto p_contents = maybe_contents.get()) { std::sregex_iterator next(p_contents->begin(), p_contents->end(), cmake_library_regex); @@ -596,37 +598,40 @@ namespace vcpkg::Install while (next != last) { auto match = *next; - library_targets.push_back(match[1]); + library_targets[find_package_name].push_back(match[1]); ++next; } } + } + } - if (library_targets.empty()) - { - } - else if (library_targets.size() <= 4) + if (library_targets.empty()) + { + } + else + { + System::println("The package %s provides CMake targets:\n", bpgh.spec); + + for (auto&& library_target_pair : library_targets) + { + if (library_target_pair.second.size() <= 4) { - System::println("The package %s provides CMake targets:\n" - "\n" - " find_package(%s REQUIRED)\n" + System::println(" find_package(%s REQUIRED)\n" " target_link_libraries(main PRIVATE %s)\n", - bpgh.spec, - path.parent_path().filename().u8string(), - Strings::join(" ", library_targets)); + library_target_pair.first, + Strings::join(" ", library_target_pair.second)); } else { - auto omitted = library_targets.size() - 4; - library_targets.erase(library_targets.begin() + 4, library_targets.end()); - System::println("The package %s provides CMake targets:\n" - "\n" - " find_package(%s REQUIRED)\n" + auto omitted = library_target_pair.second.size() - 4; + library_target_pair.second.erase(library_target_pair.second.begin() + 4, + library_target_pair.second.end()); + System::println(" find_package(%s REQUIRED)\n" " # Note: %d targets were omitted\n" " target_link_libraries(main PRIVATE %s)\n", - bpgh.spec, - path.parent_path().filename().u8string(), + library_target_pair.first, omitted, - Strings::join(" ", library_targets)); + Strings::join(" ", library_target_pair.second)); } } } @@ -730,8 +735,6 @@ namespace vcpkg::Install summary.print(); } - auto& fs = paths.get_filesystem(); - for (auto&& result : summary.results) { if (!result.action) continue; -- cgit v1.2.3 From 141f10801c2fae8ab844e94fe5338d055892c0ac Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 25 Nov 2017 11:49:15 -0800 Subject: [vcpkg] Improve external toolchain handling. --- toolsrc/src/vcpkg/base/files.cpp | 3 ++- toolsrc/src/vcpkg/base/system.cpp | 10 ++++++++++ toolsrc/src/vcpkg/build.cpp | 14 ++++++++++++-- toolsrc/src/vcpkg/commands.env.cpp | 2 +- toolsrc/src/vcpkg/export.cpp | 2 +- toolsrc/src/vcpkg/install.cpp | 2 +- toolsrc/src/vcpkg/postbuildlint.cpp | 2 +- toolsrc/src/vcpkg/vcpkgpaths.cpp | 37 +++++++++++++++++++++++++++++++------ 8 files changed, 59 insertions(+), 13 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 6e43debb1..8c9e137ed 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -72,7 +72,8 @@ namespace vcpkg::Files { std::vector ret; - fs::stdfs::recursive_directory_iterator b(dir), e{}; + std::error_code ec; + fs::stdfs::recursive_directory_iterator b(dir, ec), e{}; for (; b != e; ++b) { ret.push_back(b->path()); diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 56b725f6b..9d8e1ce84 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -51,11 +51,21 @@ namespace vcpkg::System CPUArchitecture get_host_processor() { +#if defined(_WIN32) auto w6432 = get_environment_variable("PROCESSOR_ARCHITEW6432"); if (const auto p = w6432.get()) return to_cpu_architecture(*p).value_or_exit(VCPKG_LINE_INFO); const auto procarch = get_environment_variable("PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO); return to_cpu_architecture(procarch).value_or_exit(VCPKG_LINE_INFO); +#else +#if defined(__x86_64__) || defined(_M_X64) + return CPUArchitecture::X64; +#elif defined(__x86__) || defined(_M_X86) + return CPUArchitecture::X86; +#else +#error "Unknown host architecture" +#endif +#endif } std::vector get_supported_host_architectures() diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 804573d91..fd605ac08 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -203,6 +203,10 @@ namespace vcpkg::Build std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset) { + if (pre_build_info.external_toolchain_file) + return Strings::format( + R"("%s" %s 2>&1)", toolset.vcvarsall.u8string(), Strings::join(" ", toolset.vcvarsall_options)); + const char* tonull = " >nul"; if (GlobalState::debugging) { @@ -299,8 +303,7 @@ namespace vcpkg::Build } } - const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); - + const Toolset& toolset = paths.get_toolset(pre_build_info); const std::string cmd_launch_cmake = System::make_cmake_cmd( cmake_exe_path, ports_cmake_script_path, @@ -555,6 +558,13 @@ namespace vcpkg::Build continue; } + if (variable_name == "VCPKG_CHAINLOAD_TOOLCHAIN_FILE") + { + pre_build_info.external_toolchain_file = + variable_value.empty() ? nullopt : Optional{variable_value}; + continue; + } + Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown variable name %s", line); } diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp index 98b5aced9..6e52383d8 100644 --- a/toolsrc/src/vcpkg/commands.env.cpp +++ b/toolsrc/src/vcpkg/commands.env.cpp @@ -20,7 +20,7 @@ namespace vcpkg::Commands::Env args.parse_arguments(COMMAND_STRUCTURE); const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); - const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); + const Toolset& toolset = paths.get_toolset(pre_build_info); System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, toolset) + " && cmd"); Checks::exit_success(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index f237c72f8..32cb6f03e 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -290,7 +290,7 @@ namespace vcpkg::Export {OPTION_IFW_INSTALLER_FILE_PATH, "Specify the file path for the exported installer"}, }}; - const CommandStructure vcpkg::Export::COMMAND_STRUCTURE = { + const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("export zlib zlib:x64-windows boost --nuget"), 0, SIZE_MAX, diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 249e36e0f..0888e21d5 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -561,7 +561,7 @@ namespace vcpkg::Install static void print_cmake_information(const BinaryParagraph& bpgh, const VcpkgPaths& paths) { - static const std::regex cmake_library_regex("^add_library\\(([^\\s\\$\\)]+)\\s"); + static const std::regex cmake_library_regex(R"(\badd_library\(([^\s\)]+)\s)", std::regex_constants::ECMAScript); auto& fs = paths.get_filesystem(); diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp index 1f13c0a4f..10af41bb0 100644 --- a/toolsrc/src/vcpkg/postbuildlint.cpp +++ b/toolsrc/src/vcpkg/postbuildlint.cpp @@ -726,7 +726,7 @@ namespace vcpkg::PostBuildLint const auto& fs = paths.get_filesystem(); // for dumpbin - const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); + const Toolset& toolset = paths.get_toolset(pre_build_info); const fs::path package_dir = paths.package_dir(spec); size_t error_count = 0; diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 7c4d41815..0114b51b8 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -115,11 +116,13 @@ namespace vcpkg static constexpr std::array EXPECTED_VERSION = {3, 9, 5}; static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - const fs::path downloaded_copy = downloads_folder / "cmake-3.9.5-win32-x86" / "bin" / "cmake.exe"; const std::vector from_path = Files::find_from_PATH("cmake"); std::vector candidate_paths; + const fs::path downloaded_copy = downloads_folder / "cmake-3.9.5-win32-x86" / "bin" / "cmake.exe"; +#if defined(_WIN32) candidate_paths.push_back(downloaded_copy); +#endif candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); #if defined(_WIN32) candidate_paths.push_back(System::get_program_files_platform_bitness() / "CMake" / "bin" / "cmake.exe"); @@ -161,11 +164,13 @@ namespace vcpkg static constexpr std::array EXPECTED_VERSION = {2, 15, 0}; static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - const fs::path downloaded_copy = downloads_folder / "MinGit-2.15.0-32-bit" / "cmd" / "git.exe"; const std::vector from_path = Files::find_from_PATH("git"); + const fs::path downloaded_copy = downloads_folder / "MinGit-2.15.0-32-bit" / "cmd" / "git.exe"; std::vector candidate_paths; +#if defined(_WIN32) candidate_paths.push_back(downloaded_copy); +#endif candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); #if defined(_WIN32) candidate_paths.push_back(System::get_program_files_platform_bitness() / "git" / "cmd" / "git.exe"); @@ -499,16 +504,36 @@ namespace vcpkg return found_toolsets; } - const Toolset& VcpkgPaths::get_toolset(const Optional& toolset_version, - const Optional& visual_studio_path) const + const Toolset& VcpkgPaths::get_toolset(const Build::PreBuildInfo& prebuildinfo) const { + if (prebuildinfo.external_toolchain_file) + { + static Toolset external_toolset = []() -> Toolset { + Toolset ret; + ret.dumpbin = ""; + ret.supported_architectures = { + ToolsetArchOption{"", System::get_host_processor(), System::get_host_processor()}}; +#if defined(_WIN32) + ret.vcvarsall = "cmd"; + ret.vcvarsall_options = {"/c", "echo done"}; +#else + ret.vcvarsall = "true"; + ret.vcvarsall_options = {}; +#endif + ret.version = "external"; + ret.visual_studio_root_path = ""; + return ret; + }(); + return external_toolset; + } + // Invariant: toolsets are non-empty and sorted with newest at back() const std::vector& vs_toolsets = this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); std::vector candidates = Util::element_pointers(vs_toolsets); - const auto tsv = toolset_version.get(); - const auto vsp = visual_studio_path.get(); + const auto tsv = prebuildinfo.platform_toolset.get(); + const auto vsp = prebuildinfo.visual_studio_path.get(); if (tsv && vsp) { -- cgit v1.2.3 From 5335d17f53d491d83d98e80ab0e750ec0f6f430b Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 25 Nov 2017 15:25:18 -0800 Subject: [vcpkg] Initial experimental support for VCPKG_BUILD_TYPE release --- toolsrc/src/vcpkg/build.cpp | 14 ++++++++++++++ toolsrc/src/vcpkg/postbuildlint.buildtype.cpp | 2 ++ toolsrc/src/vcpkg/postbuildlint.cpp | 22 ++++++++++++---------- 3 files changed, 28 insertions(+), 10 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index fd605ac08..6ef72b639 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -565,6 +565,20 @@ namespace vcpkg::Build continue; } + if (variable_name == "VCPKG_BUILD_TYPE") + { + if (variable_value.empty()) + pre_build_info.build_type = nullopt; + else if (Strings::case_insensitive_ascii_equals(variable_value, "debug")) + pre_build_info.build_type = ConfigurationType::DEBUG; + else if (Strings::case_insensitive_ascii_equals(variable_value, "release")) + pre_build_info.build_type = ConfigurationType::RELEASE; + else + Checks::exit_with_message( + VCPKG_LINE_INFO, "Unknown setting for VCPKG_BUILD_TYPE: %s", variable_value); + continue; + } + Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown variable name %s", line); } diff --git a/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp b/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp index 2baaddb5e..e966ce78a 100644 --- a/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp +++ b/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp @@ -3,6 +3,8 @@ #include #include +using vcpkg::Build::ConfigurationType; + namespace vcpkg::PostBuildLint { BuildType BuildType::value_of(const ConfigurationType& config, const Build::LinkageType& linkage) diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp index 10af41bb0..0532bce58 100644 --- a/toolsrc/src/vcpkg/postbuildlint.cpp +++ b/toolsrc/src/vcpkg/postbuildlint.cpp @@ -758,7 +758,8 @@ namespace vcpkg::PostBuildLint std::vector release_libs = fs.get_files_recursive(release_lib_dir); Util::unstable_keep_if(release_libs, has_extension_pred(fs, ".lib")); - error_count += check_matching_debug_and_release_binaries(debug_libs, release_libs); + if (!pre_build_info.build_type) + error_count += check_matching_debug_and_release_binaries(debug_libs, release_libs); { std::vector libs; @@ -777,7 +778,8 @@ namespace vcpkg::PostBuildLint { case Build::LinkageType::DYNAMIC: { - error_count += check_matching_debug_and_release_binaries(debug_dlls, release_dlls); + if (!pre_build_info.build_type) + error_count += check_matching_debug_and_release_binaries(debug_dlls, release_dlls); error_count += check_lib_files_are_available_if_dlls_are_available( build_info.policies, debug_libs.size(), debug_dlls.size(), debug_lib_dir); @@ -805,15 +807,15 @@ namespace vcpkg::PostBuildLint if (!build_info.policies.is_enabled(BuildPolicy::ONLY_RELEASE_CRT)) { - error_count += - check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::DEBUG, build_info.crt_linkage), - debug_libs, - toolset.dumpbin); + error_count += check_crt_linkage_of_libs( + BuildType::value_of(Build::ConfigurationType::DEBUG, build_info.crt_linkage), + debug_libs, + toolset.dumpbin); } - error_count += - check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::RELEASE, build_info.crt_linkage), - release_libs, - toolset.dumpbin); + error_count += check_crt_linkage_of_libs( + BuildType::value_of(Build::ConfigurationType::RELEASE, build_info.crt_linkage), + release_libs, + toolset.dumpbin); break; } default: Checks::unreachable(VCPKG_LINE_INFO); -- cgit v1.2.3 From 14cbe496bcc136aac590f10d79848ec224088e85 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 25 Nov 2017 15:53:32 -0800 Subject: [vcpkg] Allow compilation inside WSL --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 0114b51b8..016f26f6d 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -113,7 +113,11 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { +#if defined(_WIN32) static constexpr std::array EXPECTED_VERSION = {3, 9, 5}; +#else + static constexpr std::array EXPECTED_VERSION = {3, 5, 1}; +#endif static const std::string VERSION_CHECK_ARGUMENTS = "--version"; const std::vector from_path = Files::find_from_PATH("cmake"); @@ -161,7 +165,11 @@ namespace vcpkg fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { +#if defined(_WIN32) static constexpr std::array EXPECTED_VERSION = {2, 15, 0}; +#else + static constexpr std::array EXPECTED_VERSION = {2, 7, 4}; +#endif static const std::string VERSION_CHECK_ARGUMENTS = "--version"; const std::vector from_path = Files::find_from_PATH("git"); -- cgit v1.2.3 From 2af7fe8690a9b78f1eab1e532670ed133f82aff9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sun, 26 Nov 2017 02:49:23 -0800 Subject: Add System::powershell_execute() --- toolsrc/src/vcpkg/base/system.cpp | 43 +++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 9d8e1ce84..e3d3ad292 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -119,6 +119,16 @@ namespace vcpkg::System { } + static std::string make_powershell_cmd(const fs::path& script_path, + const std::vector& parameters) + { + const std::string args = Strings::join(" ", parameters, [](auto&& v) { return v.s; }); + + // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned + return Strings::format( + R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args); + } + int cmd_execute_clean(const CStringView cmd_line) { #if defined(_WIN32) @@ -317,16 +327,37 @@ namespace vcpkg::System #endif } + void powershell_execute(const std::string& title, + const fs::path& script_path, + const std::vector& parameters) + { + const std::string cmd = make_powershell_cmd(script_path, parameters); + const int rc = System::cmd_execute(cmd); + + if (rc) + { + System::println(Color::error, + "%s\n" + "Could not run:\n" + " '%s'", + title, + script_path.generic_string()); + + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_property("error", "powershell script failed"); + locked_metrics->track_property("title", title); + } + + Checks::exit_with_code(VCPKG_LINE_INFO, rc); + } + } + std::string powershell_execute_and_capture_output(const std::string& title, const fs::path& script_path, const std::vector& parameters) { - const std::string args = Strings::join(" ", parameters, [](auto&& v) { return v.s; }); - - // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned - const std::string cmd = Strings::format( - R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args); - + const std::string cmd = make_powershell_cmd(script_path, parameters); auto rc = System::cmd_execute_and_capture_output(cmd); if (rc.exit_code) -- cgit v1.2.3 From e009618ba0850ef54e837e8fb76910245d99b456 Mon Sep 17 00:00:00 2001 From: Mikhail Paulyshka Date: Sun, 26 Nov 2017 14:18:35 +0300 Subject: [cmake] update to 3.10.0 (#2236) --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 016f26f6d..d5763921e 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -114,7 +114,7 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { #if defined(_WIN32) - static constexpr std::array EXPECTED_VERSION = {3, 9, 5}; + static constexpr std::array EXPECTED_VERSION = {3, 10, 0}; #else static constexpr std::array EXPECTED_VERSION = {3, 5, 1}; #endif @@ -123,7 +123,7 @@ namespace vcpkg const std::vector from_path = Files::find_from_PATH("cmake"); std::vector candidate_paths; - const fs::path downloaded_copy = downloads_folder / "cmake-3.9.5-win32-x86" / "bin" / "cmake.exe"; + const fs::path downloaded_copy = downloads_folder / "cmake-3.10.0-win32-x86" / "bin" / "cmake.exe"; #if defined(_WIN32) candidate_paths.push_back(downloaded_copy); #endif -- cgit v1.2.3 From d38d4a75408e0e9d0820187b16da2e06ce0ee316 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 29 Nov 2017 23:45:47 -0800 Subject: [vcpkg] Add --x-xunit internal command to print installation results in a VSTS friendly format. --- toolsrc/src/vcpkg.cpp | 2 +- toolsrc/src/vcpkg/base/chrono.cpp | 8 ++-- toolsrc/src/vcpkg/build.cpp | 4 +- toolsrc/src/vcpkg/commands.ci.cpp | 16 +++++++- toolsrc/src/vcpkg/commands.integrate.cpp | 2 +- toolsrc/src/vcpkg/commands.portsdiff.cpp | 6 +-- toolsrc/src/vcpkg/globalstate.cpp | 2 +- toolsrc/src/vcpkg/install.cpp | 69 +++++++++++++++++++++++++++----- toolsrc/src/vcpkg/postbuildlint.cpp | 2 +- 9 files changed, 89 insertions(+), 22 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 5642f937c..04d44c414 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -255,7 +255,7 @@ int main(const int argc, const char* const* const argv) { if (argc == 0) std::abort(); - *GlobalState::timer.lock() = Chrono::ElapsedTime::create_started(); + *GlobalState::timer.lock() = Chrono::ElapsedTimer::create_started(); #if defined(_WIN32) GlobalState::g_init_console_cp = GetConsoleCP(); diff --git a/toolsrc/src/vcpkg/base/chrono.cpp b/toolsrc/src/vcpkg/base/chrono.cpp index 5d28909fc..f0e450231 100644 --- a/toolsrc/src/vcpkg/base/chrono.cpp +++ b/toolsrc/src/vcpkg/base/chrono.cpp @@ -50,12 +50,14 @@ namespace vcpkg::Chrono return Strings::format("%.4g ns", nanos_as_double); } - ElapsedTime ElapsedTime::create_started() + ElapsedTimer ElapsedTimer::create_started() { - ElapsedTime t; + ElapsedTimer t; t.m_start_tick = std::chrono::high_resolution_clock::now(); return t; } - std::string ElapsedTime::to_string() const { return format_time_userfriendly(elapsed()); } + std::string ElapsedTime::to_string() const { return format_time_userfriendly(as()); } + + std::string ElapsedTimer::to_string() const { return elapsed().to_string(); } } diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 6ef72b639..b8f122b27 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -67,7 +67,7 @@ namespace vcpkg::Build::Command const Build::BuildPackageConfig build_config{ *scf, spec.triplet(), fs::path{port_dir}, build_package_options, features_as_set}; - const auto build_timer = Chrono::ElapsedTime::create_started(); + const auto build_timer = Chrono::ElapsedTimer::create_started(); const auto result = Build::build_package(paths, build_config, status_db); System::println("Elapsed time for package %s: %s", spec.to_string(), build_timer.to_string()); @@ -323,7 +323,7 @@ namespace vcpkg::Build const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); const std::string command = Strings::format(R"(%s && %s)", cmd_set_environment, cmd_launch_cmake); - const auto timer = Chrono::ElapsedTime::create_started(); + const auto timer = Chrono::ElapsedTimer::create_started(); const int return_code = System::cmd_execute_clean(command); const auto buildtimeus = timer.microseconds(); diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 8f79b83e1..f2e984bf8 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -63,9 +63,11 @@ namespace vcpkg::Commands::CI }; static const std::string OPTION_EXCLUDE = "--exclude"; + static const std::string OPTION_XUNIT = "--x-xunit"; - static const std::array CI_SETTINGS = {{ + static const std::array CI_SETTINGS = {{ {OPTION_EXCLUDE, "Comma separated list of ports to skip"}, + {OPTION_XUNIT, "File to output results in XUnit format (internal)"}, }}; const CommandStructure COMMAND_STRUCTURE = { @@ -114,6 +116,18 @@ namespace vcpkg::Commands::CI result.summary.print(); } + auto it_xunit = options.settings.find(OPTION_XUNIT); + if (it_xunit != options.settings.end()) + { + std::string xunit_doc = "\n"; + + for (auto&& result : results) + xunit_doc += result.summary.xunit_results(); + + xunit_doc += "\n"; + paths.get_filesystem().write_contents(fs::u8path(it_xunit->second), xunit_doc); + } + Checks::exit_success(VCPKG_LINE_INFO); } } diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index f13a999fa..66c5eb5a9 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -257,7 +257,7 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")", std::error_code ec; const bool was_deleted = fs.remove(path, ec); - Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %d", ec.message()); + Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %s", ec.message()); if (was_deleted) { diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp index 0277c8bdb..6752715e4 100644 --- a/toolsrc/src/vcpkg/commands.portsdiff.cpp +++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp @@ -151,14 +151,14 @@ namespace vcpkg::Commands::PortsDiff const std::vector& added_ports = setp.only_left; if (!added_ports.empty()) { - System::println("\nThe following %d ports were added:", added_ports.size()); + System::println("\nThe following %zd ports were added:", added_ports.size()); do_print_name_and_version(added_ports, current_names_and_versions); } const std::vector& removed_ports = setp.only_right; if (!removed_ports.empty()) { - System::println("\nThe following %d ports were removed:", removed_ports.size()); + System::println("\nThe following %zd ports were removed:", removed_ports.size()); do_print_name_and_version(removed_ports, previous_names_and_versions); } @@ -168,7 +168,7 @@ namespace vcpkg::Commands::PortsDiff if (!updated_ports.empty()) { - System::println("\nThe following %d ports were updated:", updated_ports.size()); + System::println("\nThe following %zd ports were updated:", updated_ports.size()); for (const UpdatedPort& p : updated_ports) { System::println(" - %-14s %-16s", p.port, p.version_diff.to_string()); diff --git a/toolsrc/src/vcpkg/globalstate.cpp b/toolsrc/src/vcpkg/globalstate.cpp index 43230fa4b..149401b2c 100644 --- a/toolsrc/src/vcpkg/globalstate.cpp +++ b/toolsrc/src/vcpkg/globalstate.cpp @@ -4,7 +4,7 @@ namespace vcpkg { - Util::LockGuarded GlobalState::timer; + Util::LockGuarded GlobalState::timer; std::atomic GlobalState::debugging(false); std::atomic GlobalState::feature_packages(false); diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 0888e21d5..76dc7a527 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -484,18 +484,18 @@ namespace vcpkg::Install { std::vector results; - const auto timer = Chrono::ElapsedTime::create_started(); + const auto timer = Chrono::ElapsedTimer::create_started(); size_t counter = 0; const size_t package_count = action_plan.size(); for (const auto& action : action_plan) { - const auto build_timer = Chrono::ElapsedTime::create_started(); + const auto build_timer = Chrono::ElapsedTimer::create_started(); counter++; const PackageSpec& spec = action.spec(); const std::string display_name = spec.to_string(); - System::println("Starting package %d/%d: %s", counter, package_count, display_name); + System::println("Starting package %zd/%zd: %s", counter, package_count, display_name); results.emplace_back(spec, &action); @@ -521,8 +521,8 @@ namespace vcpkg::Install Checks::unreachable(VCPKG_LINE_INFO); } - results.back().timing = build_timer.to_string(); - System::println("Elapsed time for package %s: %s", display_name, build_timer.to_string()); + results.back().timing = build_timer.elapsed(); + System::println("Elapsed time for package %s: %s", display_name, results.back().timing.to_string()); } return InstallSummary{std::move(results), timer.to_string()}; @@ -533,6 +533,7 @@ namespace vcpkg::Install static const std::string OPTION_NO_DOWNLOADS = "--no-downloads"; static const std::string OPTION_RECURSE = "--recurse"; static const std::string OPTION_KEEP_GOING = "--keep-going"; + static const std::string OPTION_XUNIT = "--x-xunit"; static const std::array INSTALL_SWITCHES = {{ {OPTION_DRY_RUN, "Do not actually build or install"}, @@ -541,7 +542,9 @@ namespace vcpkg::Install {OPTION_RECURSE, "Allow removal of packages as part of installation"}, {OPTION_KEEP_GOING, "Continue installing packages on failure"}, }}; - static const std::array INSTALL_SETTINGS; + static const std::array INSTALL_SETTINGS = {{ + {OPTION_XUNIT, "File to output results in XUnit format (Internal use)"}, + }}; std::vector get_all_port_names(const VcpkgPaths& paths) { @@ -555,7 +558,7 @@ namespace vcpkg::Install Help::create_example_string("install zlib zlib:x64-windows curl boost"), 1, SIZE_MAX, - {INSTALL_SWITCHES, {}}, + {INSTALL_SWITCHES, INSTALL_SETTINGS}, &get_all_port_names, }; @@ -627,7 +630,7 @@ namespace vcpkg::Install library_target_pair.second.erase(library_target_pair.second.begin() + 4, library_target_pair.second.end()); System::println(" find_package(%s REQUIRED)\n" - " # Note: %d targets were omitted\n" + " # Note: %zd targets were omitted\n" " target_link_libraries(main PRIVATE %s)\n", library_target_pair.first, omitted, @@ -735,6 +738,17 @@ namespace vcpkg::Install summary.print(); } + auto it_xunit = options.settings.find(OPTION_XUNIT); + if (it_xunit != options.settings.end()) + { + std::string xunit_doc = "\n"; + + xunit_doc += summary.xunit_results(); + + xunit_doc += "\n"; + paths.get_filesystem().write_contents(fs::u8path(it_xunit->second), xunit_doc); + } + for (auto&& result : summary.results) { if (!result.action) continue; @@ -751,7 +765,7 @@ namespace vcpkg::Install } SpecSummary::SpecSummary(const PackageSpec& spec, const Dependencies::AnyAction* action) - : spec(spec), build_result{BuildResult::NULLVALUE, nullptr}, timing("0"), action(action) + : spec(spec), build_result{BuildResult::NULLVALUE, nullptr}, action(action) { } @@ -770,4 +784,41 @@ namespace vcpkg::Install } return nullptr; } + + std::string InstallSummary::xunit_results() const + { + std::string xunit_doc; + for (auto&& result : results) + { + std::string inner_block; + const char* result_string = ""; + switch (result.build_result.code) + { + case BuildResult::POST_BUILD_CHECKS_FAILED: + case BuildResult::FILE_CONFLICTS: + case BuildResult::BUILD_FAILED: + result_string = "Fail"; + inner_block = Strings::format("", + to_string(result.build_result.code)); + break; + case BuildResult::EXCLUDED: + case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: + result_string = "Skip"; + inner_block = + Strings::format("", to_string(result.build_result.code)); + break; + case BuildResult::SUCCEEDED: result_string = "Pass"; break; + default: Checks::exit_fail(VCPKG_LINE_INFO); + } + + xunit_doc += Strings::format(R"(%s)" + "\n", + result.spec, + result.spec, + result.timing.as().count(), + result_string, + inner_block); + } + return xunit_doc; + } } diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp index 0532bce58..2b427737a 100644 --- a/toolsrc/src/vcpkg/postbuildlint.cpp +++ b/toolsrc/src/vcpkg/postbuildlint.cpp @@ -479,7 +479,7 @@ namespace vcpkg::PostBuildLint } System::println(System::Color::warning, - "Mismatching number of debug and release binaries. Found %d for debug but %d for release.", + "Mismatching number of debug and release binaries. Found %zd for debug but %zd for release.", debug_count, release_count); System::println("Debug binaries"); -- cgit v1.2.3 From c9642097a8aa85c652daed2fc28e6a828688801e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 30 Nov 2017 21:44:34 -0800 Subject: Specify VSLANG=1033 to use english locale in builds Resolves several locale-specific issues outside our control --- toolsrc/src/vcpkg/base/system.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index e3d3ad292..8dd73c32f 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -202,6 +202,7 @@ namespace vcpkg::System env_cstr.append(Strings::to_utf16(NEW_PATH)); env_cstr.push_back(L'\0'); + env_cstr.append(L"VSLANG=1033\0"); STARTUPINFOW startup_info; memset(&startup_info, 0, sizeof(STARTUPINFOW)); -- cgit v1.2.3 From f174d5561af49cccbfb4d9618be123cf7ee971d6 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 30 Nov 2017 21:46:23 -0800 Subject: Exclude and warn about VS instances without English language pack Resolves several locale-specific issues outside our control --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 64 ++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 15 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index d5763921e..324ca29d1 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -280,7 +280,6 @@ namespace vcpkg const std::vector& VcpkgPaths::get_available_triplets() const { return this->available_triplets.get_lazy([this]() -> std::vector { - std::vector output; for (auto&& path : this->get_filesystem().get_files_non_recursive(this->triplets)) { @@ -384,6 +383,7 @@ namespace vcpkg std::vector paths_examined; std::vector found_toolsets; + std::vector excluded_toolsets; const std::vector vs_instances = get_visual_studio_instances(paths); const bool v140_is_available = Util::find_if(vs_instances, [&](const VisualStudioInstance& vs_instance) { @@ -440,17 +440,28 @@ namespace vcpkg paths_examined.push_back(dumpbin_path); if (fs.exists(dumpbin_path)) { - found_toolsets.push_back(Toolset{ - vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}); + const Toolset v141toolset = Toolset{ + vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}; + + auto english_language_pack = dumpbin_path.parent_path() / "1033"; + + if (!fs.exists(english_language_pack)) + { + excluded_toolsets.push_back(v141toolset); + break; + } + + found_toolsets.push_back(v141toolset); if (v140_is_available) { - found_toolsets.push_back(Toolset{vs_instance.root_path, - dumpbin_path, - vcvarsall_bat, - {"-vcvars_ver=14.0"}, - V_140, - supported_architectures}); + const Toolset v140toolset = Toolset{vs_instance.root_path, + dumpbin_path, + vcvarsall_bat, + {"-vcvars_ver=14.0"}, + V_140, + supported_architectures}; + found_toolsets.push_back(v140toolset); } break; @@ -487,17 +498,39 @@ namespace vcpkg if (fs.exists(vs_dumpbin_exe)) { - found_toolsets.push_back({vs_instance.root_path, - vs_dumpbin_exe, - vcvarsall_bat, - {}, - major_version == "14" ? V_140 : V_120, - supported_architectures}); + const Toolset toolset = {vs_instance.root_path, + vs_dumpbin_exe, + vcvarsall_bat, + {}, + major_version == "14" ? V_140 : V_120, + supported_architectures}; + + auto english_language_pack = vs_dumpbin_exe.parent_path() / "1033"; + + if (!fs.exists(english_language_pack)) + { + excluded_toolsets.push_back(toolset); + break; + } + + found_toolsets.push_back(toolset); } } } } + if (!excluded_toolsets.empty()) + { + System::println( + System::Color::warning, + "Warning: The following VS instances are exluded because the English language pack is unavailable."); + for (const Toolset& toolset : excluded_toolsets) + { + System::println(" %s", toolset.visual_studio_root_path.u8string()); + } + System::println(System::Color::warning, "Please install the English language pack."); + } + if (found_toolsets.empty()) { System::println(System::Color::error, "Could not locate a complete toolset."); @@ -575,6 +608,7 @@ namespace vcpkg vs_root_path.generic_string()); } + Checks::check_exit(VCPKG_LINE_INFO, !candidates.empty(), "No suitable Visual Studio instances were found"); return *candidates.front(); } -- cgit v1.2.3 From 88d953a88d7061c4c49a5cb3d6323bb8f4442521 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Dec 2017 05:57:47 -0800 Subject: [hotfix] Remove VSLANG=1033. It is causing a lot of Process creation failed with error code: 87 --- toolsrc/src/vcpkg/base/system.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 8dd73c32f..8684cefe2 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -202,7 +202,7 @@ namespace vcpkg::System env_cstr.append(Strings::to_utf16(NEW_PATH)); env_cstr.push_back(L'\0'); - env_cstr.append(L"VSLANG=1033\0"); + // env_cstr.append(L"VSLANG=1033\0"); STARTUPINFOW startup_info; memset(&startup_info, 0, sizeof(STARTUPINFOW)); -- cgit v1.2.3 From d3314dfd4ea773509588084febd8ce48fe1589fa Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 1 Dec 2017 06:09:56 -0800 Subject: Properly fix VSLANG=1033 --- toolsrc/src/vcpkg/base/system.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 8684cefe2..625ee6ce0 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -202,7 +202,8 @@ namespace vcpkg::System env_cstr.append(Strings::to_utf16(NEW_PATH)); env_cstr.push_back(L'\0'); - // env_cstr.append(L"VSLANG=1033\0"); + env_cstr.append(L"VSLANG=1033"); + env_cstr.push_back(L'\0'); STARTUPINFOW startup_info; memset(&startup_info, 0, sizeof(STARTUPINFOW)); -- cgit v1.2.3 From 71f8958a069208b08a4bcca207956ef8a15238ab Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 1 Dec 2017 16:08:09 -0800 Subject: [vcpkg-contact-survey] Add monthly survey prompt --- toolsrc/src/tests.chrono.cpp | 41 +++++++++++++++ toolsrc/src/vcpkg.cpp | 95 ++++++++++++++-------------------- toolsrc/src/vcpkg/base/chrono.cpp | 62 ++++++++++++++++++++++ toolsrc/src/vcpkg/commands.contact.cpp | 13 +++++ toolsrc/src/vcpkg/globalstate.cpp | 2 + toolsrc/src/vcpkg/metrics.cpp | 28 ++-------- toolsrc/src/vcpkg/userconfig.cpp | 83 +++++++++++++++++++++++++++++ 7 files changed, 246 insertions(+), 78 deletions(-) create mode 100644 toolsrc/src/tests.chrono.cpp create mode 100644 toolsrc/src/vcpkg/userconfig.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.chrono.cpp b/toolsrc/src/tests.chrono.cpp new file mode 100644 index 000000000..269cdca58 --- /dev/null +++ b/toolsrc/src/tests.chrono.cpp @@ -0,0 +1,41 @@ +#include "tests.pch.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace Chrono = vcpkg::Chrono; + +namespace UnitTest1 +{ + class ChronoTests : public TestClass + { + TEST_METHOD(parse_time) + { + auto timestring = "1990-02-03T04:05:06.0Z"; + auto maybe_time = Chrono::CTime::parse(timestring); + + Assert::IsTrue(maybe_time.has_value()); + + Assert::AreEqual(timestring, maybe_time.get()->to_string().c_str()); + } + + TEST_METHOD(parse_time_blank) + { + auto maybe_time = Chrono::CTime::parse(""); + + Assert::IsFalse(maybe_time.has_value()); + } + + TEST_METHOD(time_difference) + { + auto maybe_time1 = Chrono::CTime::parse("1990-02-03T04:05:06.0Z"); + auto maybe_time2 = Chrono::CTime::parse("1990-02-10T04:05:06.0Z"); + + Assert::IsTrue(maybe_time1.has_value()); + Assert::IsTrue(maybe_time2.has_value()); + + auto delta = maybe_time2.get()->to_time_point() - maybe_time1.get()->to_time_point(); + + Assert::AreEqual(24 * 7, std::chrono::duration_cast(delta).count()); + } + }; +} diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 04d44c414..094ea1dc5 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -20,11 +20,13 @@ #include #include #include +#include #include #include #include #include +#include #pragma comment(lib, "ole32") #pragma comment(lib, "shell32") @@ -110,6 +112,28 @@ static void inner(const VcpkgCmdArguments& args) if (args.command != "autocomplete") { Commands::Version::warn_if_vcpkg_version_mismatch(paths); + std::string surveydate = *GlobalState::g_surveydate.lock(); + auto maybe_surveydate = Chrono::CTime::parse(surveydate); + if (auto p_surveydate = maybe_surveydate.get()) + { + auto delta = std::chrono::system_clock::now() - p_surveydate->to_time_point(); + // 24 hours/day * 30 days/month + if (std::chrono::duration_cast(delta).count() > 24 * 30) + { + std::default_random_engine generator( + static_cast(std::chrono::system_clock::now().time_since_epoch().count())); + std::uniform_int_distribution distribution(1, 4); + + if (distribution(generator) == 1) + { + Metrics::g_metrics.lock()->track_property("surveyprompt", "true"); + System::println( + System::Color::success, + "Your feedback is important to improve Vcpkg! Please take 3 minutes to complete our survey " + "by running: vcpkg contact --survey"); + } + } + } } if (const auto command_function = find_command(Commands::get_available_commands_type_b())) @@ -148,80 +172,41 @@ static void inner(const VcpkgCmdArguments& args) static void load_config() { #if defined(_WIN32) - fs::path localappdata; - { - // Config path in AppDataLocal - wchar_t* localappdatapath = nullptr; - if (S_OK != SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &localappdatapath)) __fastfail(1); - localappdata = localappdatapath; - CoTaskMemFree(localappdatapath); - } - - std::string user_id, user_time, user_mac; - try - { - auto maybe_pghs = Paragraphs::get_paragraphs(Files::get_real_filesystem(), localappdata / "vcpkg" / "config"); - if (const auto p_pghs = maybe_pghs.get()) - { - const auto& pghs = *p_pghs; + auto& fs = Files::get_real_filesystem(); - std::unordered_map keys; - if (pghs.size() > 0) keys = pghs[0]; - - for (size_t x = 1; x < pghs.size(); ++x) - { - for (auto&& p : pghs[x]) - keys.insert(p); - } - - user_id = keys["User-Id"]; - user_time = keys["User-Since"]; - user_mac = keys["Mac-Hash"]; - } - } - catch (...) - { - } + auto config = UserConfig::try_read_data(fs); bool write_config = false; // config file not found, could not be read, or invalid - if (user_id.empty() || user_time.empty()) + if (config.user_id.empty() || config.user_time.empty()) { - ::vcpkg::Metrics::Metrics::init_user_information(user_id, user_time); + ::vcpkg::Metrics::Metrics::init_user_information(config.user_id, config.user_time); write_config = true; } - if (user_mac.empty()) + if (config.user_mac.empty()) { - user_mac = Metrics::get_MAC_user(); + config.user_mac = Metrics::get_MAC_user(); write_config = true; } { auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->set_user_information(user_id, user_time); - locked_metrics->track_property("user_mac", user_mac); + locked_metrics->set_user_information(config.user_id, config.user_time); + locked_metrics->track_property("user_mac", config.user_mac); } + if (config.last_completed_survey.empty()) + { + config.last_completed_survey = config.user_time; + } + + GlobalState::g_surveydate.lock()->assign(config.last_completed_survey); + if (write_config) { - try - { - std::error_code ec; - auto& fs = Files::get_real_filesystem(); - fs.create_directory(localappdata / "vcpkg", ec); - fs.write_contents(localappdata / "vcpkg" / "config", - Strings::format("User-Id: %s\n" - "User-Since: %s\n" - "Mac-Hash: %s\n", - user_id, - user_time, - user_mac)); - } - catch (...) - { - } + config.try_write_data(fs); } #endif } diff --git a/toolsrc/src/vcpkg/base/chrono.cpp b/toolsrc/src/vcpkg/base/chrono.cpp index f0e450231..03c1ecce9 100644 --- a/toolsrc/src/vcpkg/base/chrono.cpp +++ b/toolsrc/src/vcpkg/base/chrono.cpp @@ -60,4 +60,66 @@ namespace vcpkg::Chrono std::string ElapsedTime::to_string() const { return format_time_userfriendly(as()); } std::string ElapsedTimer::to_string() const { return elapsed().to_string(); } + + Optional CTime::get_current_date_time() + { + CTime ret; + +#if defined(_WIN32) + struct _timeb timebuffer; + + _ftime_s(&timebuffer); + + const errno_t err = gmtime_s(&ret.m_tm, &timebuffer.time); + + if (err) + { + return nullopt; + } +#else + time_t now = {0}; + time(&now); + auto null_if_failed = gmtime_r(&now, &ret.m_tm); + if (null_if_failed == nullptr) + { + return nullopt; + } +#endif + + return ret; + } + + Optional CTime::parse(CStringView str) + { + CTime ret; + auto assigned = sscanf_s(str.c_str(), + "%d-%d-%dT%d:%d:%d.", + &ret.m_tm.tm_year, + &ret.m_tm.tm_mon, + &ret.m_tm.tm_mday, + &ret.m_tm.tm_hour, + &ret.m_tm.tm_min, + &ret.m_tm.tm_sec); + if (assigned != 6) return nullopt; + if (ret.m_tm.tm_year < 1900) return nullopt; + ret.m_tm.tm_year -= 1900; + if (ret.m_tm.tm_mon < 1) return nullopt; + ret.m_tm.tm_mon -= 1; + mktime(&ret.m_tm); + return ret; + } + + std::string CTime::to_string() const + { + std::array date; + date.fill(0); + + strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S.0Z", &m_tm); + return &date[0]; + } + std::chrono::system_clock::time_point CTime::to_time_point() const + { + auto t = mktime(&m_tm); + return std::chrono::system_clock::from_time_t(t); + } } diff --git a/toolsrc/src/vcpkg/commands.contact.cpp b/toolsrc/src/vcpkg/commands.contact.cpp index 07dcea80e..8063fe317 100644 --- a/toolsrc/src/vcpkg/commands.contact.cpp +++ b/toolsrc/src/vcpkg/commands.contact.cpp @@ -1,8 +1,10 @@ #include "pch.h" +#include #include #include #include +#include namespace vcpkg::Commands::Contact { @@ -28,6 +30,17 @@ namespace vcpkg::Commands::Contact if (Util::Sets::contains(parsed_args.switches, switches[0].name)) { +#if defined(_WIN32) + auto maybe_now = Chrono::CTime::get_current_date_time(); + if (auto p_now = maybe_now.get()) + { + auto& fs = Files::get_real_filesystem(); + auto config = UserConfig::try_read_data(fs); + config.last_completed_survey = p_now->to_string(); + config.try_write_data(fs); + } +#endif + System::cmd_execute("start https://aka.ms/NPS_vcpkg"); System::println("Default browser launched to https://aka.ms/NPS_vcpkg, thank you for your feedback!"); } diff --git a/toolsrc/src/vcpkg/globalstate.cpp b/toolsrc/src/vcpkg/globalstate.cpp index 149401b2c..123c77d46 100644 --- a/toolsrc/src/vcpkg/globalstate.cpp +++ b/toolsrc/src/vcpkg/globalstate.cpp @@ -5,6 +5,8 @@ namespace vcpkg { Util::LockGuarded GlobalState::timer; + Util::LockGuarded GlobalState::g_surveydate; + std::atomic GlobalState::debugging(false); std::atomic GlobalState::feature_packages(false); diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 69160705c..a0d40e7d3 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -2,6 +2,7 @@ #include +#include #include #include #include @@ -15,32 +16,13 @@ namespace vcpkg::Metrics static std::string get_current_date_time() { - struct tm newtime; - std::array date; - date.fill(0); - -#if defined(_WIN32) - struct _timeb timebuffer; - - _ftime_s(&timebuffer); - time_t now = timebuffer.time; - const int milli = timebuffer.millitm; - - const errno_t err = gmtime_s(&newtime, &now); - - if (err) + auto maybe_time = Chrono::CTime::get_current_date_time(); + if (auto ptime = maybe_time.get()) { - return ""; + return ptime->to_string(); } -#else - time_t now; - time(&now); - gmtime_r(&now, &newtime); - const int milli = 0; -#endif - strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S", &newtime); - return std::string(&date[0]) + "." + std::to_string(milli) + "Z"; + return ""; } static std::string generate_random_UUID() diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp new file mode 100644 index 000000000..d13a46f41 --- /dev/null +++ b/toolsrc/src/vcpkg/userconfig.cpp @@ -0,0 +1,83 @@ +#include "pch.h" + +#include +#include +#include +#include + +namespace +{ + static vcpkg::Lazy s_localappdata; + + static const fs::path& get_localappdata() + { + return s_localappdata.get_lazy([]() { + fs::path localappdata; + { + // Config path in AppDataLocal + wchar_t* localappdatapath = nullptr; + if (S_OK != SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &localappdatapath)) __fastfail(1); + localappdata = localappdatapath; + CoTaskMemFree(localappdatapath); + } + return localappdata; + }); + } +} + +namespace vcpkg +{ + UserConfig UserConfig::try_read_data(const Files::Filesystem& fs) + { + UserConfig ret; + + try + { + auto maybe_pghs = Paragraphs::get_paragraphs(fs, get_localappdata() / "vcpkg" / "config"); + if (const auto p_pghs = maybe_pghs.get()) + { + const auto& pghs = *p_pghs; + + std::unordered_map keys; + if (pghs.size() > 0) keys = pghs[0]; + + for (size_t x = 1; x < pghs.size(); ++x) + { + for (auto&& p : pghs[x]) + keys.insert(p); + } + + ret.user_id = keys["User-Id"]; + ret.user_time = keys["User-Since"]; + ret.user_mac = keys["Mac-Hash"]; + ret.last_completed_survey = keys["Survey-Completed"]; + } + } + catch (...) + { + } + + return ret; + } + + void UserConfig::try_write_data(Files::Filesystem& fs) const + { + try + { + std::error_code ec; + fs.create_directory(get_localappdata() / "vcpkg", ec); + fs.write_contents(get_localappdata() / "vcpkg" / "config", + Strings::format("User-Id: %s\n" + "User-Since: %s\n" + "Mac-Hash: %s\n" + "Survey-Completed: %s\n", + user_id, + user_time, + user_mac, + last_completed_survey)); + } + catch (...) + { + } + } +} -- cgit v1.2.3 From d26a6b067c24e324b111849c320bdc4cf681e713 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sun, 26 Nov 2017 02:51:31 -0800 Subject: Add `vcpkg integrate powershell` for tab completion --- toolsrc/src/vcpkg/commands.integrate.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 66c5eb5a9..460e99b88 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -324,18 +324,20 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console " vcpkg integrate install Make installed packages available user-wide. Requires admin privileges on " "first use\n" " vcpkg integrate remove Remove user-wide integration\n" - " vcpkg integrate project Generate a referencing nuget package for individual VS project use\n"; + " vcpkg integrate project Generate a referencing nuget package for individual VS project use\n" + " vcpkg integrate powershell Enable PowerShell Tab-Completion\n"; namespace Subcommand { static const std::string INSTALL = "install"; static const std::string REMOVE = "remove"; static const std::string PROJECT = "project"; + static const std::string POWERSHELL = "powershell"; } static std::vector valid_arguments(const VcpkgPaths&) { - return {Subcommand::INSTALL, Subcommand::REMOVE, Subcommand::PROJECT}; + return {Subcommand::INSTALL, Subcommand::REMOVE, Subcommand::PROJECT, Subcommand::POWERSHELL}; } const CommandStructure COMMAND_STRUCTURE = { @@ -365,6 +367,12 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console { return integrate_project(paths); } + if (args.command_arguments[0] == Subcommand::POWERSHELL) + { + System::powershell_execute("PowerShell Tab-Completion", + paths.scripts / "addPoshVcpkgToPowershellProfile.ps1"); + Checks::exit_success(VCPKG_LINE_INFO); + } #endif Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown parameter %s for integrate", args.command_arguments[0]); -- cgit v1.2.3 From 705c8f201273e9bdad9508903d26b21f5d76f1c3 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 5 Dec 2017 18:03:36 -0800 Subject: Improve error message when failing to parse package --- toolsrc/src/vcpkg/packagespec.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/packagespec.cpp b/toolsrc/src/vcpkg/packagespec.cpp index eeb9981af..17189afcf 100644 --- a/toolsrc/src/vcpkg/packagespec.cpp +++ b/toolsrc/src/vcpkg/packagespec.cpp @@ -2,6 +2,7 @@ #include #include +#include #include using vcpkg::Parse::parse_comma_list; @@ -95,8 +96,19 @@ namespace vcpkg std::vector PackageSpec::to_package_specs(const std::vector& ports, const Triplet& triplet) { - return Util::fmap(ports, [&](const std::string s) { - return PackageSpec::from_name_and_triplet(s, triplet).value_or_exit(VCPKG_LINE_INFO); + return Util::fmap(ports, [&](const std::string& s) -> PackageSpec { + auto maybe_spec = PackageSpec::from_name_and_triplet(s, triplet); + if (auto spec = maybe_spec.get()) + { + return std::move(*spec); + } + + const PackageSpecParseResult error_type = maybe_spec.error(); + Checks::exit_with_message(VCPKG_LINE_INFO, + "Invalid package: %s\n" + "%s", + s, + vcpkg::to_string(error_type)); }); } -- cgit v1.2.3 From d540915a3aaab722e9b627ae001168be52333662 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 6 Dec 2017 14:42:17 -0800 Subject: Improve error message on invalid dependency of package --- toolsrc/src/vcpkg/dependencies.cpp | 6 +++--- toolsrc/src/vcpkg/packagespec.cpp | 27 ++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 6f599afd4..0a1f79834 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -114,19 +114,19 @@ namespace vcpkg::Dependencies { if (const auto p = this->status_paragraph.get()) { - return PackageSpec::to_package_specs(p->package.depends, triplet); + return PackageSpec::from_dependencies_of_port(p->package.spec.name(), p->package.depends, triplet); } if (const auto p = this->binary_control_file.get()) { auto deps = Util::fmap_flatten(p->features, [](const BinaryParagraph& pgh) { return pgh.depends; }); deps.insert(deps.end(), p->core_paragraph.depends.cbegin(), p->core_paragraph.depends.cend()); - return PackageSpec::to_package_specs(deps, triplet); + return PackageSpec::from_dependencies_of_port(p->core_paragraph.spec.name(), deps, triplet); } if (const auto p = this->source_paragraph.get()) { - return PackageSpec::to_package_specs(filter_dependencies(p->depends, triplet), triplet); + return PackageSpec::from_dependencies_of_port(p->name, filter_dependencies(p->depends, triplet), triplet); } Checks::exit_with_message(VCPKG_LINE_INFO, diff --git a/toolsrc/src/vcpkg/packagespec.cpp b/toolsrc/src/vcpkg/packagespec.cpp index 17189afcf..a9e072094 100644 --- a/toolsrc/src/vcpkg/packagespec.cpp +++ b/toolsrc/src/vcpkg/packagespec.cpp @@ -96,8 +96,8 @@ namespace vcpkg std::vector PackageSpec::to_package_specs(const std::vector& ports, const Triplet& triplet) { - return Util::fmap(ports, [&](const std::string& s) -> PackageSpec { - auto maybe_spec = PackageSpec::from_name_and_triplet(s, triplet); + return Util::fmap(ports, [&](const std::string& spec_as_string) -> PackageSpec { + auto maybe_spec = PackageSpec::from_name_and_triplet(spec_as_string, triplet); if (auto spec = maybe_spec.get()) { return std::move(*spec); @@ -107,7 +107,28 @@ namespace vcpkg Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid package: %s\n" "%s", - s, + spec_as_string, + vcpkg::to_string(error_type)); + }); + } + + std::vector PackageSpec::from_dependencies_of_port(const std::string& port, + const std::vector& dependencies, + const Triplet& triplet) + { + return Util::fmap(dependencies, [&](const std::string& spec_as_string) -> PackageSpec { + auto maybe_spec = PackageSpec::from_name_and_triplet(spec_as_string, triplet); + if (auto spec = maybe_spec.get()) + { + return std::move(*spec); + } + + const PackageSpecParseResult error_type = maybe_spec.error(); + Checks::exit_with_message(VCPKG_LINE_INFO, + "Invalid dependency [%s] in package [%s]\n" + "%s", + spec_as_string, + port, vcpkg::to_string(error_type)); }); } -- cgit v1.2.3 From dd1c2d9d6256d345659372ae4731bc81a91ad63b Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 12 Dec 2017 18:01:12 -0800 Subject: Fix fetching dependency text --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 324ca29d1..e64a681e2 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -92,7 +92,8 @@ namespace vcpkg tool_name, version_as_string); const fs::path script = scripts_folder / "fetchDependency.ps1"; - const std::string title = "Fetching %s version %s (No sufficient installed version was found)"; + const std::string title = Strings::format( + "Fetching %s version %s (No sufficient installed version was found)", tool_name, version_as_string); const System::PowershellParameter dependency_param("Dependency", tool_name); const std::string output = System::powershell_execute_and_capture_output(title, script, {dependency_param}); -- cgit v1.2.3 From 803347a0c545687f6e6b8b3594b52d11435491b3 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Dec 2017 02:22:52 -0800 Subject: [vcpkg-upgrade] Initial commit of upgrade command. --- toolsrc/src/commands.upgrade.cpp | 79 +++++++ toolsrc/src/tests.plan.cpp | 150 +++++++++++- toolsrc/src/tests.update.cpp | 34 ++- toolsrc/src/vcpkg/commands.ci.cpp | 2 +- toolsrc/src/vcpkg/commands.cpp | 3 +- toolsrc/src/vcpkg/commands.portsdiff.cpp | 7 +- toolsrc/src/vcpkg/dependencies.cpp | 391 +++++++++++++++++++------------ toolsrc/src/vcpkg/help.cpp | 1 + toolsrc/src/vcpkg/install.cpp | 120 +--------- toolsrc/src/vcpkg/paragraphs.cpp | 12 - toolsrc/src/vcpkg/remove.cpp | 9 +- toolsrc/src/vcpkg/update.cpp | 40 ++-- 12 files changed, 532 insertions(+), 316 deletions(-) create mode 100644 toolsrc/src/commands.upgrade.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands.upgrade.cpp b/toolsrc/src/commands.upgrade.cpp new file mode 100644 index 000000000..7a3210042 --- /dev/null +++ b/toolsrc/src/commands.upgrade.cpp @@ -0,0 +1,79 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::Upgrade +{ + using Install::KeepGoing; + using Install::to_keep_going; + + static const std::string OPTION_NO_DRY_RUN = "--no-dry-run"; + static const std::string OPTION_KEEP_GOING = "--keep-going"; + + static const std::array INSTALL_SWITCHES = {{ + {OPTION_NO_DRY_RUN, "Actually upgrade"}, + {OPTION_KEEP_GOING, "Continue installing packages on failure"}, + }}; + + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("upgrade --no-dry-run"), + 0, + 0, + {INSTALL_SWITCHES, {}}, + nullptr, + }; + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet&) + { + // input sanitization + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); + + const bool no_dry_run = Util::Sets::contains(options.switches, OPTION_NO_DRY_RUN); + const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING)); + + // create the plan + StatusParagraphs status_db = database_load_check(paths); + + Dependencies::PathsPortFileProvider provider(paths); + Dependencies::PackageGraph graph(provider, status_db); + + auto outdated_packages = Update::find_outdated_packages(provider, status_db); + for (auto&& outdated_package : outdated_packages) + graph.upgrade(outdated_package.spec); + + auto plan = graph.serialize(); + + if (plan.empty()) + { + System::println("All packages are up-to-date."); + Checks::exit_success(VCPKG_LINE_INFO); + } + + Dependencies::print_plan(plan, true); + + if (!no_dry_run) + { + System::println(System::Color::warning, + "If you are sure you want to rebuild the above packages, run this command with the " + "--no-dry-run option."); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + const Install::InstallSummary summary = Install::perform(plan, keep_going, paths, status_db); + + System::println("\nTotal elapsed time: %s\n", summary.total_elapsed_time); + + if (keep_going == KeepGoing::YES) + { + summary.print(); + } + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 122a4ffef..781588c91 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -36,7 +36,7 @@ namespace UnitTest1 std::vector vec, const Triplet& triplet = Triplet::X86_WINDOWS) { - const auto& plan = install_action->install_plan.value_or_exit(VCPKG_LINE_INFO); + const auto& plan = install_action->install_action.value_or_exit(VCPKG_LINE_INFO); const auto& feature_list = plan.feature_list; Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); @@ -61,7 +61,7 @@ namespace UnitTest1 std::string pkg_name, const Triplet& triplet = Triplet::X86_WINDOWS) { - const auto& plan = remove_action->remove_plan.value_or_exit(VCPKG_LINE_INFO); + const auto& plan = remove_action->remove_action.value_or_exit(VCPKG_LINE_INFO); Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); } @@ -98,7 +98,7 @@ namespace UnitTest1 auto spec_b = spec_map.emplace("b", "c"); auto spec_c = spec_map.emplace("c"); - Dependencies::MapPortFile map_port(spec_map.map); + Dependencies::MapPortFileProvider map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); @@ -122,7 +122,7 @@ namespace UnitTest1 auto spec_g = spec_map.emplace("g"); auto spec_h = spec_map.emplace("h"); - Dependencies::MapPortFile map_port(spec_map.map); + Dependencies::MapPortFileProvider map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan( map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); @@ -162,7 +162,7 @@ namespace UnitTest1 StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(1), install_plan.size()); - auto p = install_plan[0].install_plan.get(); + auto p = install_plan[0].install_action.get(); Assert::IsNotNull(p); Assert::AreEqual("a", p->spec.name().c_str()); Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type); @@ -183,13 +183,13 @@ namespace UnitTest1 StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(2), install_plan.size()); - auto p = install_plan[0].install_plan.get(); + auto p = install_plan[0].install_action.get(); Assert::IsNotNull(p); Assert::AreEqual("b", p->spec.name().c_str()); Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type); Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type); - auto p2 = install_plan[1].install_plan.get(); + auto p2 = install_plan[1].install_action.get(); Assert::IsNotNull(p2); Assert::AreEqual("a", p2->spec.name().c_str()); Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type); @@ -215,7 +215,7 @@ namespace UnitTest1 auto spec_j = spec_map.emplace("j", "k"); auto spec_k = spec_map.emplace("k"); - Dependencies::MapPortFile map_port(spec_map.map); + Dependencies::MapPortFileProvider map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); @@ -521,4 +521,138 @@ namespace UnitTest1 Assert::AreEqual("expat", remove_plan[2].spec.name().c_str()); } }; + + class UpgradePlanTests : public TestClass + { + TEST_METHOD(basic_upgrade_scheme) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(2), plan.size()); + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + Assert::AreEqual("a", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].install_action.has_value()); + } + + TEST_METHOD(basic_upgrade_scheme_with_recurse) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b", "a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a"); + spec_map.emplace("b", "a"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(4), plan.size()); + Assert::AreEqual("b", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + + Assert::AreEqual("a", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].remove_action.has_value()); + + Assert::AreEqual("a", plan[2].spec().name().c_str()); + Assert::IsTrue(plan[2].install_action.has_value()); + + Assert::AreEqual("b", plan[3].spec().name().c_str()); + Assert::IsTrue(plan[3].install_action.has_value()); + } + + TEST_METHOD(basic_upgrade_scheme_with_bystander) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a"); + spec_map.emplace("b", "a"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(2), plan.size()); + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + Assert::AreEqual("a", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].install_action.has_value()); + } + + TEST_METHOD(basic_upgrade_scheme_with_new_dep) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "b"); + spec_map.emplace("b"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(3), plan.size()); + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + Assert::AreEqual("b", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].install_action.has_value()); + Assert::AreEqual("a", plan[2].spec().name().c_str()); + Assert::IsTrue(plan[2].install_action.has_value()); + } + + TEST_METHOD(basic_upgrade_scheme_with_features) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_feature_pgh("a", "a1")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(2), plan.size()); + + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + + features_check(&plan[1], "a", {"core", "a1"}); + } + }; } diff --git a/toolsrc/src/tests.update.cpp b/toolsrc/src/tests.update.cpp index 06ae797f4..b6e487c17 100644 --- a/toolsrc/src/tests.update.cpp +++ b/toolsrc/src/tests.update.cpp @@ -9,6 +9,8 @@ using namespace vcpkg::Update; namespace UnitTest1 { + using Pgh = std::vector>; + class UpdateTests : public TestClass { TEST_METHOD(find_outdated_packages_basic) @@ -19,10 +21,12 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::map port_versions; - port_versions["a"] = VersionT("0"); + std::unordered_map map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); + map.emplace("a", std::move(*scf)); + Dependencies::MapPortFileProvider provider(map); - auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(1), pkgs.size()); @@ -41,10 +45,12 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::map port_versions; - port_versions["a"] = VersionT("0"); + std::unordered_map map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); + map.emplace("a", std::move(*scf)); + Dependencies::MapPortFileProvider provider(map); - auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(1), pkgs.size()); @@ -65,10 +71,12 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::map port_versions; - port_versions["a"] = VersionT("0"); + std::unordered_map map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); + map.emplace("a", std::move(*scf)); + Dependencies::MapPortFileProvider provider(map); - auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(1), pkgs.size()); @@ -84,10 +92,12 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::map port_versions; - port_versions["a"] = VersionT("2"); + std::unordered_map map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "2"}}})); + map.emplace("a", std::move(*scf)); + Dependencies::MapPortFileProvider provider(map); - auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(0), pkgs.size()); diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index f2e984bf8..1a2f9b47f 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -27,7 +27,7 @@ namespace vcpkg::Commands::CI const std::vector specs = PackageSpec::to_package_specs(ports, triplet); StatusParagraphs status_db = database_load_check(paths); - const auto& paths_port_file = Dependencies::PathsPortFile(paths); + const auto& paths_port_file = Dependencies::PathsPortFileProvider(paths); std::vector install_plan = Dependencies::create_install_plan(paths_port_file, specs, status_db); diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index 15b10c7ea..ccf6fa729 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -13,9 +13,10 @@ namespace vcpkg::Commands Span> get_available_commands_type_a() { static std::vector> t = { - PackageNameAndFunction{"install", &Install::perform_and_exit}, + {"install", &Install::perform_and_exit}, {"ci", &CI::perform_and_exit}, {"remove", &Remove::perform_and_exit}, + {"upgrade", &Upgrade::perform_and_exit}, {"build", &Build::Command::perform_and_exit}, {"env", &Env::perform_and_exit}, {"build-external", &BuildExternal::perform_and_exit}, diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp index 6752715e4..dba04ce5b 100644 --- a/toolsrc/src/vcpkg/commands.portsdiff.cpp +++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp @@ -98,8 +98,11 @@ namespace vcpkg::Commands::PortsDiff ".vcpkg-root", git_exe.u8string()); System::cmd_execute_clean(cmd); - const std::map names_and_versions = Paragraphs::load_all_port_names_and_versions( - paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); + const auto all_ports = + Paragraphs::load_all_ports(paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); + std::map names_and_versions; + for (auto&& port : all_ports) + names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version); fs.remove_all(temp_checkout_path, ec); return names_and_versions; } diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 0a1f79834..5148a10f5 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -65,26 +65,19 @@ namespace vcpkg::Dependencies struct ClusterGraph : Util::MoveOnlyBase { - explicit ClusterGraph(std::unordered_map&& ports) - : m_ports(std::move(ports)) - { - } + explicit ClusterGraph(const PortFileProvider& provider) : m_provider(provider) {} Cluster& get(const PackageSpec& spec) { auto it = m_graph.find(spec); if (it == m_graph.end()) { - // Load on-demand from m_ports - auto it_ports = m_ports.find(spec.name()); - if (it_ports != m_ports.end()) - { - auto& clust = m_graph[spec]; - clust.spec = spec; - cluster_from_scf(*it_ports->second, clust); - return clust; - } - return m_graph[spec]; + // Load on-demand from m_provider + auto maybe_scf = m_provider.get_control_file(spec.name()); + auto& clust = m_graph[spec]; + clust.spec = spec; + if (auto p_scf = maybe_scf.get()) cluster_from_scf(*p_scf, clust); + return clust; } return it->second; } @@ -107,7 +100,7 @@ namespace vcpkg::Dependencies } std::unordered_map m_graph; - std::unordered_map m_ports; + const PortFileProvider& m_provider; }; std::vector AnyParagraph::dependencies(const Triplet& triplet) const @@ -226,12 +219,12 @@ namespace vcpkg::Dependencies const PackageSpec& AnyAction::spec() const { - if (const auto p = install_plan.get()) + if (const auto p = install_action.get()) { return p->spec; } - if (const auto p = remove_plan.get()) + if (const auto p = remove_action.get()) { return p->spec; } @@ -269,21 +262,20 @@ namespace vcpkg::Dependencies return left->spec.name() < right->spec.name(); } - MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map) {} + MapPortFileProvider::MapPortFileProvider(const std::unordered_map& map) : ports(map) + { + } - const SourceControlFile& MapPortFile::get_control_file(const std::string& spec) const + Optional MapPortFileProvider::get_control_file(const std::string& spec) const { auto scf = ports.find(spec); - if (scf == ports.end()) - { - Checks::exit_fail(VCPKG_LINE_INFO); - } + if (scf == ports.end()) return nullopt; return scf->second; } - PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths) {} + PathsPortFileProvider::PathsPortFileProvider(const VcpkgPaths& paths) : ports(paths) {} - const SourceControlFile& PathsPortFile::get_control_file(const std::string& spec) const + Optional PathsPortFileProvider::get_control_file(const std::string& spec) const { auto cache_it = cache.find(spec); if (cache_it != cache.end()) @@ -298,56 +290,34 @@ namespace vcpkg::Dependencies auto it = cache.emplace(spec, std::move(*scf->get())); return it.first->second; } - print_error_message(source_control_file.error()); - Checks::exit_fail(VCPKG_LINE_INFO); + return nullopt; } std::vector create_install_plan(const PortFileProvider& port_file_provider, const std::vector& specs, const StatusParagraphs& status_db) { - struct InstallAdjacencyProvider final : Graphs::AdjacencyProvider - { - const PortFileProvider& port_file_provider; - const StatusParagraphs& status_db; - const std::unordered_set& specs_as_set; + auto fspecs = Util::fmap(specs, [](const PackageSpec& spec) { return FeatureSpec(spec, ""); }); + auto plan = create_feature_install_plan(port_file_provider, fspecs, status_db); - InstallAdjacencyProvider(const PortFileProvider& port_file_provider, - const StatusParagraphs& s, - const std::unordered_set& specs_as_set) - : port_file_provider(port_file_provider), status_db(s), specs_as_set(specs_as_set) - { - } + std::vector ret; + ret.reserve(plan.size()); - std::vector adjacency_list(const InstallPlanAction& plan) const override + for (auto&& action : plan) + { + if (auto p_install = action.install_action.get()) { - if (plan.any_paragraph.status_paragraph.get()) return std::vector{}; - return plan.any_paragraph.dependencies(plan.spec.triplet()); + ret.push_back(std::move(*p_install)); } - - InstallPlanAction load_vertex_data(const PackageSpec& spec) const override + else { - const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() - ? RequestType::USER_REQUESTED - : RequestType::AUTO_SELECTED; - auto it = status_db.find_installed(spec); - if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type}; - return InstallPlanAction{ - spec, - {nullopt, nullopt, *port_file_provider.get_control_file(spec.name()).core_paragraph}, - request_type}; + Checks::exit_with_message(VCPKG_LINE_INFO, + "The installation plan requires feature packages support. Please re-run the " + "command with --featurepackages."); } - }; - - const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); - std::vector toposort = - Graphs::topological_sort(specs, InstallAdjacencyProvider{port_file_provider, status_db, specs_as_set}); - Util::erase_remove_if(toposort, [](const InstallPlanAction& plan) { - return plan.request_type == RequestType::AUTO_SELECTED && - plan.plan_type == InstallPlanType::ALREADY_INSTALLED; - }); + } - return toposort; + return ret; } std::vector create_remove_plan(const std::vector& specs, @@ -461,11 +431,12 @@ namespace vcpkg::Dependencies SUCCESS, }; - MarkPlusResult mark_plus(const std::string& feature, - Cluster& cluster, - ClusterGraph& pkg_to_cluster, - GraphPlan& graph_plan); - void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + static MarkPlusResult mark_plus(const std::string& feature, + Cluster& cluster, + ClusterGraph& pkg_to_cluster, + GraphPlan& graph_plan); + + static void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { @@ -557,110 +528,80 @@ namespace vcpkg::Dependencies } } - static ClusterGraph create_feature_install_graph(const std::unordered_map& map, - const StatusParagraphs& status_db) + std::vector create_feature_install_plan(const PortFileProvider& provider, + const std::vector& specs, + const StatusParagraphs& status_db) { - std::unordered_map ptr_map; - for (auto&& p : map) - ptr_map.emplace(p.first, &p.second); - ClusterGraph graph(std::move(ptr_map)); - - auto installed_ports = get_installed_ports(status_db); - - for (auto&& status_paragraph : installed_ports) - { - Cluster& cluster = graph.get(status_paragraph->package.spec); - - cluster.transient_uninstalled = false; - - cluster.status_paragraphs.emplace_back(status_paragraph); - - auto& status_paragraph_feature = status_paragraph->package.feature; - // In this case, empty string indicates the "core" paragraph for a package. - if (status_paragraph_feature.empty()) - { - cluster.original_features.insert("core"); - } - else - { - cluster.original_features.insert(status_paragraph_feature); - } - } - - for (auto&& status_paragraph : installed_ports) - { - auto& spec = status_paragraph->package.spec; - auto& status_paragraph_feature = status_paragraph->package.feature; - auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, - status_paragraph->package.spec.triplet()); - - for (auto&& dependency : reverse_edges) - { - auto& dep_cluster = graph.get(dependency.spec()); - - auto depends_name = dependency.feature(); - if (depends_name.empty()) depends_name = "core"; + PackageGraph pgraph(provider, status_db); + for (auto&& spec : specs) + pgraph.install(spec); - auto& target_node = dep_cluster.edges[depends_name]; - target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); - } - } - return graph; + return pgraph.serialize(); } std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db) { - ClusterGraph graph = create_feature_install_graph(map, status_db); + MapPortFileProvider provider(map); + return create_feature_install_plan(provider, specs, status_db); + } - GraphPlan graph_plan; - for (auto&& spec : specs) + void PackageGraph::install(const FeatureSpec& spec) + { + Cluster& spec_cluster = m_graph->get(spec.spec()); + spec_cluster.request_type = RequestType::USER_REQUESTED; + if (spec.feature() == "*") { - Cluster& spec_cluster = graph.get(spec.spec()); - spec_cluster.request_type = RequestType::USER_REQUESTED; - if (spec.feature() == "*") + if (auto p_scf = spec_cluster.source_control_file.value_or(nullptr)) { - if (auto p_scf = spec_cluster.source_control_file.value_or(nullptr)) + for (auto&& feature : p_scf->feature_paragraphs) { - for (auto&& feature : p_scf->feature_paragraphs) - { - auto res = mark_plus(feature->name, spec_cluster, graph, graph_plan); - - Checks::check_exit(VCPKG_LINE_INFO, - res == MarkPlusResult::SUCCESS, - "Error: Unable to locate feature %s", - spec); - } - - auto res = mark_plus("core", spec_cluster, graph, graph_plan); + auto res = mark_plus(feature->name, spec_cluster, *m_graph, *m_graph_plan); Checks::check_exit( VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); } - else - { - Checks::exit_with_message( - VCPKG_LINE_INFO, "Error: Unable to handle '*' because can't find CONTROL for %s", spec.spec()); - } - } - else - { - auto res = mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + + auto res = mark_plus("core", spec_cluster, *m_graph, *m_graph_plan); Checks::check_exit( VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); } + else + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "Error: Unable to handle '*' because can't find CONTROL for %s", spec.spec()); + } + } + else + { + auto res = mark_plus(spec.feature(), spec_cluster, *m_graph, *m_graph_plan); - graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster}); + Checks::check_exit( + VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); } - Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); - auto remove_vertex_list = graph_plan.remove_graph.vertex_list(); + m_graph_plan->install_graph.add_vertex(ClusterPtr{&spec_cluster}); + } + + void PackageGraph::upgrade(const PackageSpec& spec) + { + Cluster& spec_cluster = m_graph->get(spec); + spec_cluster.request_type = RequestType::USER_REQUESTED; + + mark_minus(spec_cluster, *m_graph, *m_graph_plan); + } + + std::vector PackageGraph::serialize() const + { + Graphs::GraphAdjacencyProvider adjacency_remove_graph(m_graph_plan->remove_graph.adjacency_list()); + auto remove_vertex_list = m_graph_plan->remove_graph.vertex_list(); auto remove_toposort = Graphs::topological_sort(remove_vertex_list, adjacency_remove_graph); - Graphs::GraphAdjacencyProvider adjacency_install_graph(graph_plan.install_graph.adjacency_list()); - auto insert_vertex_list = graph_plan.install_graph.vertex_list(); + Graphs::GraphAdjacencyProvider adjacency_install_graph( + m_graph_plan->install_graph.adjacency_list()); + auto insert_vertex_list = m_graph_plan->install_graph.vertex_list(); auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph); std::vector plan; @@ -705,4 +646,162 @@ namespace vcpkg::Dependencies return plan; } + + static std::unique_ptr create_feature_install_graph(const PortFileProvider& map, + const StatusParagraphs& status_db) + { + std::unique_ptr graph = std::make_unique(map); + + auto installed_ports = get_installed_ports(status_db); + + for (auto&& status_paragraph : installed_ports) + { + Cluster& cluster = graph->get(status_paragraph->package.spec); + + cluster.transient_uninstalled = false; + + cluster.status_paragraphs.emplace_back(status_paragraph); + + auto& status_paragraph_feature = status_paragraph->package.feature; + // In this case, empty string indicates the "core" paragraph for a package. + if (status_paragraph_feature.empty()) + { + cluster.original_features.insert("core"); + } + else + { + cluster.original_features.insert(status_paragraph_feature); + } + } + + // Populate the graph with "remove edges", which are the reverse of the Build-Depends edges. + for (auto&& status_paragraph : installed_ports) + { + auto& spec = status_paragraph->package.spec; + auto& status_paragraph_feature = status_paragraph->package.feature; + auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, + status_paragraph->package.spec.triplet()); + + for (auto&& dependency : reverse_edges) + { + auto& dep_cluster = graph->get(dependency.spec()); + + auto depends_name = dependency.feature(); + if (depends_name.empty()) depends_name = "core"; + + auto& target_node = dep_cluster.edges[depends_name]; + target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); + } + } + return graph; + } + + PackageGraph::PackageGraph(const PortFileProvider& provider, const StatusParagraphs& status_db) + : m_graph(create_feature_install_graph(provider, status_db)), m_graph_plan(std::make_unique()) + { + } + + PackageGraph::~PackageGraph() {} + + void print_plan(const std::vector& action_plan, const bool is_recursive) + { + std::vector remove_plans; + std::vector rebuilt_plans; + std::vector only_install_plans; + std::vector new_plans; + std::vector already_installed_plans; + std::vector excluded; + + const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { + if (auto iplan = package.install_action.get()) + return iplan->request_type != RequestType::USER_REQUESTED; + else + return false; + }) != action_plan.cend(); + + for (auto&& action : action_plan) + { + if (auto install_action = action.install_action.get()) + { + // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at + // all. + auto it = Util::find_if( + remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); + if (it != remove_plans.end()) + { + rebuilt_plans.emplace_back(install_action); + } + else + { + switch (install_action->plan_type) + { + case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break; + case InstallPlanType::ALREADY_INSTALLED: + if (install_action->request_type == RequestType::USER_REQUESTED) + already_installed_plans.emplace_back(install_action); + break; + case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break; + case InstallPlanType::EXCLUDED: excluded.emplace_back(install_action); break; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + } + else if (auto remove_action = action.remove_action.get()) + { + remove_plans.emplace_back(remove_action); + } + } + + std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name); + std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(excluded.begin(), excluded.end(), &InstallPlanAction::compare_by_name); + + static auto actions_to_output_string = [](const std::vector& v) { + return Strings::join("\n", v, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname(), p->build_options); + }); + }; + + if (excluded.size() > 0) + { + System::println("The following packages are excluded:\n%s", actions_to_output_string(excluded)); + } + + if (already_installed_plans.size() > 0) + { + System::println("The following packages are already installed:\n%s", + actions_to_output_string(already_installed_plans)); + } + + if (rebuilt_plans.size() > 0) + { + System::println("The following packages will be rebuilt:\n%s", actions_to_output_string(rebuilt_plans)); + } + + if (new_plans.size() > 0) + { + System::println("The following packages will be built and installed:\n%s", + actions_to_output_string(new_plans)); + } + + if (only_install_plans.size() > 0) + { + System::println("The following packages will be directly installed:\n%s", + actions_to_output_string(only_install_plans)); + } + + if (has_non_user_requested_packages) + System::println("Additional packages (*) will be modified to complete this operation."); + + if (remove_plans.size() > 0 && !is_recursive) + { + System::println(System::Color::warning, + "If you are sure you want to rebuild the above packages, run the command with the " + "--recurse option"); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } } diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index c83f0277b..b7d355742 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -85,6 +85,7 @@ namespace vcpkg::Help " vcpkg remove --outdated Uninstall all out-of-date packages\n" " vcpkg list List installed packages\n" " vcpkg update Display list of packages for updating\n" + " vcpkg upgrade Rebuild all outdated packages\n" " vcpkg hash [alg] Hash a file by specific algorithm, default SHA512\n" " vcpkg help topics Display the list of help topics\n" " vcpkg help Display help for a specific topic\n" diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 76dc7a527..08cfc2e73 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -348,108 +348,6 @@ namespace vcpkg::Install Checks::unreachable(VCPKG_LINE_INFO); } - static void print_plan(const std::vector& action_plan, const bool is_recursive) - { - std::vector remove_plans; - std::vector rebuilt_plans; - std::vector only_install_plans; - std::vector new_plans; - std::vector already_installed_plans; - std::vector excluded; - - const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { - if (auto iplan = package.install_plan.get()) - return iplan->request_type != RequestType::USER_REQUESTED; - else - return false; - }) != action_plan.cend(); - - for (auto&& action : action_plan) - { - if (auto install_action = action.install_plan.get()) - { - // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at - // all. - auto it = Util::find_if( - remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); - if (it != remove_plans.end()) - { - rebuilt_plans.emplace_back(install_action); - } - else - { - switch (install_action->plan_type) - { - case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break; - case InstallPlanType::ALREADY_INSTALLED: - if (install_action->request_type == RequestType::USER_REQUESTED) - already_installed_plans.emplace_back(install_action); - break; - case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break; - case InstallPlanType::EXCLUDED: excluded.emplace_back(install_action); break; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - } - else if (auto remove_action = action.remove_plan.get()) - { - remove_plans.emplace_back(remove_action); - } - } - - std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name); - std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(excluded.begin(), excluded.end(), &InstallPlanAction::compare_by_name); - - static auto actions_to_output_string = [](const std::vector& v) { - return Strings::join("\n", v, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname(), p->build_options); - }); - }; - - if (excluded.size() > 0) - { - System::println("The following packages are excluded:\n%s", actions_to_output_string(excluded)); - } - - if (already_installed_plans.size() > 0) - { - System::println("The following packages are already installed:\n%s", - actions_to_output_string(already_installed_plans)); - } - - if (rebuilt_plans.size() > 0) - { - System::println("The following packages will be rebuilt:\n%s", actions_to_output_string(rebuilt_plans)); - } - - if (new_plans.size() > 0) - { - System::println("The following packages will be built and installed:\n%s", - actions_to_output_string(new_plans)); - } - - if (only_install_plans.size() > 0) - { - System::println("The following packages will be directly installed:\n%s", - actions_to_output_string(only_install_plans)); - } - - if (has_non_user_requested_packages) - System::println("Additional packages (*) will be installed to complete this operation."); - - if (remove_plans.size() > 0 && !is_recursive) - { - System::println(System::Color::warning, - "If you are sure you want to rebuild the above packages, run the command with the " - "--recurse option"); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - void InstallSummary::print() const { System::println("RESULTS"); @@ -499,7 +397,7 @@ namespace vcpkg::Install results.emplace_back(spec, &action); - if (const auto install_action = action.install_plan.get()) + if (const auto install_action = action.install_action.get()) { auto result = perform_install_plan_action(paths, *install_action, status_db); @@ -511,7 +409,7 @@ namespace vcpkg::Install results.back().build_result = std::move(result); } - else if (const auto remove_action = action.remove_plan.get()) + else if (const auto remove_action = action.remove_action.get()) { Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages); Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db); @@ -690,7 +588,7 @@ namespace vcpkg::Install } else { - Dependencies::PathsPortFile paths_port_file(paths); + Dependencies::PathsPortFileProvider paths_port_file(paths); auto install_plan = Dependencies::create_install_plan( paths_port_file, Util::fmap(specs, [](auto&& spec) { return spec.package_spec; }), status_db); @@ -700,7 +598,7 @@ namespace vcpkg::Install for (auto&& action : action_plan) { - if (auto p_install = action.install_plan.get()) + if (auto p_install = action.install_action.get()) { p_install->build_options = install_plan_options; if (p_install->request_type != RequestType::USER_REQUESTED) @@ -713,16 +611,16 @@ namespace vcpkg::Install // log the plan const std::string specs_string = Strings::join(",", action_plan, [](const AnyAction& action) { - if (auto iaction = action.install_plan.get()) + if (auto iaction = action.install_action.get()) return iaction->spec.to_string(); - else if (auto raction = action.remove_plan.get()) + else if (auto raction = action.remove_action.get()) return "R$" + raction->spec.to_string(); Checks::unreachable(VCPKG_LINE_INFO); }); Metrics::g_metrics.lock()->track_property("installplan", specs_string); - print_plan(action_plan, is_recursive); + Dependencies::print_plan(action_plan, is_recursive); if (dry_run) { @@ -752,7 +650,7 @@ namespace vcpkg::Install for (auto&& result : summary.results) { if (!result.action) continue; - if (auto p_install_action = result.action->install_plan.get()) + if (auto p_install_action = result.action->install_action.get()) { if (p_install_action->request_type != RequestType::USER_REQUESTED) continue; auto bpgh = result.get_binary_paragraph(); @@ -773,7 +671,7 @@ namespace vcpkg::Install { if (build_result.binary_control_file) return &build_result.binary_control_file->core_paragraph; if (action) - if (auto p_install_plan = action->install_plan.get()) + if (auto p_install_plan = action->install_action.get()) { if (auto p_bcf = p_install_plan->any_paragraph.binary_control_file.get()) return &p_bcf->core_paragraph; diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp index b93de190c..b66d53994 100644 --- a/toolsrc/src/vcpkg/paragraphs.cpp +++ b/toolsrc/src/vcpkg/paragraphs.cpp @@ -289,16 +289,4 @@ namespace vcpkg::Paragraphs } return std::move(results.paragraphs); } - - std::map load_all_port_names_and_versions(const Files::Filesystem& fs, - const fs::path& ports_dir) - { - auto all_ports = load_all_ports(fs, ports_dir); - - std::map names_and_versions; - for (auto&& port : all_ports) - names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version); - - return names_and_versions; - } } diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 8ae0bc881..4079d60c1 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -207,10 +207,11 @@ namespace vcpkg::Remove System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'"); Checks::exit_fail(VCPKG_LINE_INFO); } - specs = Util::fmap( - Update::find_outdated_packages( - Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports), status_db), - [](auto&& outdated) { return outdated.spec; }); + + Dependencies::PathsPortFileProvider provider(paths); + + specs = Util::fmap(Update::find_outdated_packages(provider, status_db), + [](auto&& outdated) { return outdated.spec; }); if (specs.empty()) { diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp index 29baef91e..d6c5614ed 100644 --- a/toolsrc/src/vcpkg/update.cpp +++ b/toolsrc/src/vcpkg/update.cpp @@ -14,7 +14,7 @@ namespace vcpkg::Update return left.spec.name() < right.spec.name(); } - std::vector find_outdated_packages(const std::map& src_names_to_versions, + std::vector find_outdated_packages(const Dependencies::PortFileProvider& provider, const StatusParagraphs& status_db) { const std::vector installed_packages = get_installed_ports(status_db); @@ -24,19 +24,23 @@ namespace vcpkg::Update { if (!pgh->package.feature.empty()) { - // Skip feature packages; only consider master packages for needing updates. + // Skip feature paragraphs; only consider master paragraphs for needing updates. continue; } - const auto it = src_names_to_versions.find(pgh->package.spec.name()); - if (it == src_names_to_versions.end()) + auto maybe_scf = provider.get_control_file(pgh->package.spec.name()); + if (auto p_scf = maybe_scf.get()) { - // Package was not installed from portfile - continue; + auto&& port_version = p_scf->core_paragraph->version; + auto&& installed_version = pgh->package.version; + if (installed_version != port_version) + { + output.push_back({pgh->package.spec, VersionDiff(installed_version, port_version)}); + } } - if (it->second != pgh->package.version) + else { - output.push_back({pgh->package.spec, VersionDiff(pgh->package.version, it->second)}); + // No portfile available } } @@ -58,10 +62,10 @@ namespace vcpkg::Update const StatusParagraphs status_db = database_load_check(paths); - const auto outdated_packages = SortedVector( - find_outdated_packages(Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports), - status_db), - &OutdatedPackage::compare_by_name); + Dependencies::PathsPortFileProvider provider(paths); + + const auto outdated_packages = SortedVector(find_outdated_packages(provider, status_db), + &OutdatedPackage::compare_by_name); if (outdated_packages.empty()) { @@ -69,19 +73,17 @@ namespace vcpkg::Update } else { - std::string install_line; System::println("The following packages differ from their port versions:"); for (auto&& package : outdated_packages) { - install_line += package.spec.to_string(); - install_line += " "; System::println(" %-32s %s", package.spec, package.version_diff.to_string()); } System::println("\n" - "To update these packages, run\n" - " .\\vcpkg remove --outdated\n" - " .\\vcpkg install " + - install_line); + "To update these packages and all dependencies, run\n" + " .\\vcpkg upgrade\n" + "\n" + "To only remove outdated packages, run\n" + " .\\vcpkg remove --outdated\n"); } Checks::exit_success(VCPKG_LINE_INFO); -- cgit v1.2.3 From d88563cd095b9aaad81d57f1c0a254d7e17cf859 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Dec 2017 03:01:50 -0800 Subject: [vcpkg-upgrade] Accept list of packages to specifically upgrade. --- toolsrc/src/commands.upgrade.cpp | 108 ++++++++++++++++++++++++++++++++++---- toolsrc/src/vcpkg/base/checks.cpp | 9 ++-- 2 files changed, 101 insertions(+), 16 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands.upgrade.cpp b/toolsrc/src/commands.upgrade.cpp index 7a3210042..2ce04faa9 100644 --- a/toolsrc/src/commands.upgrade.cpp +++ b/toolsrc/src/commands.upgrade.cpp @@ -1,8 +1,10 @@ #include "pch.h" +#include #include #include #include +#include #include #include #include @@ -24,37 +26,121 @@ namespace vcpkg::Commands::Upgrade const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("upgrade --no-dry-run"), 0, - 0, + SIZE_MAX, {INSTALL_SWITCHES, {}}, nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet&) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - // input sanitization const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const bool no_dry_run = Util::Sets::contains(options.switches, OPTION_NO_DRY_RUN); const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING)); - // create the plan StatusParagraphs status_db = database_load_check(paths); Dependencies::PathsPortFileProvider provider(paths); Dependencies::PackageGraph graph(provider, status_db); - auto outdated_packages = Update::find_outdated_packages(provider, status_db); - for (auto&& outdated_package : outdated_packages) - graph.upgrade(outdated_package.spec); + // input sanitization + const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + return Input::check_and_get_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text); + }); - auto plan = graph.serialize(); + for (auto&& spec : specs) + { + Input::check_triplet(spec.triplet(), paths); + } - if (plan.empty()) + if (specs.empty()) { - System::println("All packages are up-to-date."); - Checks::exit_success(VCPKG_LINE_INFO); + // If no packages specified, upgrade all outdated packages. + auto outdated_packages = Update::find_outdated_packages(provider, status_db); + + if (outdated_packages.empty()) + { + System::println("All installed packages are up-to-date with the local portfiles."); + Checks::exit_success(VCPKG_LINE_INFO); + } + + for (auto&& outdated_package : outdated_packages) + graph.upgrade(outdated_package.spec); + } + else + { + std::vector not_installed; + std::vector no_portfile; + std::vector to_upgrade; + std::vector up_to_date; + + for (auto&& spec : specs) + { + auto it = status_db.find_installed(spec); + if (it == status_db.end()) + { + not_installed.push_back(spec); + } + + auto maybe_scf = provider.get_control_file(spec.name()); + if (auto p_scf = maybe_scf.get()) + { + if (it != status_db.end()) + { + if (p_scf->core_paragraph->version != (*it)->package.version) + { + to_upgrade.push_back(spec); + } + else + { + up_to_date.push_back(spec); + } + } + } + else + { + no_portfile.push_back(spec); + } + } + + Util::sort(not_installed); + Util::sort(no_portfile); + Util::sort(up_to_date); + Util::sort(to_upgrade); + + if (!up_to_date.empty()) + { + System::println(System::Color::success, "The following packages are up-to-date:"); + System::println(Strings::join( + "", up_to_date, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); + } + + if (!not_installed.empty()) + { + System::println(System::Color::error, "The following packages are not installed:"); + System::println(Strings::join( + "", not_installed, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); + } + + if (!no_portfile.empty()) + { + System::println(System::Color::error, "The following packages do not have a valid portfile:"); + System::println(Strings::join( + "", no_portfile, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); + } + + Checks::check_exit(VCPKG_LINE_INFO, not_installed.empty() && no_portfile.empty()); + + if (to_upgrade.empty()) Checks::exit_success(VCPKG_LINE_INFO); + + for (auto&& spec : to_upgrade) + graph.upgrade(spec); } + auto plan = graph.serialize(); + + Checks::check_exit(VCPKG_LINE_INFO, !plan.empty()); + Dependencies::print_plan(plan, true); if (!no_dry_run) diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp index ed28d6e2b..23f2cc630 100644 --- a/toolsrc/src/vcpkg/base/checks.cpp +++ b/toolsrc/src/vcpkg/base/checks.cpp @@ -49,8 +49,7 @@ namespace vcpkg::Checks #else void register_console_ctrl_handler() {} #endif - - [[noreturn]] void unreachable(const LineInfo& line_info) + void unreachable(const LineInfo& line_info) { System::println(System::Color::error, "Error: Unreachable code was reached"); System::println(System::Color::error, line_info.to_string()); // Always print line_info here @@ -61,13 +60,13 @@ namespace vcpkg::Checks #endif } - [[noreturn]] void exit_with_code(const LineInfo& line_info, const int exit_code) + void exit_with_code(const LineInfo& line_info, const int exit_code) { Debug::println(System::Color::error, line_info.to_string()); cleanup_and_exit(exit_code); } - [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView error_message) + void exit_with_message(const LineInfo& line_info, const CStringView error_message) { System::println(System::Color::error, error_message); exit_fail(line_info); @@ -77,7 +76,7 @@ namespace vcpkg::Checks { if (!expression) { - exit_with_message(line_info, ""); + exit_fail(line_info); } } -- cgit v1.2.3 From e6b16165e7d69feab3f4841ab702e6072199b9d4 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Dec 2017 04:47:59 -0800 Subject: Revert "[vcpkg-upgrade] Accept list of packages to specifically upgrade." This reverts commit d88563cd095b9aaad81d57f1c0a254d7e17cf859. --- toolsrc/src/commands.upgrade.cpp | 108 ++++---------------------------------- toolsrc/src/vcpkg/base/checks.cpp | 9 ++-- 2 files changed, 16 insertions(+), 101 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands.upgrade.cpp b/toolsrc/src/commands.upgrade.cpp index 2ce04faa9..7a3210042 100644 --- a/toolsrc/src/commands.upgrade.cpp +++ b/toolsrc/src/commands.upgrade.cpp @@ -1,10 +1,8 @@ #include "pch.h" -#include #include #include #include -#include #include #include #include @@ -26,121 +24,37 @@ namespace vcpkg::Commands::Upgrade const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("upgrade --no-dry-run"), 0, - SIZE_MAX, + 0, {INSTALL_SWITCHES, {}}, nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet&) { + // input sanitization const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const bool no_dry_run = Util::Sets::contains(options.switches, OPTION_NO_DRY_RUN); const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING)); + // create the plan StatusParagraphs status_db = database_load_check(paths); Dependencies::PathsPortFileProvider provider(paths); Dependencies::PackageGraph graph(provider, status_db); - // input sanitization - const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text); - }); + auto outdated_packages = Update::find_outdated_packages(provider, status_db); + for (auto&& outdated_package : outdated_packages) + graph.upgrade(outdated_package.spec); - for (auto&& spec : specs) - { - Input::check_triplet(spec.triplet(), paths); - } - - if (specs.empty()) - { - // If no packages specified, upgrade all outdated packages. - auto outdated_packages = Update::find_outdated_packages(provider, status_db); - - if (outdated_packages.empty()) - { - System::println("All installed packages are up-to-date with the local portfiles."); - Checks::exit_success(VCPKG_LINE_INFO); - } + auto plan = graph.serialize(); - for (auto&& outdated_package : outdated_packages) - graph.upgrade(outdated_package.spec); - } - else + if (plan.empty()) { - std::vector not_installed; - std::vector no_portfile; - std::vector to_upgrade; - std::vector up_to_date; - - for (auto&& spec : specs) - { - auto it = status_db.find_installed(spec); - if (it == status_db.end()) - { - not_installed.push_back(spec); - } - - auto maybe_scf = provider.get_control_file(spec.name()); - if (auto p_scf = maybe_scf.get()) - { - if (it != status_db.end()) - { - if (p_scf->core_paragraph->version != (*it)->package.version) - { - to_upgrade.push_back(spec); - } - else - { - up_to_date.push_back(spec); - } - } - } - else - { - no_portfile.push_back(spec); - } - } - - Util::sort(not_installed); - Util::sort(no_portfile); - Util::sort(up_to_date); - Util::sort(to_upgrade); - - if (!up_to_date.empty()) - { - System::println(System::Color::success, "The following packages are up-to-date:"); - System::println(Strings::join( - "", up_to_date, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); - } - - if (!not_installed.empty()) - { - System::println(System::Color::error, "The following packages are not installed:"); - System::println(Strings::join( - "", not_installed, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); - } - - if (!no_portfile.empty()) - { - System::println(System::Color::error, "The following packages do not have a valid portfile:"); - System::println(Strings::join( - "", no_portfile, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); - } - - Checks::check_exit(VCPKG_LINE_INFO, not_installed.empty() && no_portfile.empty()); - - if (to_upgrade.empty()) Checks::exit_success(VCPKG_LINE_INFO); - - for (auto&& spec : to_upgrade) - graph.upgrade(spec); + System::println("All packages are up-to-date."); + Checks::exit_success(VCPKG_LINE_INFO); } - auto plan = graph.serialize(); - - Checks::check_exit(VCPKG_LINE_INFO, !plan.empty()); - Dependencies::print_plan(plan, true); if (!no_dry_run) diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp index 23f2cc630..ed28d6e2b 100644 --- a/toolsrc/src/vcpkg/base/checks.cpp +++ b/toolsrc/src/vcpkg/base/checks.cpp @@ -49,7 +49,8 @@ namespace vcpkg::Checks #else void register_console_ctrl_handler() {} #endif - void unreachable(const LineInfo& line_info) + + [[noreturn]] void unreachable(const LineInfo& line_info) { System::println(System::Color::error, "Error: Unreachable code was reached"); System::println(System::Color::error, line_info.to_string()); // Always print line_info here @@ -60,13 +61,13 @@ namespace vcpkg::Checks #endif } - void exit_with_code(const LineInfo& line_info, const int exit_code) + [[noreturn]] void exit_with_code(const LineInfo& line_info, const int exit_code) { Debug::println(System::Color::error, line_info.to_string()); cleanup_and_exit(exit_code); } - void exit_with_message(const LineInfo& line_info, const CStringView error_message) + [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView error_message) { System::println(System::Color::error, error_message); exit_fail(line_info); @@ -76,7 +77,7 @@ namespace vcpkg::Checks { if (!expression) { - exit_fail(line_info); + exit_with_message(line_info, ""); } } -- cgit v1.2.3 From 7a6ffdc75c6634e0df3c158e871426190511a096 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Dec 2017 04:48:13 -0800 Subject: Revert "[vcpkg-upgrade] Initial commit of upgrade command." This reverts commit 803347a0c545687f6e6b8b3594b52d11435491b3. --- toolsrc/src/commands.upgrade.cpp | 79 ------- toolsrc/src/tests.plan.cpp | 150 +----------- toolsrc/src/tests.update.cpp | 34 +-- toolsrc/src/vcpkg/commands.ci.cpp | 2 +- toolsrc/src/vcpkg/commands.cpp | 3 +- toolsrc/src/vcpkg/commands.portsdiff.cpp | 7 +- toolsrc/src/vcpkg/dependencies.cpp | 391 ++++++++++++------------------- toolsrc/src/vcpkg/help.cpp | 1 - toolsrc/src/vcpkg/install.cpp | 120 +++++++++- toolsrc/src/vcpkg/paragraphs.cpp | 12 + toolsrc/src/vcpkg/remove.cpp | 9 +- toolsrc/src/vcpkg/update.cpp | 40 ++-- 12 files changed, 316 insertions(+), 532 deletions(-) delete mode 100644 toolsrc/src/commands.upgrade.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands.upgrade.cpp b/toolsrc/src/commands.upgrade.cpp deleted file mode 100644 index 7a3210042..000000000 --- a/toolsrc/src/commands.upgrade.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "pch.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace vcpkg::Commands::Upgrade -{ - using Install::KeepGoing; - using Install::to_keep_going; - - static const std::string OPTION_NO_DRY_RUN = "--no-dry-run"; - static const std::string OPTION_KEEP_GOING = "--keep-going"; - - static const std::array INSTALL_SWITCHES = {{ - {OPTION_NO_DRY_RUN, "Actually upgrade"}, - {OPTION_KEEP_GOING, "Continue installing packages on failure"}, - }}; - - const CommandStructure COMMAND_STRUCTURE = { - Help::create_example_string("upgrade --no-dry-run"), - 0, - 0, - {INSTALL_SWITCHES, {}}, - nullptr, - }; - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet&) - { - // input sanitization - const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); - - const bool no_dry_run = Util::Sets::contains(options.switches, OPTION_NO_DRY_RUN); - const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING)); - - // create the plan - StatusParagraphs status_db = database_load_check(paths); - - Dependencies::PathsPortFileProvider provider(paths); - Dependencies::PackageGraph graph(provider, status_db); - - auto outdated_packages = Update::find_outdated_packages(provider, status_db); - for (auto&& outdated_package : outdated_packages) - graph.upgrade(outdated_package.spec); - - auto plan = graph.serialize(); - - if (plan.empty()) - { - System::println("All packages are up-to-date."); - Checks::exit_success(VCPKG_LINE_INFO); - } - - Dependencies::print_plan(plan, true); - - if (!no_dry_run) - { - System::println(System::Color::warning, - "If you are sure you want to rebuild the above packages, run this command with the " - "--no-dry-run option."); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - const Install::InstallSummary summary = Install::perform(plan, keep_going, paths, status_db); - - System::println("\nTotal elapsed time: %s\n", summary.total_elapsed_time); - - if (keep_going == KeepGoing::YES) - { - summary.print(); - } - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 781588c91..122a4ffef 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -36,7 +36,7 @@ namespace UnitTest1 std::vector vec, const Triplet& triplet = Triplet::X86_WINDOWS) { - const auto& plan = install_action->install_action.value_or_exit(VCPKG_LINE_INFO); + const auto& plan = install_action->install_plan.value_or_exit(VCPKG_LINE_INFO); const auto& feature_list = plan.feature_list; Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); @@ -61,7 +61,7 @@ namespace UnitTest1 std::string pkg_name, const Triplet& triplet = Triplet::X86_WINDOWS) { - const auto& plan = remove_action->remove_action.value_or_exit(VCPKG_LINE_INFO); + const auto& plan = remove_action->remove_plan.value_or_exit(VCPKG_LINE_INFO); Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); } @@ -98,7 +98,7 @@ namespace UnitTest1 auto spec_b = spec_map.emplace("b", "c"); auto spec_c = spec_map.emplace("c"); - Dependencies::MapPortFileProvider map_port(spec_map.map); + Dependencies::MapPortFile map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); @@ -122,7 +122,7 @@ namespace UnitTest1 auto spec_g = spec_map.emplace("g"); auto spec_h = spec_map.emplace("h"); - Dependencies::MapPortFileProvider map_port(spec_map.map); + Dependencies::MapPortFile map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan( map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); @@ -162,7 +162,7 @@ namespace UnitTest1 StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(1), install_plan.size()); - auto p = install_plan[0].install_action.get(); + auto p = install_plan[0].install_plan.get(); Assert::IsNotNull(p); Assert::AreEqual("a", p->spec.name().c_str()); Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type); @@ -183,13 +183,13 @@ namespace UnitTest1 StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(2), install_plan.size()); - auto p = install_plan[0].install_action.get(); + auto p = install_plan[0].install_plan.get(); Assert::IsNotNull(p); Assert::AreEqual("b", p->spec.name().c_str()); Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type); Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type); - auto p2 = install_plan[1].install_action.get(); + auto p2 = install_plan[1].install_plan.get(); Assert::IsNotNull(p2); Assert::AreEqual("a", p2->spec.name().c_str()); Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type); @@ -215,7 +215,7 @@ namespace UnitTest1 auto spec_j = spec_map.emplace("j", "k"); auto spec_k = spec_map.emplace("k"); - Dependencies::MapPortFileProvider map_port(spec_map.map); + Dependencies::MapPortFile map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); @@ -521,138 +521,4 @@ namespace UnitTest1 Assert::AreEqual("expat", remove_plan[2].spec.name().c_str()); } }; - - class UpgradePlanTests : public TestClass - { - TEST_METHOD(basic_upgrade_scheme) - { - std::vector> pghs; - pghs.push_back(make_status_pgh("a")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.emplace("a"); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(2), plan.size()); - Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - Assert::AreEqual("a", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].install_action.has_value()); - } - - TEST_METHOD(basic_upgrade_scheme_with_recurse) - { - std::vector> pghs; - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_pgh("b", "a")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.emplace("a"); - spec_map.emplace("b", "a"); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(4), plan.size()); - Assert::AreEqual("b", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - - Assert::AreEqual("a", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].remove_action.has_value()); - - Assert::AreEqual("a", plan[2].spec().name().c_str()); - Assert::IsTrue(plan[2].install_action.has_value()); - - Assert::AreEqual("b", plan[3].spec().name().c_str()); - Assert::IsTrue(plan[3].install_action.has_value()); - } - - TEST_METHOD(basic_upgrade_scheme_with_bystander) - { - std::vector> pghs; - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_pgh("b")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.emplace("a"); - spec_map.emplace("b", "a"); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(2), plan.size()); - Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - Assert::AreEqual("a", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].install_action.has_value()); - } - - TEST_METHOD(basic_upgrade_scheme_with_new_dep) - { - std::vector> pghs; - pghs.push_back(make_status_pgh("a")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.emplace("a", "b"); - spec_map.emplace("b"); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(3), plan.size()); - Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - Assert::AreEqual("b", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].install_action.has_value()); - Assert::AreEqual("a", plan[2].spec().name().c_str()); - Assert::IsTrue(plan[2].install_action.has_value()); - } - - TEST_METHOD(basic_upgrade_scheme_with_features) - { - std::vector> pghs; - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_feature_pgh("a", "a1")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(2), plan.size()); - - Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - - features_check(&plan[1], "a", {"core", "a1"}); - } - }; } diff --git a/toolsrc/src/tests.update.cpp b/toolsrc/src/tests.update.cpp index b6e487c17..06ae797f4 100644 --- a/toolsrc/src/tests.update.cpp +++ b/toolsrc/src/tests.update.cpp @@ -9,8 +9,6 @@ using namespace vcpkg::Update; namespace UnitTest1 { - using Pgh = std::vector>; - class UpdateTests : public TestClass { TEST_METHOD(find_outdated_packages_basic) @@ -21,12 +19,10 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::unordered_map map; - auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); - map.emplace("a", std::move(*scf)); - Dependencies::MapPortFileProvider provider(map); + std::map port_versions; + port_versions["a"] = VersionT("0"); - auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(1), pkgs.size()); @@ -45,12 +41,10 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::unordered_map map; - auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); - map.emplace("a", std::move(*scf)); - Dependencies::MapPortFileProvider provider(map); + std::map port_versions; + port_versions["a"] = VersionT("0"); - auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(1), pkgs.size()); @@ -71,12 +65,10 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::unordered_map map; - auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); - map.emplace("a", std::move(*scf)); - Dependencies::MapPortFileProvider provider(map); + std::map port_versions; + port_versions["a"] = VersionT("0"); - auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(1), pkgs.size()); @@ -92,12 +84,10 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::unordered_map map; - auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "2"}}})); - map.emplace("a", std::move(*scf)); - Dependencies::MapPortFileProvider provider(map); + std::map port_versions; + port_versions["a"] = VersionT("2"); - auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(0), pkgs.size()); diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 1a2f9b47f..f2e984bf8 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -27,7 +27,7 @@ namespace vcpkg::Commands::CI const std::vector specs = PackageSpec::to_package_specs(ports, triplet); StatusParagraphs status_db = database_load_check(paths); - const auto& paths_port_file = Dependencies::PathsPortFileProvider(paths); + const auto& paths_port_file = Dependencies::PathsPortFile(paths); std::vector install_plan = Dependencies::create_install_plan(paths_port_file, specs, status_db); diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index ccf6fa729..15b10c7ea 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -13,10 +13,9 @@ namespace vcpkg::Commands Span> get_available_commands_type_a() { static std::vector> t = { - {"install", &Install::perform_and_exit}, + PackageNameAndFunction{"install", &Install::perform_and_exit}, {"ci", &CI::perform_and_exit}, {"remove", &Remove::perform_and_exit}, - {"upgrade", &Upgrade::perform_and_exit}, {"build", &Build::Command::perform_and_exit}, {"env", &Env::perform_and_exit}, {"build-external", &BuildExternal::perform_and_exit}, diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp index dba04ce5b..6752715e4 100644 --- a/toolsrc/src/vcpkg/commands.portsdiff.cpp +++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp @@ -98,11 +98,8 @@ namespace vcpkg::Commands::PortsDiff ".vcpkg-root", git_exe.u8string()); System::cmd_execute_clean(cmd); - const auto all_ports = - Paragraphs::load_all_ports(paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); - std::map names_and_versions; - for (auto&& port : all_ports) - names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version); + const std::map names_and_versions = Paragraphs::load_all_port_names_and_versions( + paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); fs.remove_all(temp_checkout_path, ec); return names_and_versions; } diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 5148a10f5..0a1f79834 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -65,19 +65,26 @@ namespace vcpkg::Dependencies struct ClusterGraph : Util::MoveOnlyBase { - explicit ClusterGraph(const PortFileProvider& provider) : m_provider(provider) {} + explicit ClusterGraph(std::unordered_map&& ports) + : m_ports(std::move(ports)) + { + } Cluster& get(const PackageSpec& spec) { auto it = m_graph.find(spec); if (it == m_graph.end()) { - // Load on-demand from m_provider - auto maybe_scf = m_provider.get_control_file(spec.name()); - auto& clust = m_graph[spec]; - clust.spec = spec; - if (auto p_scf = maybe_scf.get()) cluster_from_scf(*p_scf, clust); - return clust; + // Load on-demand from m_ports + auto it_ports = m_ports.find(spec.name()); + if (it_ports != m_ports.end()) + { + auto& clust = m_graph[spec]; + clust.spec = spec; + cluster_from_scf(*it_ports->second, clust); + return clust; + } + return m_graph[spec]; } return it->second; } @@ -100,7 +107,7 @@ namespace vcpkg::Dependencies } std::unordered_map m_graph; - const PortFileProvider& m_provider; + std::unordered_map m_ports; }; std::vector AnyParagraph::dependencies(const Triplet& triplet) const @@ -219,12 +226,12 @@ namespace vcpkg::Dependencies const PackageSpec& AnyAction::spec() const { - if (const auto p = install_action.get()) + if (const auto p = install_plan.get()) { return p->spec; } - if (const auto p = remove_action.get()) + if (const auto p = remove_plan.get()) { return p->spec; } @@ -262,20 +269,21 @@ namespace vcpkg::Dependencies return left->spec.name() < right->spec.name(); } - MapPortFileProvider::MapPortFileProvider(const std::unordered_map& map) : ports(map) - { - } + MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map) {} - Optional MapPortFileProvider::get_control_file(const std::string& spec) const + const SourceControlFile& MapPortFile::get_control_file(const std::string& spec) const { auto scf = ports.find(spec); - if (scf == ports.end()) return nullopt; + if (scf == ports.end()) + { + Checks::exit_fail(VCPKG_LINE_INFO); + } return scf->second; } - PathsPortFileProvider::PathsPortFileProvider(const VcpkgPaths& paths) : ports(paths) {} + PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths) {} - Optional PathsPortFileProvider::get_control_file(const std::string& spec) const + const SourceControlFile& PathsPortFile::get_control_file(const std::string& spec) const { auto cache_it = cache.find(spec); if (cache_it != cache.end()) @@ -290,34 +298,56 @@ namespace vcpkg::Dependencies auto it = cache.emplace(spec, std::move(*scf->get())); return it.first->second; } - return nullopt; + print_error_message(source_control_file.error()); + Checks::exit_fail(VCPKG_LINE_INFO); } std::vector create_install_plan(const PortFileProvider& port_file_provider, const std::vector& specs, const StatusParagraphs& status_db) { - auto fspecs = Util::fmap(specs, [](const PackageSpec& spec) { return FeatureSpec(spec, ""); }); - auto plan = create_feature_install_plan(port_file_provider, fspecs, status_db); + struct InstallAdjacencyProvider final : Graphs::AdjacencyProvider + { + const PortFileProvider& port_file_provider; + const StatusParagraphs& status_db; + const std::unordered_set& specs_as_set; - std::vector ret; - ret.reserve(plan.size()); + InstallAdjacencyProvider(const PortFileProvider& port_file_provider, + const StatusParagraphs& s, + const std::unordered_set& specs_as_set) + : port_file_provider(port_file_provider), status_db(s), specs_as_set(specs_as_set) + { + } - for (auto&& action : plan) - { - if (auto p_install = action.install_action.get()) + std::vector adjacency_list(const InstallPlanAction& plan) const override { - ret.push_back(std::move(*p_install)); + if (plan.any_paragraph.status_paragraph.get()) return std::vector{}; + return plan.any_paragraph.dependencies(plan.spec.triplet()); } - else + + InstallPlanAction load_vertex_data(const PackageSpec& spec) const override { - Checks::exit_with_message(VCPKG_LINE_INFO, - "The installation plan requires feature packages support. Please re-run the " - "command with --featurepackages."); + const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() + ? RequestType::USER_REQUESTED + : RequestType::AUTO_SELECTED; + auto it = status_db.find_installed(spec); + if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type}; + return InstallPlanAction{ + spec, + {nullopt, nullopt, *port_file_provider.get_control_file(spec.name()).core_paragraph}, + request_type}; } - } + }; - return ret; + const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); + std::vector toposort = + Graphs::topological_sort(specs, InstallAdjacencyProvider{port_file_provider, status_db, specs_as_set}); + Util::erase_remove_if(toposort, [](const InstallPlanAction& plan) { + return plan.request_type == RequestType::AUTO_SELECTED && + plan.plan_type == InstallPlanType::ALREADY_INSTALLED; + }); + + return toposort; } std::vector create_remove_plan(const std::vector& specs, @@ -431,12 +461,11 @@ namespace vcpkg::Dependencies SUCCESS, }; - static MarkPlusResult mark_plus(const std::string& feature, - Cluster& cluster, - ClusterGraph& pkg_to_cluster, - GraphPlan& graph_plan); - - static void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + MarkPlusResult mark_plus(const std::string& feature, + Cluster& cluster, + ClusterGraph& pkg_to_cluster, + GraphPlan& graph_plan); + void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { @@ -528,80 +557,110 @@ namespace vcpkg::Dependencies } } - std::vector create_feature_install_plan(const PortFileProvider& provider, - const std::vector& specs, - const StatusParagraphs& status_db) + static ClusterGraph create_feature_install_graph(const std::unordered_map& map, + const StatusParagraphs& status_db) { - PackageGraph pgraph(provider, status_db); - for (auto&& spec : specs) - pgraph.install(spec); + std::unordered_map ptr_map; + for (auto&& p : map) + ptr_map.emplace(p.first, &p.second); + ClusterGraph graph(std::move(ptr_map)); + + auto installed_ports = get_installed_ports(status_db); - return pgraph.serialize(); + for (auto&& status_paragraph : installed_ports) + { + Cluster& cluster = graph.get(status_paragraph->package.spec); + + cluster.transient_uninstalled = false; + + cluster.status_paragraphs.emplace_back(status_paragraph); + + auto& status_paragraph_feature = status_paragraph->package.feature; + // In this case, empty string indicates the "core" paragraph for a package. + if (status_paragraph_feature.empty()) + { + cluster.original_features.insert("core"); + } + else + { + cluster.original_features.insert(status_paragraph_feature); + } + } + + for (auto&& status_paragraph : installed_ports) + { + auto& spec = status_paragraph->package.spec; + auto& status_paragraph_feature = status_paragraph->package.feature; + auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, + status_paragraph->package.spec.triplet()); + + for (auto&& dependency : reverse_edges) + { + auto& dep_cluster = graph.get(dependency.spec()); + + auto depends_name = dependency.feature(); + if (depends_name.empty()) depends_name = "core"; + + auto& target_node = dep_cluster.edges[depends_name]; + target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); + } + } + return graph; } std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db) { - MapPortFileProvider provider(map); - return create_feature_install_plan(provider, specs, status_db); - } + ClusterGraph graph = create_feature_install_graph(map, status_db); - void PackageGraph::install(const FeatureSpec& spec) - { - Cluster& spec_cluster = m_graph->get(spec.spec()); - spec_cluster.request_type = RequestType::USER_REQUESTED; - if (spec.feature() == "*") + GraphPlan graph_plan; + for (auto&& spec : specs) { - if (auto p_scf = spec_cluster.source_control_file.value_or(nullptr)) + Cluster& spec_cluster = graph.get(spec.spec()); + spec_cluster.request_type = RequestType::USER_REQUESTED; + if (spec.feature() == "*") { - for (auto&& feature : p_scf->feature_paragraphs) + if (auto p_scf = spec_cluster.source_control_file.value_or(nullptr)) { - auto res = mark_plus(feature->name, spec_cluster, *m_graph, *m_graph_plan); + for (auto&& feature : p_scf->feature_paragraphs) + { + auto res = mark_plus(feature->name, spec_cluster, graph, graph_plan); + + Checks::check_exit(VCPKG_LINE_INFO, + res == MarkPlusResult::SUCCESS, + "Error: Unable to locate feature %s", + spec); + } + + auto res = mark_plus("core", spec_cluster, graph, graph_plan); Checks::check_exit( VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); } - - auto res = mark_plus("core", spec_cluster, *m_graph, *m_graph_plan); - - Checks::check_exit( - VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); + else + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "Error: Unable to handle '*' because can't find CONTROL for %s", spec.spec()); + } } else { - Checks::exit_with_message( - VCPKG_LINE_INFO, "Error: Unable to handle '*' because can't find CONTROL for %s", spec.spec()); + auto res = mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + + Checks::check_exit( + VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); } - } - else - { - auto res = mark_plus(spec.feature(), spec_cluster, *m_graph, *m_graph_plan); - Checks::check_exit( - VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); + graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster}); } - m_graph_plan->install_graph.add_vertex(ClusterPtr{&spec_cluster}); - } - - void PackageGraph::upgrade(const PackageSpec& spec) - { - Cluster& spec_cluster = m_graph->get(spec); - spec_cluster.request_type = RequestType::USER_REQUESTED; - - mark_minus(spec_cluster, *m_graph, *m_graph_plan); - } - - std::vector PackageGraph::serialize() const - { - Graphs::GraphAdjacencyProvider adjacency_remove_graph(m_graph_plan->remove_graph.adjacency_list()); - auto remove_vertex_list = m_graph_plan->remove_graph.vertex_list(); + Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); + auto remove_vertex_list = graph_plan.remove_graph.vertex_list(); auto remove_toposort = Graphs::topological_sort(remove_vertex_list, adjacency_remove_graph); - Graphs::GraphAdjacencyProvider adjacency_install_graph( - m_graph_plan->install_graph.adjacency_list()); - auto insert_vertex_list = m_graph_plan->install_graph.vertex_list(); + Graphs::GraphAdjacencyProvider adjacency_install_graph(graph_plan.install_graph.adjacency_list()); + auto insert_vertex_list = graph_plan.install_graph.vertex_list(); auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph); std::vector plan; @@ -646,162 +705,4 @@ namespace vcpkg::Dependencies return plan; } - - static std::unique_ptr create_feature_install_graph(const PortFileProvider& map, - const StatusParagraphs& status_db) - { - std::unique_ptr graph = std::make_unique(map); - - auto installed_ports = get_installed_ports(status_db); - - for (auto&& status_paragraph : installed_ports) - { - Cluster& cluster = graph->get(status_paragraph->package.spec); - - cluster.transient_uninstalled = false; - - cluster.status_paragraphs.emplace_back(status_paragraph); - - auto& status_paragraph_feature = status_paragraph->package.feature; - // In this case, empty string indicates the "core" paragraph for a package. - if (status_paragraph_feature.empty()) - { - cluster.original_features.insert("core"); - } - else - { - cluster.original_features.insert(status_paragraph_feature); - } - } - - // Populate the graph with "remove edges", which are the reverse of the Build-Depends edges. - for (auto&& status_paragraph : installed_ports) - { - auto& spec = status_paragraph->package.spec; - auto& status_paragraph_feature = status_paragraph->package.feature; - auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, - status_paragraph->package.spec.triplet()); - - for (auto&& dependency : reverse_edges) - { - auto& dep_cluster = graph->get(dependency.spec()); - - auto depends_name = dependency.feature(); - if (depends_name.empty()) depends_name = "core"; - - auto& target_node = dep_cluster.edges[depends_name]; - target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); - } - } - return graph; - } - - PackageGraph::PackageGraph(const PortFileProvider& provider, const StatusParagraphs& status_db) - : m_graph(create_feature_install_graph(provider, status_db)), m_graph_plan(std::make_unique()) - { - } - - PackageGraph::~PackageGraph() {} - - void print_plan(const std::vector& action_plan, const bool is_recursive) - { - std::vector remove_plans; - std::vector rebuilt_plans; - std::vector only_install_plans; - std::vector new_plans; - std::vector already_installed_plans; - std::vector excluded; - - const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { - if (auto iplan = package.install_action.get()) - return iplan->request_type != RequestType::USER_REQUESTED; - else - return false; - }) != action_plan.cend(); - - for (auto&& action : action_plan) - { - if (auto install_action = action.install_action.get()) - { - // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at - // all. - auto it = Util::find_if( - remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); - if (it != remove_plans.end()) - { - rebuilt_plans.emplace_back(install_action); - } - else - { - switch (install_action->plan_type) - { - case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break; - case InstallPlanType::ALREADY_INSTALLED: - if (install_action->request_type == RequestType::USER_REQUESTED) - already_installed_plans.emplace_back(install_action); - break; - case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break; - case InstallPlanType::EXCLUDED: excluded.emplace_back(install_action); break; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - } - else if (auto remove_action = action.remove_action.get()) - { - remove_plans.emplace_back(remove_action); - } - } - - std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name); - std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(excluded.begin(), excluded.end(), &InstallPlanAction::compare_by_name); - - static auto actions_to_output_string = [](const std::vector& v) { - return Strings::join("\n", v, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname(), p->build_options); - }); - }; - - if (excluded.size() > 0) - { - System::println("The following packages are excluded:\n%s", actions_to_output_string(excluded)); - } - - if (already_installed_plans.size() > 0) - { - System::println("The following packages are already installed:\n%s", - actions_to_output_string(already_installed_plans)); - } - - if (rebuilt_plans.size() > 0) - { - System::println("The following packages will be rebuilt:\n%s", actions_to_output_string(rebuilt_plans)); - } - - if (new_plans.size() > 0) - { - System::println("The following packages will be built and installed:\n%s", - actions_to_output_string(new_plans)); - } - - if (only_install_plans.size() > 0) - { - System::println("The following packages will be directly installed:\n%s", - actions_to_output_string(only_install_plans)); - } - - if (has_non_user_requested_packages) - System::println("Additional packages (*) will be modified to complete this operation."); - - if (remove_plans.size() > 0 && !is_recursive) - { - System::println(System::Color::warning, - "If you are sure you want to rebuild the above packages, run the command with the " - "--recurse option"); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } } diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index b7d355742..c83f0277b 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -85,7 +85,6 @@ namespace vcpkg::Help " vcpkg remove --outdated Uninstall all out-of-date packages\n" " vcpkg list List installed packages\n" " vcpkg update Display list of packages for updating\n" - " vcpkg upgrade Rebuild all outdated packages\n" " vcpkg hash [alg] Hash a file by specific algorithm, default SHA512\n" " vcpkg help topics Display the list of help topics\n" " vcpkg help Display help for a specific topic\n" diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 08cfc2e73..76dc7a527 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -348,6 +348,108 @@ namespace vcpkg::Install Checks::unreachable(VCPKG_LINE_INFO); } + static void print_plan(const std::vector& action_plan, const bool is_recursive) + { + std::vector remove_plans; + std::vector rebuilt_plans; + std::vector only_install_plans; + std::vector new_plans; + std::vector already_installed_plans; + std::vector excluded; + + const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { + if (auto iplan = package.install_plan.get()) + return iplan->request_type != RequestType::USER_REQUESTED; + else + return false; + }) != action_plan.cend(); + + for (auto&& action : action_plan) + { + if (auto install_action = action.install_plan.get()) + { + // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at + // all. + auto it = Util::find_if( + remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); + if (it != remove_plans.end()) + { + rebuilt_plans.emplace_back(install_action); + } + else + { + switch (install_action->plan_type) + { + case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break; + case InstallPlanType::ALREADY_INSTALLED: + if (install_action->request_type == RequestType::USER_REQUESTED) + already_installed_plans.emplace_back(install_action); + break; + case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break; + case InstallPlanType::EXCLUDED: excluded.emplace_back(install_action); break; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + } + else if (auto remove_action = action.remove_plan.get()) + { + remove_plans.emplace_back(remove_action); + } + } + + std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name); + std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(excluded.begin(), excluded.end(), &InstallPlanAction::compare_by_name); + + static auto actions_to_output_string = [](const std::vector& v) { + return Strings::join("\n", v, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname(), p->build_options); + }); + }; + + if (excluded.size() > 0) + { + System::println("The following packages are excluded:\n%s", actions_to_output_string(excluded)); + } + + if (already_installed_plans.size() > 0) + { + System::println("The following packages are already installed:\n%s", + actions_to_output_string(already_installed_plans)); + } + + if (rebuilt_plans.size() > 0) + { + System::println("The following packages will be rebuilt:\n%s", actions_to_output_string(rebuilt_plans)); + } + + if (new_plans.size() > 0) + { + System::println("The following packages will be built and installed:\n%s", + actions_to_output_string(new_plans)); + } + + if (only_install_plans.size() > 0) + { + System::println("The following packages will be directly installed:\n%s", + actions_to_output_string(only_install_plans)); + } + + if (has_non_user_requested_packages) + System::println("Additional packages (*) will be installed to complete this operation."); + + if (remove_plans.size() > 0 && !is_recursive) + { + System::println(System::Color::warning, + "If you are sure you want to rebuild the above packages, run the command with the " + "--recurse option"); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } + void InstallSummary::print() const { System::println("RESULTS"); @@ -397,7 +499,7 @@ namespace vcpkg::Install results.emplace_back(spec, &action); - if (const auto install_action = action.install_action.get()) + if (const auto install_action = action.install_plan.get()) { auto result = perform_install_plan_action(paths, *install_action, status_db); @@ -409,7 +511,7 @@ namespace vcpkg::Install results.back().build_result = std::move(result); } - else if (const auto remove_action = action.remove_action.get()) + else if (const auto remove_action = action.remove_plan.get()) { Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages); Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db); @@ -588,7 +690,7 @@ namespace vcpkg::Install } else { - Dependencies::PathsPortFileProvider paths_port_file(paths); + Dependencies::PathsPortFile paths_port_file(paths); auto install_plan = Dependencies::create_install_plan( paths_port_file, Util::fmap(specs, [](auto&& spec) { return spec.package_spec; }), status_db); @@ -598,7 +700,7 @@ namespace vcpkg::Install for (auto&& action : action_plan) { - if (auto p_install = action.install_action.get()) + if (auto p_install = action.install_plan.get()) { p_install->build_options = install_plan_options; if (p_install->request_type != RequestType::USER_REQUESTED) @@ -611,16 +713,16 @@ namespace vcpkg::Install // log the plan const std::string specs_string = Strings::join(",", action_plan, [](const AnyAction& action) { - if (auto iaction = action.install_action.get()) + if (auto iaction = action.install_plan.get()) return iaction->spec.to_string(); - else if (auto raction = action.remove_action.get()) + else if (auto raction = action.remove_plan.get()) return "R$" + raction->spec.to_string(); Checks::unreachable(VCPKG_LINE_INFO); }); Metrics::g_metrics.lock()->track_property("installplan", specs_string); - Dependencies::print_plan(action_plan, is_recursive); + print_plan(action_plan, is_recursive); if (dry_run) { @@ -650,7 +752,7 @@ namespace vcpkg::Install for (auto&& result : summary.results) { if (!result.action) continue; - if (auto p_install_action = result.action->install_action.get()) + if (auto p_install_action = result.action->install_plan.get()) { if (p_install_action->request_type != RequestType::USER_REQUESTED) continue; auto bpgh = result.get_binary_paragraph(); @@ -671,7 +773,7 @@ namespace vcpkg::Install { if (build_result.binary_control_file) return &build_result.binary_control_file->core_paragraph; if (action) - if (auto p_install_plan = action->install_action.get()) + if (auto p_install_plan = action->install_plan.get()) { if (auto p_bcf = p_install_plan->any_paragraph.binary_control_file.get()) return &p_bcf->core_paragraph; diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp index b66d53994..b93de190c 100644 --- a/toolsrc/src/vcpkg/paragraphs.cpp +++ b/toolsrc/src/vcpkg/paragraphs.cpp @@ -289,4 +289,16 @@ namespace vcpkg::Paragraphs } return std::move(results.paragraphs); } + + std::map load_all_port_names_and_versions(const Files::Filesystem& fs, + const fs::path& ports_dir) + { + auto all_ports = load_all_ports(fs, ports_dir); + + std::map names_and_versions; + for (auto&& port : all_ports) + names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version); + + return names_and_versions; + } } diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 4079d60c1..8ae0bc881 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -207,11 +207,10 @@ namespace vcpkg::Remove System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'"); Checks::exit_fail(VCPKG_LINE_INFO); } - - Dependencies::PathsPortFileProvider provider(paths); - - specs = Util::fmap(Update::find_outdated_packages(provider, status_db), - [](auto&& outdated) { return outdated.spec; }); + specs = Util::fmap( + Update::find_outdated_packages( + Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports), status_db), + [](auto&& outdated) { return outdated.spec; }); if (specs.empty()) { diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp index d6c5614ed..29baef91e 100644 --- a/toolsrc/src/vcpkg/update.cpp +++ b/toolsrc/src/vcpkg/update.cpp @@ -14,7 +14,7 @@ namespace vcpkg::Update return left.spec.name() < right.spec.name(); } - std::vector find_outdated_packages(const Dependencies::PortFileProvider& provider, + std::vector find_outdated_packages(const std::map& src_names_to_versions, const StatusParagraphs& status_db) { const std::vector installed_packages = get_installed_ports(status_db); @@ -24,23 +24,19 @@ namespace vcpkg::Update { if (!pgh->package.feature.empty()) { - // Skip feature paragraphs; only consider master paragraphs for needing updates. + // Skip feature packages; only consider master packages for needing updates. continue; } - auto maybe_scf = provider.get_control_file(pgh->package.spec.name()); - if (auto p_scf = maybe_scf.get()) + const auto it = src_names_to_versions.find(pgh->package.spec.name()); + if (it == src_names_to_versions.end()) { - auto&& port_version = p_scf->core_paragraph->version; - auto&& installed_version = pgh->package.version; - if (installed_version != port_version) - { - output.push_back({pgh->package.spec, VersionDiff(installed_version, port_version)}); - } + // Package was not installed from portfile + continue; } - else + if (it->second != pgh->package.version) { - // No portfile available + output.push_back({pgh->package.spec, VersionDiff(pgh->package.version, it->second)}); } } @@ -62,10 +58,10 @@ namespace vcpkg::Update const StatusParagraphs status_db = database_load_check(paths); - Dependencies::PathsPortFileProvider provider(paths); - - const auto outdated_packages = SortedVector(find_outdated_packages(provider, status_db), - &OutdatedPackage::compare_by_name); + const auto outdated_packages = SortedVector( + find_outdated_packages(Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports), + status_db), + &OutdatedPackage::compare_by_name); if (outdated_packages.empty()) { @@ -73,17 +69,19 @@ namespace vcpkg::Update } else { + std::string install_line; System::println("The following packages differ from their port versions:"); for (auto&& package : outdated_packages) { + install_line += package.spec.to_string(); + install_line += " "; System::println(" %-32s %s", package.spec, package.version_diff.to_string()); } System::println("\n" - "To update these packages and all dependencies, run\n" - " .\\vcpkg upgrade\n" - "\n" - "To only remove outdated packages, run\n" - " .\\vcpkg remove --outdated\n"); + "To update these packages, run\n" + " .\\vcpkg remove --outdated\n" + " .\\vcpkg install " + + install_line); } Checks::exit_success(VCPKG_LINE_INFO); -- cgit v1.2.3 From eb1a7b099eb347b195491dfa2949d8aa92677276 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Dec 2017 05:43:00 -0800 Subject: [vcpkg] Fix regressions introduced with update command. Fixed issue with upgrade where it assumed downloads were not allowed. --- toolsrc/src/commands.upgrade.cpp | 180 +++++++++++++ toolsrc/src/tests.plan.cpp | 150 ++++++++++- toolsrc/src/tests.update.cpp | 34 ++- toolsrc/src/vcpkg/base/checks.cpp | 9 +- toolsrc/src/vcpkg/build.cpp | 38 ++- toolsrc/src/vcpkg/commands.ci.cpp | 2 +- toolsrc/src/vcpkg/commands.cpp | 3 +- toolsrc/src/vcpkg/commands.portsdiff.cpp | 7 +- toolsrc/src/vcpkg/dependencies.cpp | 420 +++++++++++++++++++------------ toolsrc/src/vcpkg/export.cpp | 4 +- toolsrc/src/vcpkg/help.cpp | 1 + toolsrc/src/vcpkg/install.cpp | 177 +++---------- toolsrc/src/vcpkg/paragraphs.cpp | 12 - toolsrc/src/vcpkg/remove.cpp | 9 +- toolsrc/src/vcpkg/update.cpp | 40 +-- 15 files changed, 695 insertions(+), 391 deletions(-) create mode 100644 toolsrc/src/commands.upgrade.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands.upgrade.cpp b/toolsrc/src/commands.upgrade.cpp new file mode 100644 index 000000000..d2c868870 --- /dev/null +++ b/toolsrc/src/commands.upgrade.cpp @@ -0,0 +1,180 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::Upgrade +{ + using Install::KeepGoing; + using Install::to_keep_going; + + static const std::string OPTION_NO_DRY_RUN = "--no-dry-run"; + static const std::string OPTION_KEEP_GOING = "--keep-going"; + + static const std::array INSTALL_SWITCHES = {{ + {OPTION_NO_DRY_RUN, "Actually upgrade"}, + {OPTION_KEEP_GOING, "Continue installing packages on failure"}, + }}; + + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("upgrade --no-dry-run"), + 0, + SIZE_MAX, + {INSTALL_SWITCHES, {}}, + nullptr, + }; + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); + + const bool no_dry_run = Util::Sets::contains(options.switches, OPTION_NO_DRY_RUN); + const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING)); + + StatusParagraphs status_db = database_load_check(paths); + + Dependencies::PathsPortFileProvider provider(paths); + Dependencies::PackageGraph graph(provider, status_db); + + // input sanitization + const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + return Input::check_and_get_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text); + }); + + for (auto&& spec : specs) + { + Input::check_triplet(spec.triplet(), paths); + } + + if (specs.empty()) + { + // If no packages specified, upgrade all outdated packages. + auto outdated_packages = Update::find_outdated_packages(provider, status_db); + + if (outdated_packages.empty()) + { + System::println("All installed packages are up-to-date with the local portfiles."); + Checks::exit_success(VCPKG_LINE_INFO); + } + + for (auto&& outdated_package : outdated_packages) + graph.upgrade(outdated_package.spec); + } + else + { + std::vector not_installed; + std::vector no_portfile; + std::vector to_upgrade; + std::vector up_to_date; + + for (auto&& spec : specs) + { + auto it = status_db.find_installed(spec); + if (it == status_db.end()) + { + not_installed.push_back(spec); + } + + auto maybe_scf = provider.get_control_file(spec.name()); + if (auto p_scf = maybe_scf.get()) + { + if (it != status_db.end()) + { + if (p_scf->core_paragraph->version != (*it)->package.version) + { + to_upgrade.push_back(spec); + } + else + { + up_to_date.push_back(spec); + } + } + } + else + { + no_portfile.push_back(spec); + } + } + + Util::sort(not_installed); + Util::sort(no_portfile); + Util::sort(up_to_date); + Util::sort(to_upgrade); + + if (!up_to_date.empty()) + { + System::println(System::Color::success, "The following packages are up-to-date:"); + System::println(Strings::join( + "", up_to_date, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); + } + + if (!not_installed.empty()) + { + System::println(System::Color::error, "The following packages are not installed:"); + System::println(Strings::join( + "", not_installed, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); + } + + if (!no_portfile.empty()) + { + System::println(System::Color::error, "The following packages do not have a valid portfile:"); + System::println(Strings::join( + "", no_portfile, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); + } + + Checks::check_exit(VCPKG_LINE_INFO, not_installed.empty() && no_portfile.empty()); + + if (to_upgrade.empty()) Checks::exit_success(VCPKG_LINE_INFO); + + for (auto&& spec : to_upgrade) + graph.upgrade(spec); + } + + auto plan = graph.serialize(); + + Checks::check_exit(VCPKG_LINE_INFO, !plan.empty()); + + const Build::BuildPackageOptions install_plan_options = { + Build::UseHeadVersion::NO, + Build::AllowDownloads::YES, + Build::CleanBuildtrees::NO, + }; + + // Set build settings for all install actions + for (auto&& action : plan) + { + if (auto p_install = action.install_action.get()) + { + p_install->build_options = install_plan_options; + } + } + + Dependencies::print_plan(plan, true); + + if (!no_dry_run) + { + System::println(System::Color::warning, + "If you are sure you want to rebuild the above packages, run this command with the " + "--no-dry-run option."); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + const Install::InstallSummary summary = Install::perform(plan, keep_going, paths, status_db); + + System::println("\nTotal elapsed time: %s\n", summary.total_elapsed_time); + + if (keep_going == KeepGoing::YES) + { + summary.print(); + } + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 122a4ffef..781588c91 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -36,7 +36,7 @@ namespace UnitTest1 std::vector vec, const Triplet& triplet = Triplet::X86_WINDOWS) { - const auto& plan = install_action->install_plan.value_or_exit(VCPKG_LINE_INFO); + const auto& plan = install_action->install_action.value_or_exit(VCPKG_LINE_INFO); const auto& feature_list = plan.feature_list; Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); @@ -61,7 +61,7 @@ namespace UnitTest1 std::string pkg_name, const Triplet& triplet = Triplet::X86_WINDOWS) { - const auto& plan = remove_action->remove_plan.value_or_exit(VCPKG_LINE_INFO); + const auto& plan = remove_action->remove_action.value_or_exit(VCPKG_LINE_INFO); Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); } @@ -98,7 +98,7 @@ namespace UnitTest1 auto spec_b = spec_map.emplace("b", "c"); auto spec_c = spec_map.emplace("c"); - Dependencies::MapPortFile map_port(spec_map.map); + Dependencies::MapPortFileProvider map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); @@ -122,7 +122,7 @@ namespace UnitTest1 auto spec_g = spec_map.emplace("g"); auto spec_h = spec_map.emplace("h"); - Dependencies::MapPortFile map_port(spec_map.map); + Dependencies::MapPortFileProvider map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan( map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); @@ -162,7 +162,7 @@ namespace UnitTest1 StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(1), install_plan.size()); - auto p = install_plan[0].install_plan.get(); + auto p = install_plan[0].install_action.get(); Assert::IsNotNull(p); Assert::AreEqual("a", p->spec.name().c_str()); Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type); @@ -183,13 +183,13 @@ namespace UnitTest1 StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(2), install_plan.size()); - auto p = install_plan[0].install_plan.get(); + auto p = install_plan[0].install_action.get(); Assert::IsNotNull(p); Assert::AreEqual("b", p->spec.name().c_str()); Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type); Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type); - auto p2 = install_plan[1].install_plan.get(); + auto p2 = install_plan[1].install_action.get(); Assert::IsNotNull(p2); Assert::AreEqual("a", p2->spec.name().c_str()); Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type); @@ -215,7 +215,7 @@ namespace UnitTest1 auto spec_j = spec_map.emplace("j", "k"); auto spec_k = spec_map.emplace("k"); - Dependencies::MapPortFile map_port(spec_map.map); + Dependencies::MapPortFileProvider map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); @@ -521,4 +521,138 @@ namespace UnitTest1 Assert::AreEqual("expat", remove_plan[2].spec.name().c_str()); } }; + + class UpgradePlanTests : public TestClass + { + TEST_METHOD(basic_upgrade_scheme) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(2), plan.size()); + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + Assert::AreEqual("a", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].install_action.has_value()); + } + + TEST_METHOD(basic_upgrade_scheme_with_recurse) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b", "a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a"); + spec_map.emplace("b", "a"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(4), plan.size()); + Assert::AreEqual("b", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + + Assert::AreEqual("a", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].remove_action.has_value()); + + Assert::AreEqual("a", plan[2].spec().name().c_str()); + Assert::IsTrue(plan[2].install_action.has_value()); + + Assert::AreEqual("b", plan[3].spec().name().c_str()); + Assert::IsTrue(plan[3].install_action.has_value()); + } + + TEST_METHOD(basic_upgrade_scheme_with_bystander) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a"); + spec_map.emplace("b", "a"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(2), plan.size()); + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + Assert::AreEqual("a", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].install_action.has_value()); + } + + TEST_METHOD(basic_upgrade_scheme_with_new_dep) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "b"); + spec_map.emplace("b"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(3), plan.size()); + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + Assert::AreEqual("b", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].install_action.has_value()); + Assert::AreEqual("a", plan[2].spec().name().c_str()); + Assert::IsTrue(plan[2].install_action.has_value()); + } + + TEST_METHOD(basic_upgrade_scheme_with_features) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_feature_pgh("a", "a1")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(2), plan.size()); + + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + + features_check(&plan[1], "a", {"core", "a1"}); + } + }; } diff --git a/toolsrc/src/tests.update.cpp b/toolsrc/src/tests.update.cpp index 06ae797f4..b6e487c17 100644 --- a/toolsrc/src/tests.update.cpp +++ b/toolsrc/src/tests.update.cpp @@ -9,6 +9,8 @@ using namespace vcpkg::Update; namespace UnitTest1 { + using Pgh = std::vector>; + class UpdateTests : public TestClass { TEST_METHOD(find_outdated_packages_basic) @@ -19,10 +21,12 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::map port_versions; - port_versions["a"] = VersionT("0"); + std::unordered_map map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); + map.emplace("a", std::move(*scf)); + Dependencies::MapPortFileProvider provider(map); - auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(1), pkgs.size()); @@ -41,10 +45,12 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::map port_versions; - port_versions["a"] = VersionT("0"); + std::unordered_map map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); + map.emplace("a", std::move(*scf)); + Dependencies::MapPortFileProvider provider(map); - auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(1), pkgs.size()); @@ -65,10 +71,12 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::map port_versions; - port_versions["a"] = VersionT("0"); + std::unordered_map map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); + map.emplace("a", std::move(*scf)); + Dependencies::MapPortFileProvider provider(map); - auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(1), pkgs.size()); @@ -84,10 +92,12 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(status_paragraphs)); - std::map port_versions; - port_versions["a"] = VersionT("2"); + std::unordered_map map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "2"}}})); + map.emplace("a", std::move(*scf)); + Dependencies::MapPortFileProvider provider(map); - auto pkgs = SortedVector(Update::find_outdated_packages(port_versions, status_db), + auto pkgs = SortedVector(Update::find_outdated_packages(provider, status_db), &OutdatedPackage::compare_by_name); Assert::AreEqual(size_t(0), pkgs.size()); diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp index ed28d6e2b..23f2cc630 100644 --- a/toolsrc/src/vcpkg/base/checks.cpp +++ b/toolsrc/src/vcpkg/base/checks.cpp @@ -49,8 +49,7 @@ namespace vcpkg::Checks #else void register_console_ctrl_handler() {} #endif - - [[noreturn]] void unreachable(const LineInfo& line_info) + void unreachable(const LineInfo& line_info) { System::println(System::Color::error, "Error: Unreachable code was reached"); System::println(System::Color::error, line_info.to_string()); // Always print line_info here @@ -61,13 +60,13 @@ namespace vcpkg::Checks #endif } - [[noreturn]] void exit_with_code(const LineInfo& line_info, const int exit_code) + void exit_with_code(const LineInfo& line_info, const int exit_code) { Debug::println(System::Color::error, line_info.to_string()); cleanup_and_exit(exit_code); } - [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView error_message) + void exit_with_message(const LineInfo& line_info, const CStringView error_message) { System::println(System::Color::error, error_message); exit_fail(line_info); @@ -77,7 +76,7 @@ namespace vcpkg::Checks { if (!expression) { - exit_with_message(line_info, ""); + exit_fail(line_info); } } diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index b8f122b27..f43d8788e 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -260,13 +260,13 @@ namespace vcpkg::Build const BuildPackageConfig& config, const StatusParagraphs& status_db) { - const PackageSpec spec = - PackageSpec::from_name_and_triplet(config.src.name, config.triplet).value_or_exit(VCPKG_LINE_INFO); + const PackageSpec spec = PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, config.triplet) + .value_or_exit(VCPKG_LINE_INFO); const Triplet& triplet = config.triplet; { std::vector missing_specs; - for (auto&& dep : filter_dependencies(config.src.depends, triplet)) + for (auto&& dep : filter_dependencies(config.scf.core_paragraph->depends, triplet)) { if (status_db.find_installed(dep, triplet) == status_db.end()) { @@ -290,16 +290,13 @@ namespace vcpkg::Build std::string features; if (GlobalState::feature_packages) { - if (config.feature_list) + for (auto&& feature : config.feature_list) { - for (auto&& feature : *config.feature_list) - { - features.append(feature + ";"); - } - if (features.size() > 0) - { - features.pop_back(); - } + features.append(feature + ";"); + } + if (features.size() > 0) + { + features.pop_back(); } } @@ -309,7 +306,7 @@ namespace vcpkg::Build ports_cmake_script_path, { {"CMD", "BUILD"}, - {"PORT", config.src.name}, + {"PORT", config.scf.core_paragraph->name}, {"CURRENT_PORT_DIR", config.port_dir / "/."}, {"TARGET_TRIPLET", triplet.canonical_name()}, {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, @@ -343,7 +340,7 @@ namespace vcpkg::Build const BuildInfo build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); - auto bcf = create_binary_control_file(config.src, triplet, build_info); + auto bcf = create_binary_control_file(*config.scf.core_paragraph, triplet, build_info); if (error_count != 0) { @@ -351,16 +348,13 @@ namespace vcpkg::Build } if (GlobalState::feature_packages) { - if (config.feature_list) + for (auto&& feature : config.feature_list) { - for (auto&& feature : *config.feature_list) + for (auto&& f_pgh : config.scf.feature_paragraphs) { - for (auto&& f_pgh : config.scf->feature_paragraphs) - { - if (f_pgh->name == feature) - bcf->features.push_back( - create_binary_feature_control_file(*config.scf->core_paragraph, *f_pgh, triplet)); - } + if (f_pgh->name == feature) + bcf->features.push_back( + create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet)); } } } diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index f2e984bf8..1a2f9b47f 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -27,7 +27,7 @@ namespace vcpkg::Commands::CI const std::vector specs = PackageSpec::to_package_specs(ports, triplet); StatusParagraphs status_db = database_load_check(paths); - const auto& paths_port_file = Dependencies::PathsPortFile(paths); + const auto& paths_port_file = Dependencies::PathsPortFileProvider(paths); std::vector install_plan = Dependencies::create_install_plan(paths_port_file, specs, status_db); diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index 15b10c7ea..ccf6fa729 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -13,9 +13,10 @@ namespace vcpkg::Commands Span> get_available_commands_type_a() { static std::vector> t = { - PackageNameAndFunction{"install", &Install::perform_and_exit}, + {"install", &Install::perform_and_exit}, {"ci", &CI::perform_and_exit}, {"remove", &Remove::perform_and_exit}, + {"upgrade", &Upgrade::perform_and_exit}, {"build", &Build::Command::perform_and_exit}, {"env", &Env::perform_and_exit}, {"build-external", &BuildExternal::perform_and_exit}, diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp index 6752715e4..dba04ce5b 100644 --- a/toolsrc/src/vcpkg/commands.portsdiff.cpp +++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp @@ -98,8 +98,11 @@ namespace vcpkg::Commands::PortsDiff ".vcpkg-root", git_exe.u8string()); System::cmd_execute_clean(cmd); - const std::map names_and_versions = Paragraphs::load_all_port_names_and_versions( - paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); + const auto all_ports = + Paragraphs::load_all_ports(paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); + std::map names_and_versions; + for (auto&& port : all_ports) + names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version); fs.remove_all(temp_checkout_path, ec); return names_and_versions; } diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 0a1f79834..a48f3f1d8 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -65,26 +65,19 @@ namespace vcpkg::Dependencies struct ClusterGraph : Util::MoveOnlyBase { - explicit ClusterGraph(std::unordered_map&& ports) - : m_ports(std::move(ports)) - { - } + explicit ClusterGraph(const PortFileProvider& provider) : m_provider(provider) {} Cluster& get(const PackageSpec& spec) { auto it = m_graph.find(spec); if (it == m_graph.end()) { - // Load on-demand from m_ports - auto it_ports = m_ports.find(spec.name()); - if (it_ports != m_ports.end()) - { - auto& clust = m_graph[spec]; - clust.spec = spec; - cluster_from_scf(*it_ports->second, clust); - return clust; - } - return m_graph[spec]; + // Load on-demand from m_provider + auto maybe_scf = m_provider.get_control_file(spec.name()); + auto& clust = m_graph[spec]; + clust.spec = spec; + if (auto p_scf = maybe_scf.get()) cluster_from_scf(*p_scf, clust); + return clust; } return it->second; } @@ -107,7 +100,7 @@ namespace vcpkg::Dependencies } std::unordered_map m_graph; - std::unordered_map m_ports; + const PortFileProvider& m_provider; }; std::vector AnyParagraph::dependencies(const Triplet& triplet) const @@ -124,9 +117,10 @@ namespace vcpkg::Dependencies return PackageSpec::from_dependencies_of_port(p->core_paragraph.spec.name(), deps, triplet); } - if (const auto p = this->source_paragraph.get()) + if (const auto p = this->source_control_file.value_or(nullptr)) { - return PackageSpec::from_dependencies_of_port(p->name, filter_dependencies(p->depends, triplet), triplet); + return PackageSpec::from_dependencies_of_port( + p->core_paragraph->name, filter_dependencies(p->core_paragraph->depends, triplet), triplet); } Checks::exit_with_message(VCPKG_LINE_INFO, @@ -192,11 +186,13 @@ namespace vcpkg::Dependencies return; } - if (auto p = any_paragraph.source_paragraph.get()) + if (auto p = any_paragraph.source_control_file.get()) { this->plan_type = InstallPlanType::BUILD_AND_INSTALL; return; } + + Checks::unreachable(VCPKG_LINE_INFO); } std::string InstallPlanAction::displayname() const @@ -226,12 +222,12 @@ namespace vcpkg::Dependencies const PackageSpec& AnyAction::spec() const { - if (const auto p = install_plan.get()) + if (const auto p = install_action.get()) { return p->spec; } - if (const auto p = remove_plan.get()) + if (const auto p = remove_action.get()) { return p->spec; } @@ -257,7 +253,7 @@ namespace vcpkg::Dependencies return; } - if (auto p = any_paragraph.source_paragraph.get()) + if (auto p = any_paragraph.source_control_file.get()) { this->plan_type = ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT; return; @@ -269,21 +265,20 @@ namespace vcpkg::Dependencies return left->spec.name() < right->spec.name(); } - MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map) {} + MapPortFileProvider::MapPortFileProvider(const std::unordered_map& map) : ports(map) + { + } - const SourceControlFile& MapPortFile::get_control_file(const std::string& spec) const + Optional MapPortFileProvider::get_control_file(const std::string& spec) const { auto scf = ports.find(spec); - if (scf == ports.end()) - { - Checks::exit_fail(VCPKG_LINE_INFO); - } + if (scf == ports.end()) return nullopt; return scf->second; } - PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths) {} + PathsPortFileProvider::PathsPortFileProvider(const VcpkgPaths& paths) : ports(paths) {} - const SourceControlFile& PathsPortFile::get_control_file(const std::string& spec) const + Optional PathsPortFileProvider::get_control_file(const std::string& spec) const { auto cache_it = cache.find(spec); if (cache_it != cache.end()) @@ -298,56 +293,34 @@ namespace vcpkg::Dependencies auto it = cache.emplace(spec, std::move(*scf->get())); return it.first->second; } - print_error_message(source_control_file.error()); - Checks::exit_fail(VCPKG_LINE_INFO); + return nullopt; } std::vector create_install_plan(const PortFileProvider& port_file_provider, const std::vector& specs, const StatusParagraphs& status_db) { - struct InstallAdjacencyProvider final : Graphs::AdjacencyProvider - { - const PortFileProvider& port_file_provider; - const StatusParagraphs& status_db; - const std::unordered_set& specs_as_set; + auto fspecs = Util::fmap(specs, [](const PackageSpec& spec) { return FeatureSpec(spec, ""); }); + auto plan = create_feature_install_plan(port_file_provider, fspecs, status_db); - InstallAdjacencyProvider(const PortFileProvider& port_file_provider, - const StatusParagraphs& s, - const std::unordered_set& specs_as_set) - : port_file_provider(port_file_provider), status_db(s), specs_as_set(specs_as_set) - { - } + std::vector ret; + ret.reserve(plan.size()); - std::vector adjacency_list(const InstallPlanAction& plan) const override + for (auto&& action : plan) + { + if (auto p_install = action.install_action.get()) { - if (plan.any_paragraph.status_paragraph.get()) return std::vector{}; - return plan.any_paragraph.dependencies(plan.spec.triplet()); + ret.push_back(std::move(*p_install)); } - - InstallPlanAction load_vertex_data(const PackageSpec& spec) const override + else { - const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() - ? RequestType::USER_REQUESTED - : RequestType::AUTO_SELECTED; - auto it = status_db.find_installed(spec); - if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type}; - return InstallPlanAction{ - spec, - {nullopt, nullopt, *port_file_provider.get_control_file(spec.name()).core_paragraph}, - request_type}; + Checks::exit_with_message(VCPKG_LINE_INFO, + "The installation plan requires feature packages support. Please re-run the " + "command with --featurepackages."); } - }; - - const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); - std::vector toposort = - Graphs::topological_sort(specs, InstallAdjacencyProvider{port_file_provider, status_db, specs_as_set}); - Util::erase_remove_if(toposort, [](const InstallPlanAction& plan) { - return plan.request_type == RequestType::AUTO_SELECTED && - plan.plan_type == InstallPlanType::ALREADY_INSTALLED; - }); + } - return toposort; + return ret; } std::vector create_remove_plan(const std::vector& specs, @@ -407,7 +380,8 @@ namespace vcpkg::Dependencies return Graphs::topological_sort(specs, RemoveAdjacencyProvider{status_db, installed_ports, specs_as_set}); } - std::vector create_export_plan(const VcpkgPaths& paths, + std::vector create_export_plan(const PortFileProvider& port_file_provider, + const VcpkgPaths& paths, const std::vector& specs, const StatusParagraphs& status_db) { @@ -415,12 +389,14 @@ namespace vcpkg::Dependencies { const VcpkgPaths& paths; const StatusParagraphs& status_db; + const PortFileProvider& provider; const std::unordered_set& specs_as_set; ExportAdjacencyProvider(const VcpkgPaths& p, const StatusParagraphs& s, + const PortFileProvider& prov, const std::unordered_set& specs_as_set) - : paths(p), status_db(s), specs_as_set(specs_as_set) + : paths(p), status_db(s), provider(prov), specs_as_set(specs_as_set) { } @@ -439,19 +415,16 @@ namespace vcpkg::Dependencies if (auto bcf = maybe_bpgh.get()) return ExportPlanAction{spec, AnyParagraph{nullopt, std::move(*bcf), nullopt}, request_type}; - auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); - if (auto scf = maybe_scf.get()) - return ExportPlanAction{spec, {nullopt, nullopt, *scf->get()->core_paragraph}, request_type}; - else - print_error_message(maybe_scf.error()); + auto maybe_scf = provider.get_control_file(spec.name()); + if (auto scf = maybe_scf.get()) return ExportPlanAction{spec, {nullopt, nullopt, scf}, request_type}; Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); } }; const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); - std::vector toposort = - Graphs::topological_sort(specs, ExportAdjacencyProvider{paths, status_db, specs_as_set}); + std::vector toposort = Graphs::topological_sort( + specs, ExportAdjacencyProvider{paths, status_db, port_file_provider, specs_as_set}); return toposort; } @@ -461,11 +434,12 @@ namespace vcpkg::Dependencies SUCCESS, }; - MarkPlusResult mark_plus(const std::string& feature, - Cluster& cluster, - ClusterGraph& pkg_to_cluster, - GraphPlan& graph_plan); - void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + static MarkPlusResult mark_plus(const std::string& feature, + Cluster& cluster, + ClusterGraph& pkg_to_cluster, + GraphPlan& graph_plan); + + static void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { @@ -557,110 +531,80 @@ namespace vcpkg::Dependencies } } - static ClusterGraph create_feature_install_graph(const std::unordered_map& map, - const StatusParagraphs& status_db) + std::vector create_feature_install_plan(const PortFileProvider& provider, + const std::vector& specs, + const StatusParagraphs& status_db) { - std::unordered_map ptr_map; - for (auto&& p : map) - ptr_map.emplace(p.first, &p.second); - ClusterGraph graph(std::move(ptr_map)); - - auto installed_ports = get_installed_ports(status_db); - - for (auto&& status_paragraph : installed_ports) - { - Cluster& cluster = graph.get(status_paragraph->package.spec); - - cluster.transient_uninstalled = false; - - cluster.status_paragraphs.emplace_back(status_paragraph); - - auto& status_paragraph_feature = status_paragraph->package.feature; - // In this case, empty string indicates the "core" paragraph for a package. - if (status_paragraph_feature.empty()) - { - cluster.original_features.insert("core"); - } - else - { - cluster.original_features.insert(status_paragraph_feature); - } - } - - for (auto&& status_paragraph : installed_ports) - { - auto& spec = status_paragraph->package.spec; - auto& status_paragraph_feature = status_paragraph->package.feature; - auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, - status_paragraph->package.spec.triplet()); - - for (auto&& dependency : reverse_edges) - { - auto& dep_cluster = graph.get(dependency.spec()); - - auto depends_name = dependency.feature(); - if (depends_name.empty()) depends_name = "core"; + PackageGraph pgraph(provider, status_db); + for (auto&& spec : specs) + pgraph.install(spec); - auto& target_node = dep_cluster.edges[depends_name]; - target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); - } - } - return graph; + return pgraph.serialize(); } std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db) { - ClusterGraph graph = create_feature_install_graph(map, status_db); + MapPortFileProvider provider(map); + return create_feature_install_plan(provider, specs, status_db); + } - GraphPlan graph_plan; - for (auto&& spec : specs) + void PackageGraph::install(const FeatureSpec& spec) + { + Cluster& spec_cluster = m_graph->get(spec.spec()); + spec_cluster.request_type = RequestType::USER_REQUESTED; + if (spec.feature() == "*") { - Cluster& spec_cluster = graph.get(spec.spec()); - spec_cluster.request_type = RequestType::USER_REQUESTED; - if (spec.feature() == "*") + if (auto p_scf = spec_cluster.source_control_file.value_or(nullptr)) { - if (auto p_scf = spec_cluster.source_control_file.value_or(nullptr)) + for (auto&& feature : p_scf->feature_paragraphs) { - for (auto&& feature : p_scf->feature_paragraphs) - { - auto res = mark_plus(feature->name, spec_cluster, graph, graph_plan); - - Checks::check_exit(VCPKG_LINE_INFO, - res == MarkPlusResult::SUCCESS, - "Error: Unable to locate feature %s", - spec); - } - - auto res = mark_plus("core", spec_cluster, graph, graph_plan); + auto res = mark_plus(feature->name, spec_cluster, *m_graph, *m_graph_plan); Checks::check_exit( VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); } - else - { - Checks::exit_with_message( - VCPKG_LINE_INFO, "Error: Unable to handle '*' because can't find CONTROL for %s", spec.spec()); - } - } - else - { - auto res = mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + + auto res = mark_plus("core", spec_cluster, *m_graph, *m_graph_plan); Checks::check_exit( VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); } + else + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "Error: Unable to handle '*' because can't find CONTROL for %s", spec.spec()); + } + } + else + { + auto res = mark_plus(spec.feature(), spec_cluster, *m_graph, *m_graph_plan); - graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster}); + Checks::check_exit( + VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); } - Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); - auto remove_vertex_list = graph_plan.remove_graph.vertex_list(); + m_graph_plan->install_graph.add_vertex(ClusterPtr{&spec_cluster}); + } + + void PackageGraph::upgrade(const PackageSpec& spec) + { + Cluster& spec_cluster = m_graph->get(spec); + spec_cluster.request_type = RequestType::USER_REQUESTED; + + mark_minus(spec_cluster, *m_graph, *m_graph_plan); + } + + std::vector PackageGraph::serialize() const + { + Graphs::GraphAdjacencyProvider adjacency_remove_graph(m_graph_plan->remove_graph.adjacency_list()); + auto remove_vertex_list = m_graph_plan->remove_graph.vertex_list(); auto remove_toposort = Graphs::topological_sort(remove_vertex_list, adjacency_remove_graph); - Graphs::GraphAdjacencyProvider adjacency_install_graph(graph_plan.install_graph.adjacency_list()); - auto insert_vertex_list = graph_plan.install_graph.vertex_list(); + Graphs::GraphAdjacencyProvider adjacency_install_graph( + m_graph_plan->install_graph.adjacency_list()); + auto insert_vertex_list = m_graph_plan->install_graph.vertex_list(); auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph); std::vector plan; @@ -705,4 +649,162 @@ namespace vcpkg::Dependencies return plan; } + + static std::unique_ptr create_feature_install_graph(const PortFileProvider& map, + const StatusParagraphs& status_db) + { + std::unique_ptr graph = std::make_unique(map); + + auto installed_ports = get_installed_ports(status_db); + + for (auto&& status_paragraph : installed_ports) + { + Cluster& cluster = graph->get(status_paragraph->package.spec); + + cluster.transient_uninstalled = false; + + cluster.status_paragraphs.emplace_back(status_paragraph); + + auto& status_paragraph_feature = status_paragraph->package.feature; + // In this case, empty string indicates the "core" paragraph for a package. + if (status_paragraph_feature.empty()) + { + cluster.original_features.insert("core"); + } + else + { + cluster.original_features.insert(status_paragraph_feature); + } + } + + // Populate the graph with "remove edges", which are the reverse of the Build-Depends edges. + for (auto&& status_paragraph : installed_ports) + { + auto& spec = status_paragraph->package.spec; + auto& status_paragraph_feature = status_paragraph->package.feature; + auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, + status_paragraph->package.spec.triplet()); + + for (auto&& dependency : reverse_edges) + { + auto& dep_cluster = graph->get(dependency.spec()); + + auto depends_name = dependency.feature(); + if (depends_name.empty()) depends_name = "core"; + + auto& target_node = dep_cluster.edges[depends_name]; + target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); + } + } + return graph; + } + + PackageGraph::PackageGraph(const PortFileProvider& provider, const StatusParagraphs& status_db) + : m_graph(create_feature_install_graph(provider, status_db)), m_graph_plan(std::make_unique()) + { + } + + PackageGraph::~PackageGraph() {} + + void print_plan(const std::vector& action_plan, const bool is_recursive) + { + std::vector remove_plans; + std::vector rebuilt_plans; + std::vector only_install_plans; + std::vector new_plans; + std::vector already_installed_plans; + std::vector excluded; + + const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { + if (auto iplan = package.install_action.get()) + return iplan->request_type != RequestType::USER_REQUESTED; + else + return false; + }) != action_plan.cend(); + + for (auto&& action : action_plan) + { + if (auto install_action = action.install_action.get()) + { + // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at + // all. + auto it = Util::find_if( + remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); + if (it != remove_plans.end()) + { + rebuilt_plans.emplace_back(install_action); + } + else + { + switch (install_action->plan_type) + { + case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break; + case InstallPlanType::ALREADY_INSTALLED: + if (install_action->request_type == RequestType::USER_REQUESTED) + already_installed_plans.emplace_back(install_action); + break; + case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break; + case InstallPlanType::EXCLUDED: excluded.emplace_back(install_action); break; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + } + else if (auto remove_action = action.remove_action.get()) + { + remove_plans.emplace_back(remove_action); + } + } + + std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name); + std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(excluded.begin(), excluded.end(), &InstallPlanAction::compare_by_name); + + static auto actions_to_output_string = [](const std::vector& v) { + return Strings::join("\n", v, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname(), p->build_options); + }); + }; + + if (excluded.size() > 0) + { + System::println("The following packages are excluded:\n%s", actions_to_output_string(excluded)); + } + + if (already_installed_plans.size() > 0) + { + System::println("The following packages are already installed:\n%s", + actions_to_output_string(already_installed_plans)); + } + + if (rebuilt_plans.size() > 0) + { + System::println("The following packages will be rebuilt:\n%s", actions_to_output_string(rebuilt_plans)); + } + + if (new_plans.size() > 0) + { + System::println("The following packages will be built and installed:\n%s", + actions_to_output_string(new_plans)); + } + + if (only_install_plans.size() > 0) + { + System::println("The following packages will be directly installed:\n%s", + actions_to_output_string(only_install_plans)); + } + + if (has_non_user_requested_packages) + System::println("Additional packages (*) will be modified to complete this operation."); + + if (remove_plans.size() > 0 && !is_recursive) + { + System::println(System::Color::warning, + "If you are sure you want to rebuild the above packages, run the command with the " + "--recurse option"); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } } diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 32cb6f03e..e3221a12f 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -478,7 +478,9 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console // create the plan const StatusParagraphs status_db = database_load_check(paths); - std::vector export_plan = Dependencies::create_export_plan(paths, opts.specs, status_db); + Dependencies::PathsPortFileProvider provider(paths); + std::vector export_plan = + Dependencies::create_export_plan(provider, paths, opts.specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty"); std::map> group_by_plan_type; diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index c83f0277b..b7d355742 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -85,6 +85,7 @@ namespace vcpkg::Help " vcpkg remove --outdated Uninstall all out-of-date packages\n" " vcpkg list List installed packages\n" " vcpkg update Display list of packages for updating\n" + " vcpkg upgrade Rebuild all outdated packages\n" " vcpkg hash [alg] Hash a file by specific algorithm, default SHA512\n" " vcpkg help topics Display the list of help topics\n" " vcpkg help Display help for a specific topic\n" diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 76dc7a527..dcc130be3 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -292,25 +292,13 @@ namespace vcpkg::Install System::println("Building package %s... ", display_name_with_features); auto result = [&]() -> Build::ExtendedBuildResult { - if (GlobalState::feature_packages) - { - const Build::BuildPackageConfig build_config{ - *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), - action.spec.triplet(), - paths.port_dir(action.spec), - action.build_options, - action.feature_list}; - return Build::build_package(paths, build_config, status_db); - } - else - { - const Build::BuildPackageConfig build_config{ - action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO), - action.spec.triplet(), - paths.port_dir(action.spec), - action.build_options}; - return Build::build_package(paths, build_config, status_db); - } + const Build::BuildPackageConfig build_config{ + *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), + action.spec.triplet(), + paths.port_dir(action.spec), + action.build_options, + action.feature_list}; + return Build::build_package(paths, build_config, status_db); }(); if (result.code != Build::BuildResult::SUCCEEDED) @@ -348,108 +336,6 @@ namespace vcpkg::Install Checks::unreachable(VCPKG_LINE_INFO); } - static void print_plan(const std::vector& action_plan, const bool is_recursive) - { - std::vector remove_plans; - std::vector rebuilt_plans; - std::vector only_install_plans; - std::vector new_plans; - std::vector already_installed_plans; - std::vector excluded; - - const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { - if (auto iplan = package.install_plan.get()) - return iplan->request_type != RequestType::USER_REQUESTED; - else - return false; - }) != action_plan.cend(); - - for (auto&& action : action_plan) - { - if (auto install_action = action.install_plan.get()) - { - // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at - // all. - auto it = Util::find_if( - remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); - if (it != remove_plans.end()) - { - rebuilt_plans.emplace_back(install_action); - } - else - { - switch (install_action->plan_type) - { - case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break; - case InstallPlanType::ALREADY_INSTALLED: - if (install_action->request_type == RequestType::USER_REQUESTED) - already_installed_plans.emplace_back(install_action); - break; - case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break; - case InstallPlanType::EXCLUDED: excluded.emplace_back(install_action); break; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - } - else if (auto remove_action = action.remove_plan.get()) - { - remove_plans.emplace_back(remove_action); - } - } - - std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name); - std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name); - std::sort(excluded.begin(), excluded.end(), &InstallPlanAction::compare_by_name); - - static auto actions_to_output_string = [](const std::vector& v) { - return Strings::join("\n", v, [](const InstallPlanAction* p) { - return to_output_string(p->request_type, p->displayname(), p->build_options); - }); - }; - - if (excluded.size() > 0) - { - System::println("The following packages are excluded:\n%s", actions_to_output_string(excluded)); - } - - if (already_installed_plans.size() > 0) - { - System::println("The following packages are already installed:\n%s", - actions_to_output_string(already_installed_plans)); - } - - if (rebuilt_plans.size() > 0) - { - System::println("The following packages will be rebuilt:\n%s", actions_to_output_string(rebuilt_plans)); - } - - if (new_plans.size() > 0) - { - System::println("The following packages will be built and installed:\n%s", - actions_to_output_string(new_plans)); - } - - if (only_install_plans.size() > 0) - { - System::println("The following packages will be directly installed:\n%s", - actions_to_output_string(only_install_plans)); - } - - if (has_non_user_requested_packages) - System::println("Additional packages (*) will be installed to complete this operation."); - - if (remove_plans.size() > 0 && !is_recursive) - { - System::println(System::Color::warning, - "If you are sure you want to rebuild the above packages, run the command with the " - "--recurse option"); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - void InstallSummary::print() const { System::println("RESULTS"); @@ -499,7 +385,7 @@ namespace vcpkg::Install results.emplace_back(spec, &action); - if (const auto install_action = action.install_plan.get()) + if (const auto install_action = action.install_action.get()) { auto result = perform_install_plan_action(paths, *install_action, status_db); @@ -511,9 +397,8 @@ namespace vcpkg::Install results.back().build_result = std::move(result); } - else if (const auto remove_action = action.remove_plan.get()) + else if (const auto remove_action = action.remove_action.get()) { - Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages); Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db); } else @@ -676,31 +561,33 @@ namespace vcpkg::Install }; // Note: action_plan will hold raw pointers to SourceControlFiles from this map - std::unordered_map scf_map; std::vector action_plan; - if (GlobalState::feature_packages) + auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + std::unordered_map scf_map; + for (auto&& port : all_ports) + scf_map[port->core_paragraph->name] = std::move(*port); + MapPortFileProvider provider(scf_map); + + action_plan = create_feature_install_plan(provider, FullPackageSpec::to_feature_specs(specs), status_db); + + if (!GlobalState::feature_packages) { - auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - for (auto&& port : all_ports) + for (auto&& action : action_plan) { - scf_map[port->core_paragraph->name] = std::move(*port); + if (action.remove_action.has_value()) + { + Checks::exit_with_message( + VCPKG_LINE_INFO, + "The installation plan requires feature packages support. Please re-run the " + "command with --featurepackages."); + } } - action_plan = create_feature_install_plan(scf_map, FullPackageSpec::to_feature_specs(specs), status_db); - } - else - { - Dependencies::PathsPortFile paths_port_file(paths); - auto install_plan = Dependencies::create_install_plan( - paths_port_file, Util::fmap(specs, [](auto&& spec) { return spec.package_spec; }), status_db); - - action_plan = Util::fmap( - install_plan, [](InstallPlanAction& install_action) { return AnyAction(std::move(install_action)); }); } for (auto&& action : action_plan) { - if (auto p_install = action.install_plan.get()) + if (auto p_install = action.install_action.get()) { p_install->build_options = install_plan_options; if (p_install->request_type != RequestType::USER_REQUESTED) @@ -713,16 +600,16 @@ namespace vcpkg::Install // log the plan const std::string specs_string = Strings::join(",", action_plan, [](const AnyAction& action) { - if (auto iaction = action.install_plan.get()) + if (auto iaction = action.install_action.get()) return iaction->spec.to_string(); - else if (auto raction = action.remove_plan.get()) + else if (auto raction = action.remove_action.get()) return "R$" + raction->spec.to_string(); Checks::unreachable(VCPKG_LINE_INFO); }); Metrics::g_metrics.lock()->track_property("installplan", specs_string); - print_plan(action_plan, is_recursive); + Dependencies::print_plan(action_plan, is_recursive); if (dry_run) { @@ -752,7 +639,7 @@ namespace vcpkg::Install for (auto&& result : summary.results) { if (!result.action) continue; - if (auto p_install_action = result.action->install_plan.get()) + if (auto p_install_action = result.action->install_action.get()) { if (p_install_action->request_type != RequestType::USER_REQUESTED) continue; auto bpgh = result.get_binary_paragraph(); @@ -773,7 +660,7 @@ namespace vcpkg::Install { if (build_result.binary_control_file) return &build_result.binary_control_file->core_paragraph; if (action) - if (auto p_install_plan = action->install_plan.get()) + if (auto p_install_plan = action->install_action.get()) { if (auto p_bcf = p_install_plan->any_paragraph.binary_control_file.get()) return &p_bcf->core_paragraph; diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp index b93de190c..b66d53994 100644 --- a/toolsrc/src/vcpkg/paragraphs.cpp +++ b/toolsrc/src/vcpkg/paragraphs.cpp @@ -289,16 +289,4 @@ namespace vcpkg::Paragraphs } return std::move(results.paragraphs); } - - std::map load_all_port_names_and_versions(const Files::Filesystem& fs, - const fs::path& ports_dir) - { - auto all_ports = load_all_ports(fs, ports_dir); - - std::map names_and_versions; - for (auto&& port : all_ports) - names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version); - - return names_and_versions; - } } diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 8ae0bc881..4079d60c1 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -207,10 +207,11 @@ namespace vcpkg::Remove System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'"); Checks::exit_fail(VCPKG_LINE_INFO); } - specs = Util::fmap( - Update::find_outdated_packages( - Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports), status_db), - [](auto&& outdated) { return outdated.spec; }); + + Dependencies::PathsPortFileProvider provider(paths); + + specs = Util::fmap(Update::find_outdated_packages(provider, status_db), + [](auto&& outdated) { return outdated.spec; }); if (specs.empty()) { diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp index 29baef91e..d6c5614ed 100644 --- a/toolsrc/src/vcpkg/update.cpp +++ b/toolsrc/src/vcpkg/update.cpp @@ -14,7 +14,7 @@ namespace vcpkg::Update return left.spec.name() < right.spec.name(); } - std::vector find_outdated_packages(const std::map& src_names_to_versions, + std::vector find_outdated_packages(const Dependencies::PortFileProvider& provider, const StatusParagraphs& status_db) { const std::vector installed_packages = get_installed_ports(status_db); @@ -24,19 +24,23 @@ namespace vcpkg::Update { if (!pgh->package.feature.empty()) { - // Skip feature packages; only consider master packages for needing updates. + // Skip feature paragraphs; only consider master paragraphs for needing updates. continue; } - const auto it = src_names_to_versions.find(pgh->package.spec.name()); - if (it == src_names_to_versions.end()) + auto maybe_scf = provider.get_control_file(pgh->package.spec.name()); + if (auto p_scf = maybe_scf.get()) { - // Package was not installed from portfile - continue; + auto&& port_version = p_scf->core_paragraph->version; + auto&& installed_version = pgh->package.version; + if (installed_version != port_version) + { + output.push_back({pgh->package.spec, VersionDiff(installed_version, port_version)}); + } } - if (it->second != pgh->package.version) + else { - output.push_back({pgh->package.spec, VersionDiff(pgh->package.version, it->second)}); + // No portfile available } } @@ -58,10 +62,10 @@ namespace vcpkg::Update const StatusParagraphs status_db = database_load_check(paths); - const auto outdated_packages = SortedVector( - find_outdated_packages(Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports), - status_db), - &OutdatedPackage::compare_by_name); + Dependencies::PathsPortFileProvider provider(paths); + + const auto outdated_packages = SortedVector(find_outdated_packages(provider, status_db), + &OutdatedPackage::compare_by_name); if (outdated_packages.empty()) { @@ -69,19 +73,17 @@ namespace vcpkg::Update } else { - std::string install_line; System::println("The following packages differ from their port versions:"); for (auto&& package : outdated_packages) { - install_line += package.spec.to_string(); - install_line += " "; System::println(" %-32s %s", package.spec, package.version_diff.to_string()); } System::println("\n" - "To update these packages, run\n" - " .\\vcpkg remove --outdated\n" - " .\\vcpkg install " + - install_line); + "To update these packages and all dependencies, run\n" + " .\\vcpkg upgrade\n" + "\n" + "To only remove outdated packages, run\n" + " .\\vcpkg remove --outdated\n"); } Checks::exit_success(VCPKG_LINE_INFO); -- cgit v1.2.3 From 0ba4b66293085601d458b52ddf30deb07b279fa1 Mon Sep 17 00:00:00 2001 From: JUAN DENT Date: Wed, 13 Dec 2017 11:55:22 -0600 Subject: Add quotation marks to support user profiles with spaces in them --- toolsrc/src/vcpkg/metrics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index a0d40e7d3..dc7bf824c 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -403,7 +403,7 @@ namespace vcpkg::Metrics fs.write_contents(vcpkg_metrics_txt_path, payload); const std::string cmd_line = - Strings::format("start %s %s", temp_folder_path_exe.u8string(), vcpkg_metrics_txt_path.u8string()); + Strings::format("start \"%s\" \"%s\"", temp_folder_path_exe.u8string(), vcpkg_metrics_txt_path.u8string()); System::cmd_execute_clean(cmd_line); #endif } -- cgit v1.2.3 From e44da2345681f60ea6d1b923672cb5042a336d12 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Dec 2017 10:46:10 -0800 Subject: Revert "Add quotation marks to support user profiles with spaces in them" This reverts commit 0ba4b66293085601d458b52ddf30deb07b279fa1. --- toolsrc/src/vcpkg/metrics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index dc7bf824c..a0d40e7d3 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -403,7 +403,7 @@ namespace vcpkg::Metrics fs.write_contents(vcpkg_metrics_txt_path, payload); const std::string cmd_line = - Strings::format("start \"%s\" \"%s\"", temp_folder_path_exe.u8string(), vcpkg_metrics_txt_path.u8string()); + Strings::format("start %s %s", temp_folder_path_exe.u8string(), vcpkg_metrics_txt_path.u8string()); System::cmd_execute_clean(cmd_line); #endif } -- cgit v1.2.3 From 7a2120dba1fb606b06f555965908db438d10e019 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Dec 2017 11:02:04 -0800 Subject: [vcpkg] Revert revert of #2369. --- toolsrc/src/vcpkg/commands.version.cpp | 7 +++++++ toolsrc/src/vcpkg/metrics.cpp | 13 +++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.version.cpp b/toolsrc/src/vcpkg/commands.version.cpp index 3f44cf1a2..c21e8cafd 100644 --- a/toolsrc/src/vcpkg/commands.version.cpp +++ b/toolsrc/src/vcpkg/commands.version.cpp @@ -12,6 +12,13 @@ namespace vcpkg::Commands::Version { + const char* base_version() + { + return +#include "../VERSION.txt" + ; + } + const std::string& version() { static const std::string S_VERSION = diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index a0d40e7d3..cdb21d260 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include #include #include @@ -376,8 +377,9 @@ namespace vcpkg::Metrics wchar_t temp_folder[MAX_PATH]; GetTempPathW(MAX_PATH, temp_folder); - const fs::path temp_folder_path = temp_folder; - const fs::path temp_folder_path_exe = temp_folder_path / "vcpkgmetricsuploader.exe"; + const fs::path temp_folder_path = fs::path(temp_folder) / "vcpkg"; + const fs::path temp_folder_path_exe = + temp_folder_path / Strings::format("vcpkgmetricsuploader-%s.exe", Commands::Version::base_version()); auto& fs = Files::get_real_filesystem(); @@ -395,6 +397,8 @@ namespace vcpkg::Metrics }(); std::error_code ec; + fs.create_directories(temp_folder_path, ec); + if (ec) return; fs.copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec); if (ec) return; } @@ -402,8 +406,9 @@ namespace vcpkg::Metrics const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); fs.write_contents(vcpkg_metrics_txt_path, payload); - const std::string cmd_line = - Strings::format("start %s %s", temp_folder_path_exe.u8string(), vcpkg_metrics_txt_path.u8string()); + const std::string cmd_line = Strings::format("start \"vcpkgmetricsuploader.exe\" \"%s\" \"%s\"", + temp_folder_path_exe.u8string(), + vcpkg_metrics_txt_path.u8string()); System::cmd_execute_clean(cmd_line); #endif } -- cgit v1.2.3 From 63a23cf0cad4da12eed69883f37c21d319461187 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 14 Dec 2017 14:31:16 -0800 Subject: [vcpkg] Fix regressions in WSL build. --- toolsrc/src/commands.upgrade.cpp | 180 --------------------------------- toolsrc/src/vcpkg/base/chrono.cpp | 22 ++-- toolsrc/src/vcpkg/commands.upgrade.cpp | 180 +++++++++++++++++++++++++++++++++ toolsrc/src/vcpkg/userconfig.cpp | 7 +- 4 files changed, 200 insertions(+), 189 deletions(-) delete mode 100644 toolsrc/src/commands.upgrade.cpp create mode 100644 toolsrc/src/vcpkg/commands.upgrade.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/commands.upgrade.cpp b/toolsrc/src/commands.upgrade.cpp deleted file mode 100644 index d2c868870..000000000 --- a/toolsrc/src/commands.upgrade.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include "pch.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace vcpkg::Commands::Upgrade -{ - using Install::KeepGoing; - using Install::to_keep_going; - - static const std::string OPTION_NO_DRY_RUN = "--no-dry-run"; - static const std::string OPTION_KEEP_GOING = "--keep-going"; - - static const std::array INSTALL_SWITCHES = {{ - {OPTION_NO_DRY_RUN, "Actually upgrade"}, - {OPTION_KEEP_GOING, "Continue installing packages on failure"}, - }}; - - const CommandStructure COMMAND_STRUCTURE = { - Help::create_example_string("upgrade --no-dry-run"), - 0, - SIZE_MAX, - {INSTALL_SWITCHES, {}}, - nullptr, - }; - - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) - { - const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); - - const bool no_dry_run = Util::Sets::contains(options.switches, OPTION_NO_DRY_RUN); - const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING)); - - StatusParagraphs status_db = database_load_check(paths); - - Dependencies::PathsPortFileProvider provider(paths); - Dependencies::PackageGraph graph(provider, status_db); - - // input sanitization - const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text); - }); - - for (auto&& spec : specs) - { - Input::check_triplet(spec.triplet(), paths); - } - - if (specs.empty()) - { - // If no packages specified, upgrade all outdated packages. - auto outdated_packages = Update::find_outdated_packages(provider, status_db); - - if (outdated_packages.empty()) - { - System::println("All installed packages are up-to-date with the local portfiles."); - Checks::exit_success(VCPKG_LINE_INFO); - } - - for (auto&& outdated_package : outdated_packages) - graph.upgrade(outdated_package.spec); - } - else - { - std::vector not_installed; - std::vector no_portfile; - std::vector to_upgrade; - std::vector up_to_date; - - for (auto&& spec : specs) - { - auto it = status_db.find_installed(spec); - if (it == status_db.end()) - { - not_installed.push_back(spec); - } - - auto maybe_scf = provider.get_control_file(spec.name()); - if (auto p_scf = maybe_scf.get()) - { - if (it != status_db.end()) - { - if (p_scf->core_paragraph->version != (*it)->package.version) - { - to_upgrade.push_back(spec); - } - else - { - up_to_date.push_back(spec); - } - } - } - else - { - no_portfile.push_back(spec); - } - } - - Util::sort(not_installed); - Util::sort(no_portfile); - Util::sort(up_to_date); - Util::sort(to_upgrade); - - if (!up_to_date.empty()) - { - System::println(System::Color::success, "The following packages are up-to-date:"); - System::println(Strings::join( - "", up_to_date, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); - } - - if (!not_installed.empty()) - { - System::println(System::Color::error, "The following packages are not installed:"); - System::println(Strings::join( - "", not_installed, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); - } - - if (!no_portfile.empty()) - { - System::println(System::Color::error, "The following packages do not have a valid portfile:"); - System::println(Strings::join( - "", no_portfile, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); - } - - Checks::check_exit(VCPKG_LINE_INFO, not_installed.empty() && no_portfile.empty()); - - if (to_upgrade.empty()) Checks::exit_success(VCPKG_LINE_INFO); - - for (auto&& spec : to_upgrade) - graph.upgrade(spec); - } - - auto plan = graph.serialize(); - - Checks::check_exit(VCPKG_LINE_INFO, !plan.empty()); - - const Build::BuildPackageOptions install_plan_options = { - Build::UseHeadVersion::NO, - Build::AllowDownloads::YES, - Build::CleanBuildtrees::NO, - }; - - // Set build settings for all install actions - for (auto&& action : plan) - { - if (auto p_install = action.install_action.get()) - { - p_install->build_options = install_plan_options; - } - } - - Dependencies::print_plan(plan, true); - - if (!no_dry_run) - { - System::println(System::Color::warning, - "If you are sure you want to rebuild the above packages, run this command with the " - "--no-dry-run option."); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - const Install::InstallSummary summary = Install::perform(plan, keep_going, paths, status_db); - - System::println("\nTotal elapsed time: %s\n", summary.total_elapsed_time); - - if (keep_going == KeepGoing::YES) - { - summary.print(); - } - - Checks::exit_success(VCPKG_LINE_INFO); - } -} diff --git a/toolsrc/src/vcpkg/base/chrono.cpp b/toolsrc/src/vcpkg/base/chrono.cpp index 03c1ecce9..00f8ba3f1 100644 --- a/toolsrc/src/vcpkg/base/chrono.cpp +++ b/toolsrc/src/vcpkg/base/chrono.cpp @@ -92,14 +92,20 @@ namespace vcpkg::Chrono Optional CTime::parse(CStringView str) { CTime ret; - auto assigned = sscanf_s(str.c_str(), - "%d-%d-%dT%d:%d:%d.", - &ret.m_tm.tm_year, - &ret.m_tm.tm_mon, - &ret.m_tm.tm_mday, - &ret.m_tm.tm_hour, - &ret.m_tm.tm_min, - &ret.m_tm.tm_sec); + auto assigned = +#if defined(_WIN32) + sscanf_s +#else + sscanf +#endif + (str.c_str(), + "%d-%d-%dT%d:%d:%d.", + &ret.m_tm.tm_year, + &ret.m_tm.tm_mon, + &ret.m_tm.tm_mday, + &ret.m_tm.tm_hour, + &ret.m_tm.tm_min, + &ret.m_tm.tm_sec); if (assigned != 6) return nullopt; if (ret.m_tm.tm_year < 1900) return nullopt; ret.m_tm.tm_year -= 1900; diff --git a/toolsrc/src/vcpkg/commands.upgrade.cpp b/toolsrc/src/vcpkg/commands.upgrade.cpp new file mode 100644 index 000000000..d2c868870 --- /dev/null +++ b/toolsrc/src/vcpkg/commands.upgrade.cpp @@ -0,0 +1,180 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::Upgrade +{ + using Install::KeepGoing; + using Install::to_keep_going; + + static const std::string OPTION_NO_DRY_RUN = "--no-dry-run"; + static const std::string OPTION_KEEP_GOING = "--keep-going"; + + static const std::array INSTALL_SWITCHES = {{ + {OPTION_NO_DRY_RUN, "Actually upgrade"}, + {OPTION_KEEP_GOING, "Continue installing packages on failure"}, + }}; + + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("upgrade --no-dry-run"), + 0, + SIZE_MAX, + {INSTALL_SWITCHES, {}}, + nullptr, + }; + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); + + const bool no_dry_run = Util::Sets::contains(options.switches, OPTION_NO_DRY_RUN); + const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING)); + + StatusParagraphs status_db = database_load_check(paths); + + Dependencies::PathsPortFileProvider provider(paths); + Dependencies::PackageGraph graph(provider, status_db); + + // input sanitization + const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + return Input::check_and_get_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text); + }); + + for (auto&& spec : specs) + { + Input::check_triplet(spec.triplet(), paths); + } + + if (specs.empty()) + { + // If no packages specified, upgrade all outdated packages. + auto outdated_packages = Update::find_outdated_packages(provider, status_db); + + if (outdated_packages.empty()) + { + System::println("All installed packages are up-to-date with the local portfiles."); + Checks::exit_success(VCPKG_LINE_INFO); + } + + for (auto&& outdated_package : outdated_packages) + graph.upgrade(outdated_package.spec); + } + else + { + std::vector not_installed; + std::vector no_portfile; + std::vector to_upgrade; + std::vector up_to_date; + + for (auto&& spec : specs) + { + auto it = status_db.find_installed(spec); + if (it == status_db.end()) + { + not_installed.push_back(spec); + } + + auto maybe_scf = provider.get_control_file(spec.name()); + if (auto p_scf = maybe_scf.get()) + { + if (it != status_db.end()) + { + if (p_scf->core_paragraph->version != (*it)->package.version) + { + to_upgrade.push_back(spec); + } + else + { + up_to_date.push_back(spec); + } + } + } + else + { + no_portfile.push_back(spec); + } + } + + Util::sort(not_installed); + Util::sort(no_portfile); + Util::sort(up_to_date); + Util::sort(to_upgrade); + + if (!up_to_date.empty()) + { + System::println(System::Color::success, "The following packages are up-to-date:"); + System::println(Strings::join( + "", up_to_date, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); + } + + if (!not_installed.empty()) + { + System::println(System::Color::error, "The following packages are not installed:"); + System::println(Strings::join( + "", not_installed, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); + } + + if (!no_portfile.empty()) + { + System::println(System::Color::error, "The following packages do not have a valid portfile:"); + System::println(Strings::join( + "", no_portfile, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); + } + + Checks::check_exit(VCPKG_LINE_INFO, not_installed.empty() && no_portfile.empty()); + + if (to_upgrade.empty()) Checks::exit_success(VCPKG_LINE_INFO); + + for (auto&& spec : to_upgrade) + graph.upgrade(spec); + } + + auto plan = graph.serialize(); + + Checks::check_exit(VCPKG_LINE_INFO, !plan.empty()); + + const Build::BuildPackageOptions install_plan_options = { + Build::UseHeadVersion::NO, + Build::AllowDownloads::YES, + Build::CleanBuildtrees::NO, + }; + + // Set build settings for all install actions + for (auto&& action : plan) + { + if (auto p_install = action.install_action.get()) + { + p_install->build_options = install_plan_options; + } + } + + Dependencies::print_plan(plan, true); + + if (!no_dry_run) + { + System::println(System::Color::warning, + "If you are sure you want to rebuild the above packages, run this command with the " + "--no-dry-run option."); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + const Install::InstallSummary summary = Install::perform(plan, keep_going, paths, status_db); + + System::println("\nTotal elapsed time: %s\n", summary.total_elapsed_time); + + if (keep_going == KeepGoing::YES) + { + summary.print(); + } + + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp index d13a46f41..906594691 100644 --- a/toolsrc/src/vcpkg/userconfig.cpp +++ b/toolsrc/src/vcpkg/userconfig.cpp @@ -5,6 +5,7 @@ #include #include +#if defined(_WIN32) namespace { static vcpkg::Lazy s_localappdata; @@ -24,13 +25,14 @@ namespace }); } } +#endif namespace vcpkg { UserConfig UserConfig::try_read_data(const Files::Filesystem& fs) { UserConfig ret; - +#if defined(_WIN32) try { auto maybe_pghs = Paragraphs::get_paragraphs(fs, get_localappdata() / "vcpkg" / "config"); @@ -56,12 +58,14 @@ namespace vcpkg catch (...) { } +#endif return ret; } void UserConfig::try_write_data(Files::Filesystem& fs) const { +#if defined(_WIN32) try { std::error_code ec; @@ -79,5 +83,6 @@ namespace vcpkg catch (...) { } +#endif } } -- cgit v1.2.3 From 5ac69dd02bef426d71ed1e58923345c9042c37dc Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 18 Dec 2017 23:00:11 -0800 Subject: [vcpkg] Improve error message upon graph cycle detected. --- toolsrc/src/vcpkg/dependencies.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index a48f3f1d8..76aeb0eaa 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -373,6 +373,8 @@ namespace vcpkg::Dependencies } return RemovePlanAction{spec, RemovePlanType::REMOVE, request_type}; } + + std::string to_string(const PackageSpec& spec) const override { return spec.to_string(); } }; const std::vector& installed_ports = get_installed_ports(status_db); @@ -420,6 +422,8 @@ namespace vcpkg::Dependencies Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); } + + std::string to_string(const PackageSpec& spec) const override { return spec.to_string(); } }; const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); @@ -598,14 +602,11 @@ namespace vcpkg::Dependencies std::vector PackageGraph::serialize() const { - Graphs::GraphAdjacencyProvider adjacency_remove_graph(m_graph_plan->remove_graph.adjacency_list()); auto remove_vertex_list = m_graph_plan->remove_graph.vertex_list(); - auto remove_toposort = Graphs::topological_sort(remove_vertex_list, adjacency_remove_graph); + auto remove_toposort = Graphs::topological_sort(remove_vertex_list, m_graph_plan->remove_graph); - Graphs::GraphAdjacencyProvider adjacency_install_graph( - m_graph_plan->install_graph.adjacency_list()); auto insert_vertex_list = m_graph_plan->install_graph.vertex_list(); - auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph); + auto insert_toposort = Graphs::topological_sort(insert_vertex_list, m_graph_plan->install_graph); std::vector plan; -- cgit v1.2.3 From a6ee2c145fca2006848ef9afbf580ea88bee7dd1 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 19 Dec 2017 10:22:43 -0800 Subject: [vcpkg-list] Improve list output for long triplets --- toolsrc/src/vcpkg/binaryparagraph.cpp | 5 +++-- toolsrc/src/vcpkg/commands.list.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp index c7136b713..7c9e905e8 100644 --- a/toolsrc/src/vcpkg/binaryparagraph.cpp +++ b/toolsrc/src/vcpkg/binaryparagraph.cpp @@ -92,8 +92,9 @@ namespace vcpkg std::string BinaryParagraph::displayname() const { - const auto f = this->feature.empty() ? "core" : this->feature; - return Strings::format("%s[%s]:%s", this->spec.name(), f, this->spec.triplet()); + if (this->feature.empty() || this->feature == "core") + return Strings::format("%s:%s", this->spec.name(), this->spec.triplet()); + return Strings::format("%s[%s]:%s", this->spec.name(), this->feature, this->spec.triplet()); } std::string BinaryParagraph::dir() const { return this->spec.dir(); } diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp index 1f2387843..960c57225 100644 --- a/toolsrc/src/vcpkg/commands.list.cpp +++ b/toolsrc/src/vcpkg/commands.list.cpp @@ -13,14 +13,14 @@ namespace vcpkg::Commands::List { if (full_desc) { - System::println("%-30s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description); + System::println("%-50s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description); } else { - System::println("%-30s %-16s %s", - vcpkg::shorten_text(pgh.package.displayname(), 30), + System::println("%-50s %-16s %s", + vcpkg::shorten_text(pgh.package.displayname(), 50), vcpkg::shorten_text(pgh.package.version, 16), - vcpkg::shorten_text(pgh.package.description, 71)); + vcpkg::shorten_text(pgh.package.description, 51)); } } -- cgit v1.2.3 From a24ccdfc01aba83b833af528b8f1a6ec6db020a4 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 19 Oct 2017 17:19:11 -0700 Subject: [vcpkg-build-cmake] Build at IDLE priority. Try to detect out-of-memory issues in the linker, and restart the build once. --- toolsrc/src/vcpkg/base/system.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 625ee6ce0..84721bf6e 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -220,7 +220,7 @@ namespace vcpkg::System nullptr, nullptr, FALSE, - BELOW_NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, + IDLE_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, env_cstr.data(), nullptr, &startup_info, -- cgit v1.2.3 From 2d0a76370ead152896411d17aa19934235b93d1c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 21 Dec 2017 16:28:13 -0800 Subject: clang-tidy fixes --- toolsrc/src/vcpkg.cpp | 14 +++++----- toolsrc/src/vcpkg/base/chrono.cpp | 2 +- toolsrc/src/vcpkg/base/cofffilereader.cpp | 2 +- toolsrc/src/vcpkg/base/files.cpp | 4 +-- toolsrc/src/vcpkg/build.cpp | 11 ++++---- toolsrc/src/vcpkg/commands.cache.cpp | 2 +- toolsrc/src/vcpkg/commands.create.cpp | 2 +- toolsrc/src/vcpkg/commands.exportifw.cpp | 6 ++--- toolsrc/src/vcpkg/commands.integrate.cpp | 2 +- toolsrc/src/vcpkg/commands.list.cpp | 2 +- toolsrc/src/vcpkg/export.cpp | 4 +-- toolsrc/src/vcpkg/install.cpp | 2 +- toolsrc/src/vcpkg/metrics.cpp | 43 ++++++++++++++----------------- toolsrc/src/vcpkg/remove.cpp | 4 +-- toolsrc/src/vcpkg/sourceparagraph.cpp | 6 ++--- toolsrc/src/vcpkg/statusparagraphs.cpp | 2 +- toolsrc/src/vcpkg/update.cpp | 3 ++- toolsrc/src/vcpkg/userconfig.cpp | 2 +- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 +-- toolsrc/src/vcpkg/versiont.cpp | 2 +- 20 files changed, 58 insertions(+), 61 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 094ea1dc5..08dd3fcf6 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -4,7 +4,7 @@ #pragma warning(push) #pragma warning(disable : 4768) -#include +#include #pragma warning(pop) #else #include @@ -21,10 +21,8 @@ #include #include #include -#include #include -#include #include #include @@ -49,7 +47,7 @@ static void inner(const VcpkgCmdArguments& args) Checks::exit_fail(VCPKG_LINE_INFO); } - static const auto find_command = [&](auto&& commands) { + static const auto FIND_COMMAND = [&](auto&& commands) { auto it = Util::find_if(commands, [&](auto&& commandc) { return Strings::case_insensitive_ascii_equals(commandc.name, args.command); }); @@ -62,7 +60,7 @@ static void inner(const VcpkgCmdArguments& args) return static_cast(nullptr); }; - if (const auto command_function = find_command(Commands::get_available_commands_type_c())) + if (const auto command_function = FIND_COMMAND(Commands::get_available_commands_type_c())) { return command_function->function(args); } @@ -136,7 +134,7 @@ static void inner(const VcpkgCmdArguments& args) } } - if (const auto command_function = find_command(Commands::get_available_commands_type_b())) + if (const auto command_function = FIND_COMMAND(Commands::get_available_commands_type_b())) { return command_function->function(args, paths); } @@ -161,7 +159,7 @@ static void inner(const VcpkgCmdArguments& args) Input::check_triplet(default_triplet, paths); - if (const auto command_function = find_command(Commands::get_available_commands_type_a())) + if (const auto command_function = FIND_COMMAND(Commands::get_available_commands_type_a())) { return command_function->function(args, paths, default_triplet); } @@ -214,7 +212,7 @@ static void load_config() static std::string trim_path_from_command_line(const std::string& full_command_line) { Checks::check_exit( - VCPKG_LINE_INFO, full_command_line.size() > 0, "Internal failure - cannot have empty command line"); + VCPKG_LINE_INFO, !full_command_line.empty(), "Internal failure - cannot have empty command line"); if (full_command_line[0] == '"') { diff --git a/toolsrc/src/vcpkg/base/chrono.cpp b/toolsrc/src/vcpkg/base/chrono.cpp index 00f8ba3f1..d83106c8b 100644 --- a/toolsrc/src/vcpkg/base/chrono.cpp +++ b/toolsrc/src/vcpkg/base/chrono.cpp @@ -15,7 +15,7 @@ namespace vcpkg::Chrono using std::chrono::nanoseconds; using std::chrono::seconds; - const double nanos_as_double = static_cast(nanos.count()); + const auto nanos_as_double = static_cast(nanos.count()); if (duration_cast(nanos) > hours()) { diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp index 1927e0b5e..27426eb0a 100644 --- a/toolsrc/src/vcpkg/base/cofffilereader.cpp +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -223,7 +223,7 @@ namespace vcpkg::CoffFileReader static const char* FILE_START = "!\n"; static const size_t FILE_START_SIZE = 8; - fs.seekg(fs.beg); + fs.seekg(fstream::beg); char file_start[FILE_START_SIZE]; fs.read(file_start, FILE_START_SIZE); diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 8c9e137ed..7e4cfbf6a 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -18,9 +18,9 @@ namespace vcpkg::Files return std::make_error_code(std::errc::no_such_file_or_directory); } - file_stream.seekg(0, file_stream.end); + file_stream.seekg(0, std::fstream::end); auto length = file_stream.tellg(); - file_stream.seekg(0, file_stream.beg); + file_stream.seekg(0, std::fstream::beg); if (length > SIZE_MAX) { diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index f43d8788e..16f7a400f 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -60,7 +60,8 @@ namespace vcpkg::Build::Command spec.name()); const StatusParagraphs status_db = database_load_check(paths); - const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; + const Build::BuildPackageOptions build_package_options{ + Build::UseHeadVersion::NO, Build::AllowDownloads::YES, Build::CleanBuildtrees::NO}; const std::unordered_set features_as_set(full_spec.features.begin(), full_spec.features.end()); @@ -192,7 +193,7 @@ namespace vcpkg::Build for (auto&& host : host_architectures) { - auto it = Util::find_if(toolset.supported_architectures, [&](const ToolsetArchOption& opt) { + const auto it = Util::find_if(toolset.supported_architectures, [&](const ToolsetArchOption& opt) { return host == opt.host_arch && target_arch == opt.target_arch; }); if (it != toolset.supported_architectures.end()) return it->name; @@ -294,7 +295,7 @@ namespace vcpkg::Build { features.append(feature + ";"); } - if (features.size() > 0) + if (!features.empty()) { features.pop_back(); } @@ -364,7 +365,7 @@ namespace vcpkg::Build if (config.build_package_options.clean_buildtrees == CleanBuildtrees::YES) { auto& fs = paths.get_filesystem(); - auto buildtrees_dir = paths.buildtrees / spec.name(); + const auto buildtrees_dir = paths.buildtrees / spec.name(); auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir); for (auto&& file : buildtree_files) { @@ -500,7 +501,7 @@ namespace vcpkg::Build const std::vector lines = Strings::split(ec_data.output, "\n"); - PreBuildInfo pre_build_info; + PreBuildInfo pre_build_info{}; const auto e = lines.cend(); auto cur = std::find(lines.cbegin(), e, FLAG_GUID); diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp index 6fd123b7c..85bf5fb4d 100644 --- a/toolsrc/src/vcpkg/commands.cache.cpp +++ b/toolsrc/src/vcpkg/commands.cache.cpp @@ -47,7 +47,7 @@ namespace vcpkg::Commands::Cache Checks::exit_success(VCPKG_LINE_INFO); } - if (args.command_arguments.size() == 0) + if (args.command_arguments.empty()) { for (const BinaryParagraph& binary_paragraph : binary_paragraphs) { diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp index 44f5f7928..25c34cf09 100644 --- a/toolsrc/src/vcpkg/commands.create.cpp +++ b/toolsrc/src/vcpkg/commands.create.cpp @@ -34,7 +34,7 @@ namespace vcpkg::Commands::Create R"(Filename cannot contain invalid chars %s, but was %s)", Files::FILESYSTEM_INVALID_CHARACTERS, zip_file_name); - cmake_args.push_back({"FILENAME", zip_file_name}); + cmake_args.emplace_back("FILENAME", zip_file_name); } const std::string cmd_launch_cmake = make_cmake_cmd(cmake_exe, paths.ports_cmake, cmake_args); diff --git a/toolsrc/src/vcpkg/commands.exportifw.cpp b/toolsrc/src/vcpkg/commands.exportifw.cpp index 682267acb..96c0e2215 100644 --- a/toolsrc/src/vcpkg/commands.exportifw.cpp +++ b/toolsrc/src/vcpkg/commands.exportifw.cpp @@ -139,14 +139,14 @@ namespace vcpkg::Export::IFW )###", create_release_date())); - for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) + for (const auto& unique_package : unique_packages) { - const ExportPlanAction& action = *(package->second); + const ExportPlanAction& action = *(unique_package.second); const BinaryParagraph& binary_paragraph = action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; package_xml_file_path = - raw_exported_dir_path / Strings::format("packages.%s", package->first) / "meta" / "package.xml"; + raw_exported_dir_path / Strings::format("packages.%s", unique_package.first) / "meta" / "package.xml"; package_xml_dir_path = package_xml_file_path.parent_path(); fs.create_directories(package_xml_dir_path, ec); Checks::check_exit(VCPKG_LINE_INFO, diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 460e99b88..0f647a40f 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -191,7 +191,7 @@ namespace vcpkg::Commands::Integrate const auto found = std::regex_search(*contents_data, match, RE); if (found) { - const int ver = atoi(match[1].str().c_str()); + const auto ver = strtol(match[1].str().c_str(), nullptr, 10); if (ver >= 1) should_install_system = false; } } diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp index 960c57225..66939a68a 100644 --- a/toolsrc/src/vcpkg/commands.list.cpp +++ b/toolsrc/src/vcpkg/commands.list.cpp @@ -57,7 +57,7 @@ namespace vcpkg::Commands::List return lhs->package.displayname() < rhs->package.displayname(); }); - if (args.command_arguments.size() == 0) + if (args.command_arguments.empty()) { for (const StatusParagraph* status_paragraph : installed_packages) { diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index e3221a12f..11e810339 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -69,8 +69,8 @@ namespace vcpkg::Export { static constexpr std::array ORDER = {ExportPlanType::ALREADY_BUILT, ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT}; - static constexpr Build::BuildPackageOptions build_options = {Build::UseHeadVersion::NO, - Build::AllowDownloads::YES}; + static constexpr Build::BuildPackageOptions build_options = { + Build::UseHeadVersion::NO, Build::AllowDownloads::YES, Build::CleanBuildtrees::NO}; for (const ExportPlanType plan_type : ORDER) { diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index dcc130be3..88c9d8882 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -159,7 +159,7 @@ namespace vcpkg::Install auto package_files = Util::fmap(package_file_paths, [package_remove_char_count](const fs::path& path) { std::string as_string = path.generic_string(); as_string.erase(0, package_remove_char_count); - return std::move(as_string); + return as_string; }); return SortedVector(std::move(package_files)); diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index cdb21d260..818a9066c 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -152,7 +152,7 @@ namespace vcpkg::Metrics void track_property(const std::string& name, const std::string& value) { - if (properties.size() != 0) properties.push_back(','); + if (!properties.empty()) properties.push_back(','); properties.append(to_json_string(name)); properties.push_back(':'); properties.append(to_json_string(value)); @@ -160,7 +160,7 @@ namespace vcpkg::Metrics void track_metric(const std::string& name, double value) { - if (measurements.size() != 0) measurements.push_back(','); + if (!measurements.empty()) measurements.push_back(','); measurements.append(to_json_string(name)); measurements.push_back(':'); measurements.append(std::to_string(value)); @@ -302,7 +302,7 @@ namespace vcpkg::Metrics { if (MAXDWORD <= payload.size()) abort(); std::wstring hdrs = L"Content-Type: application/json\r\n"; - std::string& p = const_cast(payload); + auto& p = const_cast(payload); results = WinHttpSendRequest(request, hdrs.c_str(), static_cast(hdrs.size()), @@ -383,30 +383,27 @@ namespace vcpkg::Metrics auto& fs = Files::get_real_filesystem(); - if (true) - { - const fs::path exe_path = [&fs]() -> fs::path { - auto vcpkgdir = System::get_exe_path_of_current_process().parent_path(); - auto path = vcpkgdir / "vcpkgmetricsuploader.exe"; - if (fs.exists(path)) return path; - - path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; - if (fs.exists(path)) return path; - - return ""; - }(); - - std::error_code ec; - fs.create_directories(temp_folder_path, ec); - if (ec) return; - fs.copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec); - if (ec) return; - } + const fs::path exe_path = [&fs]() -> fs::path { + auto vcpkgdir = System::get_exe_path_of_current_process().parent_path(); + auto path = vcpkgdir / "vcpkgmetricsuploader.exe"; + if (fs.exists(path)) return path; + + path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; + if (fs.exists(path)) return path; + + return ""; + }(); + + std::error_code ec; + fs.create_directories(temp_folder_path, ec); + if (ec) return; + fs.copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec); + if (ec) return; const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); fs.write_contents(vcpkg_metrics_txt_path, payload); - const std::string cmd_line = Strings::format("start \"vcpkgmetricsuploader.exe\" \"%s\" \"%s\"", + const std::string cmd_line = Strings::format(R"(start "vcpkgmetricsuploader.exe" "%s" "%s")", temp_folder_path_exe.u8string(), vcpkg_metrics_txt_path.u8string()); System::cmd_execute_clean(cmd_line); diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 4079d60c1..ed2c02b9f 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -202,7 +202,7 @@ namespace vcpkg::Remove std::vector specs; if (Util::Sets::contains(options.switches, OPTION_OUTDATED)) { - if (args.command_arguments.size() != 0) + if (!args.command_arguments.empty()) { System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'"); Checks::exit_fail(VCPKG_LINE_INFO); @@ -221,7 +221,7 @@ namespace vcpkg::Remove } else { - if (args.command_arguments.size() < 1) + if (args.command_arguments.empty()) { System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'"); Checks::exit_fail(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp index 2a9480538..4da0cfcfc 100644 --- a/toolsrc/src/vcpkg/sourceparagraph.cpp +++ b/toolsrc/src/vcpkg/sourceparagraph.cpp @@ -158,7 +158,7 @@ namespace vcpkg return std::move(control_file); } - Dependency Dependency::parse_dependency(std::string name, std::string qualifier) + Dependency Dependency::parse_dependency(std::string&& name, std::string&& qualifier) { Dependency dep; dep.qualifier = qualifier; @@ -182,7 +182,7 @@ namespace vcpkg { return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency { auto pos = depend_string.find(' '); - if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, ""); + if (pos == std::string::npos) return Dependency::parse_dependency(std::string{depend_string}, ""); // expect of the form "\w+ \[\w+\]" Dependency dep; @@ -190,7 +190,7 @@ namespace vcpkg if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')') { // Error, but for now just slurp the entire string. - return Dependency::parse_dependency(depend_string, ""); + return Dependency::parse_dependency(std::string{depend_string}, ""); } dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3); return dep; diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp index d4afc0427..d516b6284 100644 --- a/toolsrc/src/vcpkg/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -47,7 +47,7 @@ namespace vcpkg StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name, const Triplet& triplet) const { - const const_iterator it = find(name, triplet); + const auto it = find(name, triplet); if (it != end() && (*it)->want == Want::INSTALL && (*it)->state == InstallState::INSTALLED) { return it; diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp index d6c5614ed..9f89da13c 100644 --- a/toolsrc/src/vcpkg/update.cpp +++ b/toolsrc/src/vcpkg/update.cpp @@ -35,7 +35,8 @@ namespace vcpkg::Update auto&& installed_version = pgh->package.version; if (installed_version != port_version) { - output.push_back({pgh->package.spec, VersionDiff(installed_version, port_version)}); + output.push_back( + {pgh->package.spec, VersionDiff(std::string{installed_version}, std::string{port_version})}); } } else diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp index 906594691..45ed01ec6 100644 --- a/toolsrc/src/vcpkg/userconfig.cpp +++ b/toolsrc/src/vcpkg/userconfig.cpp @@ -41,7 +41,7 @@ namespace vcpkg const auto& pghs = *p_pghs; std::unordered_map keys; - if (pghs.size() > 0) keys = pghs[0]; + if (!pghs.empty()) keys = pghs[0]; for (size_t x = 1; x < pghs.size(); ++x) { diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index e64a681e2..cbf1e97e1 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -50,14 +50,14 @@ namespace vcpkg const std::string& version_check_arguments, const std::array& expected_version) { - auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { + const auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { const std::string cmd = Strings::format(R"("%s" %s)", p.u8string(), version_check_arguments); return exists_and_has_equal_or_greater_version(cmd, expected_version); }); if (it != candidate_paths.cend()) { - return std::move(*it); + return *it; } return nullopt; diff --git a/toolsrc/src/vcpkg/versiont.cpp b/toolsrc/src/vcpkg/versiont.cpp index 91f7e23ef..cff49d9e8 100644 --- a/toolsrc/src/vcpkg/versiont.cpp +++ b/toolsrc/src/vcpkg/versiont.cpp @@ -6,7 +6,7 @@ namespace vcpkg { VersionT::VersionT() : value("0.0.0") {} - VersionT::VersionT(const std::string& value) : value(value) {} + VersionT::VersionT(std::string&& value) : value(std::move(value)) {} const std::string& VersionT::to_string() const { return value; } bool operator==(const VersionT& left, const VersionT& right) { return left.to_string() == right.to_string(); } bool operator!=(const VersionT& left, const VersionT& right) { return left.to_string() != right.to_string(); } -- cgit v1.2.3 From 7cc7c28e209b6fe7b037c59c9fa83a763e337bb8 Mon Sep 17 00:00:00 2001 From: Stanislav Ershov Date: Sat, 23 Dec 2017 17:26:05 +0300 Subject: [vcpkg-hash] Replace certutil.exe with cmake built-in hash commands --- toolsrc/src/vcpkg/commands.cpp | 7 ++++--- toolsrc/src/vcpkg/commands.hash.cpp | 16 +++++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index ccf6fa729..d9c0e54cd 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -41,7 +41,9 @@ namespace vcpkg::Commands {"import", &Import::perform_and_exit}, {"cache", &Cache::perform_and_exit}, {"portsdiff", &PortsDiff::perform_and_exit}, - {"autocomplete", &Autocomplete::perform_and_exit}}; + {"autocomplete", &Autocomplete::perform_and_exit}, + {"hash", &Hash::perform_and_exit}, + }; return t; } @@ -49,8 +51,7 @@ namespace vcpkg::Commands { static std::vector> t = { {"version", &Version::perform_and_exit}, - {"contact", &Contact::perform_and_exit}, - {"hash", &Hash::perform_and_exit}, + {"contact", &Contact::perform_and_exit} }; return t; } diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index a5940ea1e..1e3e5b23d 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -7,15 +7,17 @@ namespace vcpkg::Commands::Hash { - static void do_file_hash(fs::path const& path, std::string const& hash_type) + static void do_file_hash(fs::path const &cmake_exe_path, fs::path const& path, std::string const& hash_type) { - const auto cmd_line = Strings::format(R"(CertUtil.exe -hashfile "%s" %s)", path.u8string().c_str(), hash_type); + const std::string cmd_line = Strings::format( + R"("%s" -E %ssum %s)", cmake_exe_path.u8string(), Strings::ascii_to_lowercase(hash_type), path.u8string()); + const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line); std::string const& output = ec_data.output; - const auto start = output.find_first_of("\r\n"); + const auto start = output.find_first_of(" "); Checks::check_exit( VCPKG_LINE_INFO, start != std::string::npos, "Unexpected output format from command: %s", cmd_line); @@ -23,7 +25,7 @@ namespace vcpkg::Commands::Hash Checks::check_exit( VCPKG_LINE_INFO, end != std::string::npos, "Unexpected output format from command: %s", cmd_line); - auto hash = output.substr(start, end - start); + auto hash = output.substr(0, start); Util::erase_remove_if(hash, isspace); System::println(hash); } @@ -37,17 +39,17 @@ namespace vcpkg::Commands::Hash nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { args.parse_arguments(COMMAND_STRUCTURE); if (args.command_arguments.size() == 1) { - do_file_hash(args.command_arguments[0], "SHA512"); + do_file_hash(paths.get_cmake_exe(), args.command_arguments[0], "SHA512"); } if (args.command_arguments.size() == 2) { - do_file_hash(args.command_arguments[0], args.command_arguments[1]); + do_file_hash(paths.get_cmake_exe(), args.command_arguments[0], args.command_arguments[1]); } Checks::exit_success(VCPKG_LINE_INFO); -- cgit v1.2.3 From 332414111dcc1eee316aa93c1c5e74699a521709 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 23 Dec 2017 07:29:12 -0800 Subject: Revert "clang-tidy fixes" This reverts commit 2d0a76370ead152896411d17aa19934235b93d1c. --- toolsrc/src/vcpkg.cpp | 14 +++++----- toolsrc/src/vcpkg/base/chrono.cpp | 2 +- toolsrc/src/vcpkg/base/cofffilereader.cpp | 2 +- toolsrc/src/vcpkg/base/files.cpp | 4 +-- toolsrc/src/vcpkg/build.cpp | 11 ++++---- toolsrc/src/vcpkg/commands.cache.cpp | 2 +- toolsrc/src/vcpkg/commands.create.cpp | 2 +- toolsrc/src/vcpkg/commands.exportifw.cpp | 6 ++--- toolsrc/src/vcpkg/commands.integrate.cpp | 2 +- toolsrc/src/vcpkg/commands.list.cpp | 2 +- toolsrc/src/vcpkg/export.cpp | 4 +-- toolsrc/src/vcpkg/install.cpp | 2 +- toolsrc/src/vcpkg/metrics.cpp | 43 +++++++++++++++++-------------- toolsrc/src/vcpkg/remove.cpp | 4 +-- toolsrc/src/vcpkg/sourceparagraph.cpp | 6 ++--- toolsrc/src/vcpkg/statusparagraphs.cpp | 2 +- toolsrc/src/vcpkg/update.cpp | 3 +-- toolsrc/src/vcpkg/userconfig.cpp | 2 +- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 +-- toolsrc/src/vcpkg/versiont.cpp | 2 +- 20 files changed, 61 insertions(+), 58 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 08dd3fcf6..094ea1dc5 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -4,7 +4,7 @@ #pragma warning(push) #pragma warning(disable : 4768) -#include +#include #pragma warning(pop) #else #include @@ -21,8 +21,10 @@ #include #include #include +#include #include +#include #include #include @@ -47,7 +49,7 @@ static void inner(const VcpkgCmdArguments& args) Checks::exit_fail(VCPKG_LINE_INFO); } - static const auto FIND_COMMAND = [&](auto&& commands) { + static const auto find_command = [&](auto&& commands) { auto it = Util::find_if(commands, [&](auto&& commandc) { return Strings::case_insensitive_ascii_equals(commandc.name, args.command); }); @@ -60,7 +62,7 @@ static void inner(const VcpkgCmdArguments& args) return static_cast(nullptr); }; - if (const auto command_function = FIND_COMMAND(Commands::get_available_commands_type_c())) + if (const auto command_function = find_command(Commands::get_available_commands_type_c())) { return command_function->function(args); } @@ -134,7 +136,7 @@ static void inner(const VcpkgCmdArguments& args) } } - if (const auto command_function = FIND_COMMAND(Commands::get_available_commands_type_b())) + if (const auto command_function = find_command(Commands::get_available_commands_type_b())) { return command_function->function(args, paths); } @@ -159,7 +161,7 @@ static void inner(const VcpkgCmdArguments& args) Input::check_triplet(default_triplet, paths); - if (const auto command_function = FIND_COMMAND(Commands::get_available_commands_type_a())) + if (const auto command_function = find_command(Commands::get_available_commands_type_a())) { return command_function->function(args, paths, default_triplet); } @@ -212,7 +214,7 @@ static void load_config() static std::string trim_path_from_command_line(const std::string& full_command_line) { Checks::check_exit( - VCPKG_LINE_INFO, !full_command_line.empty(), "Internal failure - cannot have empty command line"); + VCPKG_LINE_INFO, full_command_line.size() > 0, "Internal failure - cannot have empty command line"); if (full_command_line[0] == '"') { diff --git a/toolsrc/src/vcpkg/base/chrono.cpp b/toolsrc/src/vcpkg/base/chrono.cpp index d83106c8b..00f8ba3f1 100644 --- a/toolsrc/src/vcpkg/base/chrono.cpp +++ b/toolsrc/src/vcpkg/base/chrono.cpp @@ -15,7 +15,7 @@ namespace vcpkg::Chrono using std::chrono::nanoseconds; using std::chrono::seconds; - const auto nanos_as_double = static_cast(nanos.count()); + const double nanos_as_double = static_cast(nanos.count()); if (duration_cast(nanos) > hours()) { diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp index 27426eb0a..1927e0b5e 100644 --- a/toolsrc/src/vcpkg/base/cofffilereader.cpp +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -223,7 +223,7 @@ namespace vcpkg::CoffFileReader static const char* FILE_START = "!\n"; static const size_t FILE_START_SIZE = 8; - fs.seekg(fstream::beg); + fs.seekg(fs.beg); char file_start[FILE_START_SIZE]; fs.read(file_start, FILE_START_SIZE); diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 7e4cfbf6a..8c9e137ed 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -18,9 +18,9 @@ namespace vcpkg::Files return std::make_error_code(std::errc::no_such_file_or_directory); } - file_stream.seekg(0, std::fstream::end); + file_stream.seekg(0, file_stream.end); auto length = file_stream.tellg(); - file_stream.seekg(0, std::fstream::beg); + file_stream.seekg(0, file_stream.beg); if (length > SIZE_MAX) { diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 16f7a400f..f43d8788e 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -60,8 +60,7 @@ namespace vcpkg::Build::Command spec.name()); const StatusParagraphs status_db = database_load_check(paths); - const Build::BuildPackageOptions build_package_options{ - Build::UseHeadVersion::NO, Build::AllowDownloads::YES, Build::CleanBuildtrees::NO}; + const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; const std::unordered_set features_as_set(full_spec.features.begin(), full_spec.features.end()); @@ -193,7 +192,7 @@ namespace vcpkg::Build for (auto&& host : host_architectures) { - const auto it = Util::find_if(toolset.supported_architectures, [&](const ToolsetArchOption& opt) { + auto it = Util::find_if(toolset.supported_architectures, [&](const ToolsetArchOption& opt) { return host == opt.host_arch && target_arch == opt.target_arch; }); if (it != toolset.supported_architectures.end()) return it->name; @@ -295,7 +294,7 @@ namespace vcpkg::Build { features.append(feature + ";"); } - if (!features.empty()) + if (features.size() > 0) { features.pop_back(); } @@ -365,7 +364,7 @@ namespace vcpkg::Build if (config.build_package_options.clean_buildtrees == CleanBuildtrees::YES) { auto& fs = paths.get_filesystem(); - const auto buildtrees_dir = paths.buildtrees / spec.name(); + auto buildtrees_dir = paths.buildtrees / spec.name(); auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir); for (auto&& file : buildtree_files) { @@ -501,7 +500,7 @@ namespace vcpkg::Build const std::vector lines = Strings::split(ec_data.output, "\n"); - PreBuildInfo pre_build_info{}; + PreBuildInfo pre_build_info; const auto e = lines.cend(); auto cur = std::find(lines.cbegin(), e, FLAG_GUID); diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp index 85bf5fb4d..6fd123b7c 100644 --- a/toolsrc/src/vcpkg/commands.cache.cpp +++ b/toolsrc/src/vcpkg/commands.cache.cpp @@ -47,7 +47,7 @@ namespace vcpkg::Commands::Cache Checks::exit_success(VCPKG_LINE_INFO); } - if (args.command_arguments.empty()) + if (args.command_arguments.size() == 0) { for (const BinaryParagraph& binary_paragraph : binary_paragraphs) { diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp index 25c34cf09..44f5f7928 100644 --- a/toolsrc/src/vcpkg/commands.create.cpp +++ b/toolsrc/src/vcpkg/commands.create.cpp @@ -34,7 +34,7 @@ namespace vcpkg::Commands::Create R"(Filename cannot contain invalid chars %s, but was %s)", Files::FILESYSTEM_INVALID_CHARACTERS, zip_file_name); - cmake_args.emplace_back("FILENAME", zip_file_name); + cmake_args.push_back({"FILENAME", zip_file_name}); } const std::string cmd_launch_cmake = make_cmake_cmd(cmake_exe, paths.ports_cmake, cmake_args); diff --git a/toolsrc/src/vcpkg/commands.exportifw.cpp b/toolsrc/src/vcpkg/commands.exportifw.cpp index 96c0e2215..682267acb 100644 --- a/toolsrc/src/vcpkg/commands.exportifw.cpp +++ b/toolsrc/src/vcpkg/commands.exportifw.cpp @@ -139,14 +139,14 @@ namespace vcpkg::Export::IFW )###", create_release_date())); - for (const auto& unique_package : unique_packages) + for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) { - const ExportPlanAction& action = *(unique_package.second); + const ExportPlanAction& action = *(package->second); const BinaryParagraph& binary_paragraph = action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; package_xml_file_path = - raw_exported_dir_path / Strings::format("packages.%s", unique_package.first) / "meta" / "package.xml"; + raw_exported_dir_path / Strings::format("packages.%s", package->first) / "meta" / "package.xml"; package_xml_dir_path = package_xml_file_path.parent_path(); fs.create_directories(package_xml_dir_path, ec); Checks::check_exit(VCPKG_LINE_INFO, diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 0f647a40f..460e99b88 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -191,7 +191,7 @@ namespace vcpkg::Commands::Integrate const auto found = std::regex_search(*contents_data, match, RE); if (found) { - const auto ver = strtol(match[1].str().c_str(), nullptr, 10); + const int ver = atoi(match[1].str().c_str()); if (ver >= 1) should_install_system = false; } } diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp index 66939a68a..960c57225 100644 --- a/toolsrc/src/vcpkg/commands.list.cpp +++ b/toolsrc/src/vcpkg/commands.list.cpp @@ -57,7 +57,7 @@ namespace vcpkg::Commands::List return lhs->package.displayname() < rhs->package.displayname(); }); - if (args.command_arguments.empty()) + if (args.command_arguments.size() == 0) { for (const StatusParagraph* status_paragraph : installed_packages) { diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 11e810339..e3221a12f 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -69,8 +69,8 @@ namespace vcpkg::Export { static constexpr std::array ORDER = {ExportPlanType::ALREADY_BUILT, ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT}; - static constexpr Build::BuildPackageOptions build_options = { - Build::UseHeadVersion::NO, Build::AllowDownloads::YES, Build::CleanBuildtrees::NO}; + static constexpr Build::BuildPackageOptions build_options = {Build::UseHeadVersion::NO, + Build::AllowDownloads::YES}; for (const ExportPlanType plan_type : ORDER) { diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 88c9d8882..dcc130be3 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -159,7 +159,7 @@ namespace vcpkg::Install auto package_files = Util::fmap(package_file_paths, [package_remove_char_count](const fs::path& path) { std::string as_string = path.generic_string(); as_string.erase(0, package_remove_char_count); - return as_string; + return std::move(as_string); }); return SortedVector(std::move(package_files)); diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 818a9066c..cdb21d260 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -152,7 +152,7 @@ namespace vcpkg::Metrics void track_property(const std::string& name, const std::string& value) { - if (!properties.empty()) properties.push_back(','); + if (properties.size() != 0) properties.push_back(','); properties.append(to_json_string(name)); properties.push_back(':'); properties.append(to_json_string(value)); @@ -160,7 +160,7 @@ namespace vcpkg::Metrics void track_metric(const std::string& name, double value) { - if (!measurements.empty()) measurements.push_back(','); + if (measurements.size() != 0) measurements.push_back(','); measurements.append(to_json_string(name)); measurements.push_back(':'); measurements.append(std::to_string(value)); @@ -302,7 +302,7 @@ namespace vcpkg::Metrics { if (MAXDWORD <= payload.size()) abort(); std::wstring hdrs = L"Content-Type: application/json\r\n"; - auto& p = const_cast(payload); + std::string& p = const_cast(payload); results = WinHttpSendRequest(request, hdrs.c_str(), static_cast(hdrs.size()), @@ -383,27 +383,30 @@ namespace vcpkg::Metrics auto& fs = Files::get_real_filesystem(); - const fs::path exe_path = [&fs]() -> fs::path { - auto vcpkgdir = System::get_exe_path_of_current_process().parent_path(); - auto path = vcpkgdir / "vcpkgmetricsuploader.exe"; - if (fs.exists(path)) return path; - - path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; - if (fs.exists(path)) return path; - - return ""; - }(); - - std::error_code ec; - fs.create_directories(temp_folder_path, ec); - if (ec) return; - fs.copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec); - if (ec) return; + if (true) + { + const fs::path exe_path = [&fs]() -> fs::path { + auto vcpkgdir = System::get_exe_path_of_current_process().parent_path(); + auto path = vcpkgdir / "vcpkgmetricsuploader.exe"; + if (fs.exists(path)) return path; + + path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; + if (fs.exists(path)) return path; + + return ""; + }(); + + std::error_code ec; + fs.create_directories(temp_folder_path, ec); + if (ec) return; + fs.copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec); + if (ec) return; + } const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); fs.write_contents(vcpkg_metrics_txt_path, payload); - const std::string cmd_line = Strings::format(R"(start "vcpkgmetricsuploader.exe" "%s" "%s")", + const std::string cmd_line = Strings::format("start \"vcpkgmetricsuploader.exe\" \"%s\" \"%s\"", temp_folder_path_exe.u8string(), vcpkg_metrics_txt_path.u8string()); System::cmd_execute_clean(cmd_line); diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index ed2c02b9f..4079d60c1 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -202,7 +202,7 @@ namespace vcpkg::Remove std::vector specs; if (Util::Sets::contains(options.switches, OPTION_OUTDATED)) { - if (!args.command_arguments.empty()) + if (args.command_arguments.size() != 0) { System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'"); Checks::exit_fail(VCPKG_LINE_INFO); @@ -221,7 +221,7 @@ namespace vcpkg::Remove } else { - if (args.command_arguments.empty()) + if (args.command_arguments.size() < 1) { System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'"); Checks::exit_fail(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp index 4da0cfcfc..2a9480538 100644 --- a/toolsrc/src/vcpkg/sourceparagraph.cpp +++ b/toolsrc/src/vcpkg/sourceparagraph.cpp @@ -158,7 +158,7 @@ namespace vcpkg return std::move(control_file); } - Dependency Dependency::parse_dependency(std::string&& name, std::string&& qualifier) + Dependency Dependency::parse_dependency(std::string name, std::string qualifier) { Dependency dep; dep.qualifier = qualifier; @@ -182,7 +182,7 @@ namespace vcpkg { return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency { auto pos = depend_string.find(' '); - if (pos == std::string::npos) return Dependency::parse_dependency(std::string{depend_string}, ""); + if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, ""); // expect of the form "\w+ \[\w+\]" Dependency dep; @@ -190,7 +190,7 @@ namespace vcpkg if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')') { // Error, but for now just slurp the entire string. - return Dependency::parse_dependency(std::string{depend_string}, ""); + return Dependency::parse_dependency(depend_string, ""); } dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3); return dep; diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp index d516b6284..d4afc0427 100644 --- a/toolsrc/src/vcpkg/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -47,7 +47,7 @@ namespace vcpkg StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name, const Triplet& triplet) const { - const auto it = find(name, triplet); + const const_iterator it = find(name, triplet); if (it != end() && (*it)->want == Want::INSTALL && (*it)->state == InstallState::INSTALLED) { return it; diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp index 9f89da13c..d6c5614ed 100644 --- a/toolsrc/src/vcpkg/update.cpp +++ b/toolsrc/src/vcpkg/update.cpp @@ -35,8 +35,7 @@ namespace vcpkg::Update auto&& installed_version = pgh->package.version; if (installed_version != port_version) { - output.push_back( - {pgh->package.spec, VersionDiff(std::string{installed_version}, std::string{port_version})}); + output.push_back({pgh->package.spec, VersionDiff(installed_version, port_version)}); } } else diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp index 45ed01ec6..906594691 100644 --- a/toolsrc/src/vcpkg/userconfig.cpp +++ b/toolsrc/src/vcpkg/userconfig.cpp @@ -41,7 +41,7 @@ namespace vcpkg const auto& pghs = *p_pghs; std::unordered_map keys; - if (!pghs.empty()) keys = pghs[0]; + if (pghs.size() > 0) keys = pghs[0]; for (size_t x = 1; x < pghs.size(); ++x) { diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index cbf1e97e1..e64a681e2 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -50,14 +50,14 @@ namespace vcpkg const std::string& version_check_arguments, const std::array& expected_version) { - const auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { + auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { const std::string cmd = Strings::format(R"("%s" %s)", p.u8string(), version_check_arguments); return exists_and_has_equal_or_greater_version(cmd, expected_version); }); if (it != candidate_paths.cend()) { - return *it; + return std::move(*it); } return nullopt; diff --git a/toolsrc/src/vcpkg/versiont.cpp b/toolsrc/src/vcpkg/versiont.cpp index cff49d9e8..91f7e23ef 100644 --- a/toolsrc/src/vcpkg/versiont.cpp +++ b/toolsrc/src/vcpkg/versiont.cpp @@ -6,7 +6,7 @@ namespace vcpkg { VersionT::VersionT() : value("0.0.0") {} - VersionT::VersionT(std::string&& value) : value(std::move(value)) {} + VersionT::VersionT(const std::string& value) : value(value) {} const std::string& VersionT::to_string() const { return value; } bool operator==(const VersionT& left, const VersionT& right) { return left.to_string() == right.to_string(); } bool operator!=(const VersionT& left, const VersionT& right) { return left.to_string() != right.to_string(); } -- cgit v1.2.3 From be5e529bb3e8483e5675488232d936e7d7d29ceb Mon Sep 17 00:00:00 2001 From: Albert Ziegenhagel Date: Wed, 3 Jan 2018 10:57:46 +0100 Subject: Update cmake to 3.10.1 --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index e64a681e2..70d64de45 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -115,7 +115,7 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { #if defined(_WIN32) - static constexpr std::array EXPECTED_VERSION = {3, 10, 0}; + static constexpr std::array EXPECTED_VERSION = {3, 10, 1}; #else static constexpr std::array EXPECTED_VERSION = {3, 5, 1}; #endif @@ -124,7 +124,7 @@ namespace vcpkg const std::vector from_path = Files::find_from_PATH("cmake"); std::vector candidate_paths; - const fs::path downloaded_copy = downloads_folder / "cmake-3.10.0-win32-x86" / "bin" / "cmake.exe"; + const fs::path downloaded_copy = downloads_folder / "cmake-3.10.1-win32-x86" / "bin" / "cmake.exe"; #if defined(_WIN32) candidate_paths.push_back(downloaded_copy); #endif -- cgit v1.2.3 From a28138eb9ef8d2986227b7cd784be9ffa8492a46 Mon Sep 17 00:00:00 2001 From: Jacek Blaszczynski Date: Thu, 4 Jan 2018 00:19:52 +0100 Subject: Add preliminary support for arm-windows and arm64-windows triplets (#2371) * Add preliminary support for arm-windows and arm64-windows triplets Visual Studio 15.4 shipped with new VC tools targeting arm and arm64 for desktop. This change allows for recognition and usage of new triplets supporting arm and arm64 Windows desktop and server targets. * Remove unnecessary changes * Part 2 * Part 3 * Make detection of Arm64 _VCPKG_TARGET_ARCHITECTURE precise * Enforce usage of Visual Studio CMake generatorfor arm and temporarily arm64 targets * Address code review feedback, clean libjpeg-turbo port.cmake * [libjpeg-turbo][tiff] Reduce changes to existing libraries. * [vcpkg-cmake] Simplify toolchain selection logic and improve comments --- toolsrc/src/vcpkg/triplet.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/triplet.cpp b/toolsrc/src/vcpkg/triplet.cpp index 4cba1523d..ef0fab183 100644 --- a/toolsrc/src/vcpkg/triplet.cpp +++ b/toolsrc/src/vcpkg/triplet.cpp @@ -36,6 +36,9 @@ namespace vcpkg const Triplet Triplet::X86_UWP = from_canonical_name("x86-uwp"); const Triplet Triplet::X64_UWP = from_canonical_name("x64-uwp"); const Triplet Triplet::ARM_UWP = from_canonical_name("arm-uwp"); + const Triplet Triplet::ARM64_UWP = from_canonical_name("arm64-uwp"); + const Triplet Triplet::ARM_WINDOWS = from_canonical_name("arm-windows"); + const Triplet Triplet::ARM64_WINDOWS = from_canonical_name("arm64-windows"); bool Triplet::operator==(const Triplet& other) const { return this->m_instance == other.m_instance; } -- cgit v1.2.3 From aa8883f71a3cdef460df6eda7fd6db7bca242db4 Mon Sep 17 00:00:00 2001 From: Stanislav Ershov Date: Sat, 6 Jan 2018 13:01:06 +0300 Subject: [vcpkg] fix typos in error messages --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 70d64de45..fa5fb128c 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -583,7 +583,7 @@ namespace vcpkg candidates, [&](const Toolset* t) { return *tsv == t->version && *vsp == t->visual_studio_root_path; }); Checks::check_exit(VCPKG_LINE_INFO, !candidates.empty(), - "Could not find Visual Studio instace at %s with %s toolset.", + "Could not find Visual Studio instance at %s with %s toolset.", vsp->u8string(), *tsv); @@ -595,7 +595,7 @@ namespace vcpkg { Util::stable_keep_if(candidates, [&](const Toolset* t) { return *tsv == t->version; }); Checks::check_exit( - VCPKG_LINE_INFO, !candidates.empty(), "Could not find Visual Studio instace with %s toolset.", *tsv); + VCPKG_LINE_INFO, !candidates.empty(), "Could not find Visual Studio instance with %s toolset.", *tsv); } if (vsp) @@ -605,7 +605,7 @@ namespace vcpkg [&](const Toolset* t) { return vs_root_path == t->visual_studio_root_path; }); Checks::check_exit(VCPKG_LINE_INFO, !candidates.empty(), - "Could not find Visual Studio instace at %s.", + "Could not find Visual Studio instance at %s.", vs_root_path.generic_string()); } -- cgit v1.2.3 From c14f2b36e44526300f0ea7f828d09eefb77a3ad5 Mon Sep 17 00:00:00 2001 From: Ryan Fitzsimon Date: Fri, 12 Jan 2018 14:14:23 +1000 Subject: Add output option to export - The '--output=...' option allows the date/time string used in exported filenames to be overridden --- toolsrc/src/vcpkg/export.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index e3221a12f..66e6af5b6 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -251,6 +251,8 @@ namespace vcpkg::Export bool zip; bool seven_zip; + Optional maybe_output; + Optional maybe_nuget_id; Optional maybe_nuget_version; @@ -258,6 +260,7 @@ namespace vcpkg::Export std::vector specs; }; + static const std::string OPTION_OUTPUT = "--output"; static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_RAW = "--raw"; static const std::string OPTION_NUGET = "--nuget"; @@ -280,8 +283,9 @@ namespace vcpkg::Export {OPTION_ZIP, "Export to a zip file"}, {OPTION_SEVEN_ZIP, "Export to a 7zip (.7z) file"}, }}; - static const std::array EXPORT_SETTINGS = {{ - {OPTION_NUGET_ID, "Specify the id for the exported NuGet package"}, + static const std::array EXPORT_SETTINGS = {{ + {OPTION_OUTPUT, "Specify the output name (used to construct filename)"}, + {OPTION_NUGET_ID, "Specify the id for the exported NuGet package (overrides " + OPTION_OUTPUT + ")"}, {OPTION_NUGET_VERSION, "Specify the version for the exported NuGet package"}, {OPTION_IFW_REPOSITORY_URL, "Specify the remote repository URL for the online installer"}, {OPTION_IFW_PACKAGES_DIR_PATH, "Specify the temporary directory path for the repacked packages"}, @@ -316,6 +320,8 @@ namespace vcpkg::Export ret.zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); ret.seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend(); + ret.maybe_output = maybe_lookup(options.settings, OPTION_OUTPUT); + if (!ret.raw && !ret.nuget && !ret.ifw && !ret.zip && !ret.seven_zip && !ret.dry_run) { System::println(System::Color::error, @@ -520,7 +526,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console Checks::exit_success(VCPKG_LINE_INFO); } - std::string export_id = create_export_id(); + std::string export_id = opts.maybe_output.value_or(create_export_id()); if (opts.raw || opts.nuget || opts.zip || opts.seven_zip) { -- cgit v1.2.3 From 0fde60e467ba756ddaaae389f1969a826268dc5d Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 17 Jan 2018 12:32:38 -0800 Subject: Fix variable lifetime issue --- toolsrc/src/vcpkg/export.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 66e6af5b6..d15df95d2 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -283,9 +283,13 @@ namespace vcpkg::Export {OPTION_ZIP, "Export to a zip file"}, {OPTION_SEVEN_ZIP, "Export to a 7zip (.7z) file"}, }}; + + static const std::string EXPORT_SETTINGS_NUGET_ID_HELP_TEXT = + Strings::format("Specify the id for the exported NuGet package (overrides %s)", OPTION_OUTPUT); + static const std::array EXPORT_SETTINGS = {{ {OPTION_OUTPUT, "Specify the output name (used to construct filename)"}, - {OPTION_NUGET_ID, "Specify the id for the exported NuGet package (overrides " + OPTION_OUTPUT + ")"}, + {OPTION_NUGET_ID, EXPORT_SETTINGS_NUGET_ID_HELP_TEXT}, {OPTION_NUGET_VERSION, "Specify the version for the exported NuGet package"}, {OPTION_IFW_REPOSITORY_URL, "Specify the remote repository URL for the online installer"}, {OPTION_IFW_PACKAGES_DIR_PATH, "Specify the temporary directory path for the repacked packages"}, -- cgit v1.2.3 From f563d2b58849d8ae6a04be0ad531cb2e20313fe0 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 17 Jan 2018 19:39:46 -0800 Subject: Use StringLiteral and constexpr for options/switches --- toolsrc/src/vcpkg/build.cpp | 5 ++-- toolsrc/src/vcpkg/commands.autocomplete.cpp | 6 +++-- toolsrc/src/vcpkg/commands.ci.cpp | 7 ++--- toolsrc/src/vcpkg/commands.edit.cpp | 4 +-- toolsrc/src/vcpkg/commands.list.cpp | 5 ++-- toolsrc/src/vcpkg/commands.search.cpp | 7 ++--- toolsrc/src/vcpkg/commands.upgrade.cpp | 6 ++--- toolsrc/src/vcpkg/export.cpp | 40 ++++++++++++++--------------- toolsrc/src/vcpkg/install.cpp | 18 ++++++------- toolsrc/src/vcpkg/remove.cpp | 12 ++++----- 10 files changed, 57 insertions(+), 53 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index f43d8788e..960ba0400 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,7 @@ namespace vcpkg::Build::Command using Dependencies::InstallPlanAction; using Dependencies::InstallPlanType; - static const std::string OPTION_CHECKS_ONLY = "--checks-only"; + static constexpr StringLiteral OPTION_CHECKS_ONLY = "--checks-only"; void perform_and_exit_ex(const FullPackageSpec& full_spec, const fs::path& port_dir, @@ -97,7 +98,7 @@ namespace vcpkg::Build::Command Checks::exit_success(VCPKG_LINE_INFO); } - static const std::array BUILD_SWITCHES = {{ + static constexpr std::array BUILD_SWITCHES = {{ {OPTION_CHECKS_ONLY, "Only run checks, do not rebuild package"}, }}; diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp index 0df7ec5eb..564404421 100644 --- a/toolsrc/src/vcpkg/commands.autocomplete.cpp +++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp @@ -136,8 +136,8 @@ namespace vcpkg::Commands::Autocomplete const bool is_option = Strings::case_insensitive_ascii_starts_with(prefix, "-"); if (is_option) { - results = - Util::fmap(command.structure.options.switches, [](const CommandSwitch& s) { return s.name; }); + results = Util::fmap(command.structure.options.switches, + [](const CommandSwitch& s) -> std::string { return s.name; }); auto settings = Util::fmap(command.structure.options.settings, [](auto&& s) { return s.name; }); results.insert(results.end(), settings.begin(), settings.end()); @@ -145,7 +145,9 @@ namespace vcpkg::Commands::Autocomplete else { if (command.structure.valid_arguments != nullptr) + { results = command.structure.valid_arguments(paths); + } } Util::unstable_keep_if(results, [&](const std::string& s) { diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 1a2f9b47f..4636a5738 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include +#include #include #include #include @@ -62,10 +63,10 @@ namespace vcpkg::Commands::CI Install::InstallSummary summary; }; - static const std::string OPTION_EXCLUDE = "--exclude"; - static const std::string OPTION_XUNIT = "--x-xunit"; + static constexpr StringLiteral OPTION_EXCLUDE = "--exclude"; + static constexpr StringLiteral OPTION_XUNIT = "--x-xunit"; - static const std::array CI_SETTINGS = {{ + static constexpr std::array CI_SETTINGS = {{ {OPTION_EXCLUDE, "Comma separated list of ports to skip"}, {OPTION_XUNIT, "File to output results in XUnit format (internal)"}, }}; diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index e40e394fb..3e5d08956 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -32,7 +32,7 @@ namespace vcpkg::Commands::Edit return output; } - static const std::string OPTION_BUILDTREES = "--buildtrees"; + static constexpr StringLiteral OPTION_BUILDTREES = "--buildtrees"; static std::vector valid_arguments(const VcpkgPaths& paths) { @@ -42,7 +42,7 @@ namespace vcpkg::Commands::Edit [](auto&& pgh) -> std::string { return pgh->core_paragraph->name; }); } - static const std::array EDIT_SWITCHES = {{ + static constexpr std::array EDIT_SWITCHES = {{ {OPTION_BUILDTREES, "Open editor into the port-specific buildtree subfolder"}, }}; diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp index 960c57225..2570c8a6d 100644 --- a/toolsrc/src/vcpkg/commands.list.cpp +++ b/toolsrc/src/vcpkg/commands.list.cpp @@ -7,7 +7,8 @@ namespace vcpkg::Commands::List { - static const std::string OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually + static constexpr StringLiteral OPTION_FULLDESC = + "--x-full-desc"; // TODO: This should find a better home, eventually static void do_print(const StatusParagraph& pgh, bool full_desc) { @@ -24,7 +25,7 @@ namespace vcpkg::Commands::List } } - static const std::array LIST_SWITCHES = {{ + static constexpr std::array LIST_SWITCHES = {{ {OPTION_FULLDESC, "Do not truncate long text"}, }}; diff --git a/toolsrc/src/vcpkg/commands.search.cpp b/toolsrc/src/vcpkg/commands.search.cpp index 01291ddfb..33a642e40 100644 --- a/toolsrc/src/vcpkg/commands.search.cpp +++ b/toolsrc/src/vcpkg/commands.search.cpp @@ -10,8 +10,9 @@ namespace vcpkg::Commands::Search { - static const std::string OPTION_GRAPH = "--graph"; // TODO: This should find a better home, eventually - static const std::string OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually + static constexpr StringLiteral OPTION_GRAPH = "--graph"; // TODO: This should find a better home, eventually + static constexpr StringLiteral OPTION_FULLDESC = + "--x-full-desc"; // TODO: This should find a better home, eventually static std::string replace_dashes_with_underscore(const std::string& input) { @@ -79,7 +80,7 @@ namespace vcpkg::Commands::Search } } - static std::array SEARCH_SWITCHES = {{ + static constexpr std::array SEARCH_SWITCHES = {{ {OPTION_GRAPH, "Open editor into the port-specific buildtree subfolder"}, {OPTION_FULLDESC, "Do not truncate long text"}, }}; diff --git a/toolsrc/src/vcpkg/commands.upgrade.cpp b/toolsrc/src/vcpkg/commands.upgrade.cpp index d2c868870..bb26dc735 100644 --- a/toolsrc/src/vcpkg/commands.upgrade.cpp +++ b/toolsrc/src/vcpkg/commands.upgrade.cpp @@ -15,10 +15,10 @@ namespace vcpkg::Commands::Upgrade using Install::KeepGoing; using Install::to_keep_going; - static const std::string OPTION_NO_DRY_RUN = "--no-dry-run"; - static const std::string OPTION_KEEP_GOING = "--keep-going"; + static constexpr StringLiteral OPTION_NO_DRY_RUN = "--no-dry-run"; + static constexpr StringLiteral OPTION_KEEP_GOING = "--keep-going"; - static const std::array INSTALL_SWITCHES = {{ + static constexpr std::array INSTALL_SWITCHES = {{ {OPTION_NO_DRY_RUN, "Actually upgrade"}, {OPTION_KEEP_GOING, "Continue installing packages on failure"}, }}; diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index d15df95d2..64cb3c804 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include #include #include #include @@ -260,22 +261,22 @@ namespace vcpkg::Export std::vector specs; }; - static const std::string OPTION_OUTPUT = "--output"; - static const std::string OPTION_DRY_RUN = "--dry-run"; - static const std::string OPTION_RAW = "--raw"; - static const std::string OPTION_NUGET = "--nuget"; - static const std::string OPTION_IFW = "--ifw"; - static const std::string OPTION_ZIP = "--zip"; - static const std::string OPTION_SEVEN_ZIP = "--7zip"; - static const std::string OPTION_NUGET_ID = "--nuget-id"; - static const std::string OPTION_NUGET_VERSION = "--nuget-version"; - static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url"; - static const std::string OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path"; - static const std::string OPTION_IFW_REPOSITORY_DIR_PATH = "--ifw-repository-directory-path"; - static const std::string OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path"; - static const std::string OPTION_IFW_INSTALLER_FILE_PATH = "--ifw-installer-file-path"; - - static const std::array EXPORT_SWITCHES = {{ + static constexpr StringLiteral OPTION_OUTPUT = "--output"; + static constexpr StringLiteral OPTION_DRY_RUN = "--dry-run"; + static constexpr StringLiteral OPTION_RAW = "--raw"; + static constexpr StringLiteral OPTION_NUGET = "--nuget"; + static constexpr StringLiteral OPTION_IFW = "--ifw"; + static constexpr StringLiteral OPTION_ZIP = "--zip"; + static constexpr StringLiteral OPTION_SEVEN_ZIP = "--7zip"; + static constexpr StringLiteral OPTION_NUGET_ID = "--nuget-id"; + static constexpr StringLiteral OPTION_NUGET_VERSION = "--nuget-version"; + static constexpr StringLiteral OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url"; + static constexpr StringLiteral OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path"; + static constexpr StringLiteral OPTION_IFW_REPOSITORY_DIR_PATH = "--ifw-repository-directory-path"; + static constexpr StringLiteral OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path"; + static constexpr StringLiteral OPTION_IFW_INSTALLER_FILE_PATH = "--ifw-installer-file-path"; + + static constexpr std::array EXPORT_SWITCHES = {{ {OPTION_DRY_RUN, "Do not actually export"}, {OPTION_RAW, "Export to an uncompressed directory"}, {OPTION_NUGET, "Export a NuGet package"}, @@ -284,12 +285,9 @@ namespace vcpkg::Export {OPTION_SEVEN_ZIP, "Export to a 7zip (.7z) file"}, }}; - static const std::string EXPORT_SETTINGS_NUGET_ID_HELP_TEXT = - Strings::format("Specify the id for the exported NuGet package (overrides %s)", OPTION_OUTPUT); - - static const std::array EXPORT_SETTINGS = {{ + static constexpr std::array EXPORT_SETTINGS = {{ {OPTION_OUTPUT, "Specify the output name (used to construct filename)"}, - {OPTION_NUGET_ID, EXPORT_SETTINGS_NUGET_ID_HELP_TEXT}, + {OPTION_NUGET_ID, "Specify the id for the exported NuGet package (overrides --output)"}, {OPTION_NUGET_VERSION, "Specify the version for the exported NuGet package"}, {OPTION_IFW_REPOSITORY_URL, "Specify the remote repository URL for the online installer"}, {OPTION_IFW_PACKAGES_DIR_PATH, "Specify the temporary directory path for the repacked packages"}, diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index dcc130be3..d6a28d57c 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -413,21 +413,21 @@ namespace vcpkg::Install return InstallSummary{std::move(results), timer.to_string()}; } - static const std::string OPTION_DRY_RUN = "--dry-run"; - static const std::string OPTION_USE_HEAD_VERSION = "--head"; - static const std::string OPTION_NO_DOWNLOADS = "--no-downloads"; - static const std::string OPTION_RECURSE = "--recurse"; - static const std::string OPTION_KEEP_GOING = "--keep-going"; - static const std::string OPTION_XUNIT = "--x-xunit"; - - static const std::array INSTALL_SWITCHES = {{ + static constexpr StringLiteral OPTION_DRY_RUN = "--dry-run"; + static constexpr StringLiteral OPTION_USE_HEAD_VERSION = "--head"; + static constexpr StringLiteral OPTION_NO_DOWNLOADS = "--no-downloads"; + static constexpr StringLiteral OPTION_RECURSE = "--recurse"; + static constexpr StringLiteral OPTION_KEEP_GOING = "--keep-going"; + static constexpr StringLiteral OPTION_XUNIT = "--x-xunit"; + + static constexpr std::array INSTALL_SWITCHES = {{ {OPTION_DRY_RUN, "Do not actually build or install"}, {OPTION_USE_HEAD_VERSION, "Install the libraries on the command line using the latest upstream sources"}, {OPTION_NO_DOWNLOADS, "Do not download new sources"}, {OPTION_RECURSE, "Allow removal of packages as part of installation"}, {OPTION_KEEP_GOING, "Continue installing packages on failure"}, }}; - static const std::array INSTALL_SETTINGS = {{ + static constexpr std::array INSTALL_SETTINGS = {{ {OPTION_XUNIT, "File to output results in XUnit format (Internal use)"}, }}; diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 4079d60c1..e03df2ed2 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -164,13 +164,13 @@ namespace vcpkg::Remove } } - static const std::string OPTION_PURGE = "--purge"; - static const std::string OPTION_NO_PURGE = "--no-purge"; - static const std::string OPTION_RECURSE = "--recurse"; - static const std::string OPTION_DRY_RUN = "--dry-run"; - static const std::string OPTION_OUTDATED = "--outdated"; + static constexpr StringLiteral OPTION_PURGE = "--purge"; + static constexpr StringLiteral OPTION_NO_PURGE = "--no-purge"; + static constexpr StringLiteral OPTION_RECURSE = "--recurse"; + static constexpr StringLiteral OPTION_DRY_RUN = "--dry-run"; + static constexpr StringLiteral OPTION_OUTDATED = "--outdated"; - static const std::array SWITCHES = {{ + static constexpr std::array SWITCHES = {{ {OPTION_PURGE, "Remove the cached copy of the package (default)"}, {OPTION_NO_PURGE, "Do not remove the cached copy of the package"}, {OPTION_RECURSE, "Allow removal of packages not explicitly specified on the command line"}, -- cgit v1.2.3 From 14650ddfb8d31a0e075b4684e8c1ebc9976319bc Mon Sep 17 00:00:00 2001 From: Jonathan Hale Date: Thu, 18 Jan 2018 10:09:53 +0100 Subject: [vkpkg] Fix edit command not considering EDITOR environment variable (#2597) * [vkpkg] Fix edit command not considering EDITOR environment variable Signed-off-by: Squareys * [vcpkg-edit] Reformat and improve code consistency --- toolsrc/src/vcpkg/commands.edit.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index 3e5d08956..41f261a53 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -68,8 +68,11 @@ namespace vcpkg::Commands::Edit Checks::check_exit(VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name); std::vector candidate_paths; - const std::vector from_path = Files::find_from_PATH("EDITOR"); - candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + auto maybe_editor_path = System::get_environment_variable("EDITOR"); + if (auto editor_path = maybe_editor_path.get()) + { + candidate_paths.emplace_back(*editor_path); + } candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE_INSIDERS); candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE_INSIDERS); candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE); @@ -81,8 +84,9 @@ namespace vcpkg::Commands::Edit auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { return fs.exists(p); }); if (it == candidate_paths.cend()) { - System::println(System::Color::error, - "Error: Visual Studio Code was not found and the environment variable EDITOR is not set."); + System::println( + System::Color::error, + "Error: Visual Studio Code was not found and the environment variable EDITOR is not set or invalid."); System::println("The following paths were examined:"); Files::print_paths(candidate_paths); System::println("You can also set the environmental variable EDITOR to your editor of choice."); -- cgit v1.2.3 From 228eebfbecf2e5d0a4c901820b26659137707d7a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 19 Jan 2018 15:23:47 -0800 Subject: [vcpkg] Add additional tests. Enable featurepackages by default. --- toolsrc/src/tests.plan.cpp | 69 +++++++++++++++++++++++++++++++++ toolsrc/src/vcpkg/globalstate.cpp | 2 +- toolsrc/src/vcpkg/vcpkgcmdarguments.cpp | 5 +++ 3 files changed, 75 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 781588c91..593003b80 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -434,6 +434,75 @@ namespace UnitTest1 Assert::IsTrue(install_plan.size() == 1); features_check(&install_plan[0], "a", {"0", "1", "core"}, Triplet::X64_WINDOWS); } + + TEST_METHOD(transitive_features_test) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"0", "b[0]"}}), {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "c", {{"0", "c[0]"}}), {"core"}}; + auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}}; + + auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); + Assert::IsTrue(install_specs.has_value()); + if (!install_specs.has_value()) return; + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::IsTrue(install_plan.size() == 3); + features_check(&install_plan[0], "c", {"0", "core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[1], "b", {"0", "core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[2], "a", {"0", "core"}, Triplet::X64_WINDOWS); + } + + TEST_METHOD(no_transitive_features_test) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"0", ""}}), {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "c", {{"0", ""}}), {"core"}}; + auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}}; + + auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); + Assert::IsTrue(install_specs.has_value()); + if (!install_specs.has_value()) return; + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::IsTrue(install_plan.size() == 3); + features_check(&install_plan[0], "c", {"core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[1], "b", {"core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[2], "a", {"0", "core"}, Triplet::X64_WINDOWS); + } + + TEST_METHOD(only_transitive_features_test) + { + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "", {{"0", "b[0]"}}), {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "", {{"0", "c[0]"}}), {"core"}}; + auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}}; + + auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); + Assert::IsTrue(install_specs.has_value()); + if (!install_specs.has_value()) return; + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::IsTrue(install_plan.size() == 3); + features_check(&install_plan[0], "c", {"0", "core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[1], "b", {"0", "core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[2], "a", {"0", "core"}, Triplet::X64_WINDOWS); + } }; static PackageSpec unsafe_pspec(std::string name, Triplet t = Triplet::X86_WINDOWS) diff --git a/toolsrc/src/vcpkg/globalstate.cpp b/toolsrc/src/vcpkg/globalstate.cpp index 123c77d46..eac69d9f5 100644 --- a/toolsrc/src/vcpkg/globalstate.cpp +++ b/toolsrc/src/vcpkg/globalstate.cpp @@ -8,7 +8,7 @@ namespace vcpkg Util::LockGuarded GlobalState::g_surveydate; std::atomic GlobalState::debugging(false); - std::atomic GlobalState::feature_packages(false); + std::atomic GlobalState::feature_packages(true); std::atomic GlobalState::g_init_console_cp(0); std::atomic GlobalState::g_init_console_output_cp(0); diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp index 671a89892..84ad17fe3 100644 --- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp +++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp @@ -129,6 +129,11 @@ namespace vcpkg GlobalState::feature_packages = true; continue; } + if (arg == "--no-featurepackages") + { + GlobalState::feature_packages = false; + continue; + } const auto eq_pos = arg.find('='); if (eq_pos != std::string::npos) -- cgit v1.2.3 From 0682bb734d5f8667d5aa1a8c2448d69fc042c53f Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 22 Jan 2018 23:40:41 -0800 Subject: [vcpkg] Store Optional<&> instead of Optional<*> --- toolsrc/src/tests.plan.cpp | 3 +-- toolsrc/src/vcpkg/dependencies.cpp | 6 +++--- toolsrc/src/vcpkg/install.cpp | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 593003b80..0916e66c8 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -41,8 +41,7 @@ namespace UnitTest1 Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); - Assert::AreEqual(pkg_name.c_str(), - (*plan.any_paragraph.source_control_file.get())->core_paragraph->name.c_str()); + Assert::AreEqual(pkg_name.c_str(), plan.any_paragraph.source_control_file.get()->core_paragraph->name.c_str()); Assert::AreEqual(size_t(vec.size()), feature_list.size()); for (auto&& feature_name : vec) diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 76aeb0eaa..e48d85885 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -117,7 +117,7 @@ namespace vcpkg::Dependencies return PackageSpec::from_dependencies_of_port(p->core_paragraph.spec.name(), deps, triplet); } - if (const auto p = this->source_control_file.value_or(nullptr)) + if (const auto p = this->source_control_file.get()) { return PackageSpec::from_dependencies_of_port( p->core_paragraph->name, filter_dependencies(p->core_paragraph->depends, triplet), triplet); @@ -159,7 +159,7 @@ namespace vcpkg::Dependencies const RequestType& request_type) : spec(spec), plan_type(InstallPlanType::BUILD_AND_INSTALL), request_type(request_type), feature_list(features) { - this->any_paragraph.source_control_file = &any_paragraph; + this->any_paragraph.source_control_file = any_paragraph; } InstallPlanAction::InstallPlanAction(const PackageSpec& spec, @@ -418,7 +418,7 @@ namespace vcpkg::Dependencies return ExportPlanAction{spec, AnyParagraph{nullopt, std::move(*bcf), nullopt}, request_type}; auto maybe_scf = provider.get_control_file(spec.name()); - if (auto scf = maybe_scf.get()) return ExportPlanAction{spec, {nullopt, nullopt, scf}, request_type}; + if (auto scf = maybe_scf.get()) return ExportPlanAction{spec, {nullopt, nullopt, *scf}, request_type}; Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); } diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index d6a28d57c..3ecb627f5 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -293,7 +293,7 @@ namespace vcpkg::Install auto result = [&]() -> Build::ExtendedBuildResult { const Build::BuildPackageConfig build_config{ - *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), + action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), action.spec.triplet(), paths.port_dir(action.spec), action.build_options, -- cgit v1.2.3 From 10d712ed018fe3b2cd8d485e41f32ad555d9a1f1 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 23 Jan 2018 01:56:25 -0800 Subject: [vcpkg] Added StatusParagraph::is_installed() --- toolsrc/src/vcpkg/statusparagraphs.cpp | 2 +- toolsrc/src/vcpkg/vcpkglib.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp index d4afc0427..19919b76f 100644 --- a/toolsrc/src/vcpkg/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -48,7 +48,7 @@ namespace vcpkg const Triplet& triplet) const { const const_iterator it = find(name, triplet); - if (it != end() && (*it)->want == Want::INSTALL && (*it)->state == InstallState::INSTALLED) + if (it != end() && (*it)->is_installed()) { return it; } diff --git a/toolsrc/src/vcpkg/vcpkglib.cpp b/toolsrc/src/vcpkg/vcpkglib.cpp index 5b2cec4d0..de6ffefed 100644 --- a/toolsrc/src/vcpkg/vcpkglib.cpp +++ b/toolsrc/src/vcpkg/vcpkglib.cpp @@ -173,7 +173,7 @@ namespace vcpkg std::vector installed_packages; for (auto&& pgh : status_db) { - if (pgh->state != InstallState::INSTALLED || pgh->want != Want::INSTALL) continue; + if (!pgh->is_installed()) continue; installed_packages.push_back(pgh.get()); } @@ -189,7 +189,7 @@ namespace vcpkg for (const std::unique_ptr& pgh : status_db) { - if (pgh->state != InstallState::INSTALLED || !pgh->package.feature.empty()) + if (!pgh->is_installed() || !pgh->package.feature.empty()) { continue; } -- cgit v1.2.3 From ff8a2d17266f1c601d04ac7b3c3e85ad674c8491 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 23 Jan 2018 02:21:47 -0800 Subject: [vcpkg] Remove AnyParagraph and InstallPlanType::INSTALL --- toolsrc/src/tests.plan.cpp | 2 +- toolsrc/src/tests.utils.cpp | 1 - toolsrc/src/vcpkg/commands.exportifw.cpp | 9 +-- toolsrc/src/vcpkg/dependencies.cpp | 132 ++++++++++++++----------------- toolsrc/src/vcpkg/export.cpp | 5 +- toolsrc/src/vcpkg/install.cpp | 30 ++----- toolsrc/src/vcpkg/statusparagraphs.cpp | 23 +++++- 7 files changed, 96 insertions(+), 106 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 0916e66c8..67abf8de0 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -41,7 +41,7 @@ namespace UnitTest1 Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); - Assert::AreEqual(pkg_name.c_str(), plan.any_paragraph.source_control_file.get()->core_paragraph->name.c_str()); + Assert::AreEqual(pkg_name.c_str(), plan.source_control_file.get()->core_paragraph->name.c_str()); Assert::AreEqual(size_t(vec.size()), feature_list.size()); for (auto&& feature_name : vec) diff --git a/toolsrc/src/tests.utils.cpp b/toolsrc/src/tests.utils.cpp index b9fb51a59..d155c7238 100644 --- a/toolsrc/src/tests.utils.cpp +++ b/toolsrc/src/tests.utils.cpp @@ -13,7 +13,6 @@ namespace Microsoft::VisualStudio::CppUnitTestFramework { case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; - case Dependencies::InstallPlanType::INSTALL: return L"INSTALL"; case Dependencies::InstallPlanType::EXCLUDED: return L"EXCLUDED"; case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; default: return ToString(static_cast(t)); diff --git a/toolsrc/src/vcpkg/commands.exportifw.cpp b/toolsrc/src/vcpkg/commands.exportifw.cpp index 682267acb..b25982e4b 100644 --- a/toolsrc/src/vcpkg/commands.exportifw.cpp +++ b/toolsrc/src/vcpkg/commands.exportifw.cpp @@ -69,8 +69,7 @@ namespace vcpkg::Export::IFW { std::error_code ec; - const BinaryParagraph& binary_paragraph = - action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + const BinaryParagraph& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO); // Prepare meta dir const fs::path package_xml_file_path = @@ -142,8 +141,7 @@ namespace vcpkg::Export::IFW for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) { const ExportPlanAction& action = *(package->second); - const BinaryParagraph& binary_paragraph = - action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + const BinaryParagraph& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO); package_xml_file_path = raw_exported_dir_path / Strings::format("packages.%s", package->first) / "meta" / "package.xml"; @@ -436,8 +434,7 @@ namespace vcpkg::Export::IFW const std::string display_name = action.spec.to_string(); System::println("Exporting package %s... ", display_name); - const BinaryParagraph& binary_paragraph = - action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + const BinaryParagraph& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO); unique_packages[action.spec.name()] = &action; unique_triplets.insert(action.spec.triplet().canonical_name()); diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index e48d85885..277de0557 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -103,28 +103,15 @@ namespace vcpkg::Dependencies const PortFileProvider& m_provider; }; - std::vector AnyParagraph::dependencies(const Triplet& triplet) const + static std::vector source_paragraphs_dependencies(Span spghs) { - if (const auto p = this->status_paragraph.get()) - { - return PackageSpec::from_dependencies_of_port(p->package.spec.name(), p->package.depends, triplet); - } + if (spghs.size() == 0) return {}; - if (const auto p = this->binary_control_file.get()) - { - auto deps = Util::fmap_flatten(p->features, [](const BinaryParagraph& pgh) { return pgh.depends; }); - deps.insert(deps.end(), p->core_paragraph.depends.cbegin(), p->core_paragraph.depends.cend()); - return PackageSpec::from_dependencies_of_port(p->core_paragraph.spec.name(), deps, triplet); - } + auto deps = Util::fmap_flatten( + spghs, [](const StatusParagraph* pgh) -> std::vector const& { return pgh->package.depends; }); - if (const auto p = this->source_control_file.get()) - { - return PackageSpec::from_dependencies_of_port( - p->core_paragraph->name, filter_dependencies(p->core_paragraph->depends, triplet), triplet); - } - - Checks::exit_with_message(VCPKG_LINE_INFO, - "Cannot get dependencies because there was none of: source/binary/status paragraphs"); + auto&& spec = spghs[0]->package.spec; + return PackageSpec::from_dependencies_of_port(spec.name(), deps, spec.triplet()); } std::string to_output_string(RequestType request_type, @@ -154,45 +141,28 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction() : plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} InstallPlanAction::InstallPlanAction(const PackageSpec& spec, - const SourceControlFile& any_paragraph, + const SourceControlFile& scf, const std::unordered_set& features, const RequestType& request_type) - : spec(spec), plan_type(InstallPlanType::BUILD_AND_INSTALL), request_type(request_type), feature_list(features) + : spec(spec) + , source_control_file(scf) + , plan_type(InstallPlanType::BUILD_AND_INSTALL) + , request_type(request_type) + , feature_list(features) { - this->any_paragraph.source_control_file = any_paragraph; } InstallPlanAction::InstallPlanAction(const PackageSpec& spec, + std::vector&& spghs, const std::unordered_set& features, const RequestType& request_type) - : spec(spec), plan_type(InstallPlanType::ALREADY_INSTALLED), request_type(request_type), feature_list(features) + : spec(spec) + , status_paragraphs(std::move(spghs)) + , plan_type(InstallPlanType::ALREADY_INSTALLED) + , request_type(request_type) + , feature_list(features) { - } - - InstallPlanAction::InstallPlanAction(const PackageSpec& spec, - const AnyParagraph& any_paragraph, - const RequestType& request_type) - : spec(spec), any_paragraph(any_paragraph), plan_type(InstallPlanType::UNKNOWN), request_type(request_type) - { - if (auto p = any_paragraph.status_paragraph.get()) - { - this->plan_type = InstallPlanType::ALREADY_INSTALLED; - return; - } - - if (auto p = any_paragraph.binary_control_file.get()) - { - this->plan_type = InstallPlanType::INSTALL; - return; - } - - if (auto p = any_paragraph.source_control_file.get()) - { - this->plan_type = InstallPlanType::BUILD_AND_INSTALL; - return; - } - - Checks::unreachable(VCPKG_LINE_INFO); + Checks::check_exit(VCPKG_LINE_INFO, status_paragraphs.get()->size() > 0); } std::string InstallPlanAction::displayname() const @@ -243,21 +213,30 @@ namespace vcpkg::Dependencies ExportPlanAction::ExportPlanAction() : plan_type(ExportPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} ExportPlanAction::ExportPlanAction(const PackageSpec& spec, - const AnyParagraph& any_paragraph, + std::vector&& status_paragraphs, const RequestType& request_type) - : spec(spec), any_paragraph(any_paragraph), plan_type(ExportPlanType::UNKNOWN), request_type(request_type) + : spec(spec) + , plan_type(ExportPlanType::ALREADY_BUILT) + , request_type(request_type) + , m_spghs(std::move(status_paragraphs)) { - if (auto p = any_paragraph.binary_control_file.get()) - { - this->plan_type = ExportPlanType::ALREADY_BUILT; - return; - } + } - if (auto p = any_paragraph.source_control_file.get()) - { - this->plan_type = ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT; - return; - } + ExportPlanAction::ExportPlanAction(const PackageSpec& spec, const RequestType& request_type) + : spec(spec), plan_type(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT), request_type(request_type) + { + } + + Optional ExportPlanAction::core_paragraph() const + { + auto it = m_spghs.begin(); + if (it == m_spghs.end()) return nullopt; + return (*it)->package; + } + + std::vector ExportPlanAction::dependencies(const Triplet&) const + { + return source_paragraphs_dependencies(m_spghs); } bool RemovePlanAction::compare_by_name(const RemovePlanAction* left, const RemovePlanAction* right) @@ -404,7 +383,7 @@ namespace vcpkg::Dependencies std::vector adjacency_list(const ExportPlanAction& plan) const override { - return plan.any_paragraph.dependencies(plan.spec.triplet()); + return plan.dependencies(plan.spec.triplet()); } ExportPlanAction load_vertex_data(const PackageSpec& spec) const override @@ -413,14 +392,22 @@ namespace vcpkg::Dependencies ? RequestType::USER_REQUESTED : RequestType::AUTO_SELECTED; - Expected maybe_bpgh = Paragraphs::try_load_cached_control_package(paths, spec); - if (auto bcf = maybe_bpgh.get()) - return ExportPlanAction{spec, AnyParagraph{nullopt, std::move(*bcf), nullopt}, request_type}; - - auto maybe_scf = provider.get_control_file(spec.name()); - if (auto scf = maybe_scf.get()) return ExportPlanAction{spec, {nullopt, nullopt, *scf}, request_type}; + auto spghs = status_db.find_all_installed(spec); - Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); + if (spghs.size() == 0) + { + return ExportPlanAction{spec, request_type}; + } + else + { + return ExportPlanAction{ + spec, + Util::fmap(spghs, + [](std::unique_ptr const* const& p) -> const StatusParagraph* { + return p->get(); + }), + request_type}; + } } std::string to_string(const PackageSpec& spec) const override { return spec.to_string(); } @@ -642,6 +629,7 @@ namespace vcpkg::Dependencies if (p_cluster->request_type != RequestType::USER_REQUESTED) continue; plan.emplace_back(InstallPlanAction{ p_cluster->spec, + {p_cluster->status_paragraphs.begin(), p_cluster->status_paragraphs.end()}, p_cluster->original_features, p_cluster->request_type, }); @@ -664,17 +652,18 @@ namespace vcpkg::Dependencies cluster.transient_uninstalled = false; - cluster.status_paragraphs.emplace_back(status_paragraph); - auto& status_paragraph_feature = status_paragraph->package.feature; + // In this case, empty string indicates the "core" paragraph for a package. if (status_paragraph_feature.empty()) { cluster.original_features.insert("core"); + cluster.status_paragraphs.emplace(cluster.status_paragraphs.begin(), status_paragraph); } else { cluster.original_features.insert(status_paragraph_feature); + cluster.status_paragraphs.emplace_back(status_paragraph); } } @@ -739,7 +728,6 @@ namespace vcpkg::Dependencies { switch (install_action->plan_type) { - case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break; case InstallPlanType::ALREADY_INSTALLED: if (install_action->request_type == RequestType::USER_REQUESTED) already_installed_plans.emplace_back(install_action); diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 64cb3c804..a9c407dd8 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -385,7 +385,7 @@ namespace vcpkg::Export " %s" "\n", cmake_variable.s); - }; + } static void handle_raw_based_export(Span export_plan, const ExportArguments& opts, @@ -410,8 +410,7 @@ namespace vcpkg::Export const std::string display_name = action.spec.to_string(); System::println("Exporting package %s... ", display_name); - const BinaryParagraph& binary_paragraph = - action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + const BinaryParagraph& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO); const InstallDir dirs = InstallDir::from_destination_root( raw_exported_dir_path / "installed", diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 3ecb627f5..368ca6487 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -292,12 +292,11 @@ namespace vcpkg::Install System::println("Building package %s... ", display_name_with_features); auto result = [&]() -> Build::ExtendedBuildResult { - const Build::BuildPackageConfig build_config{ - action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), - action.spec.triplet(), - paths.port_dir(action.spec), - action.build_options, - action.feature_list}; + const Build::BuildPackageConfig build_config{action.source_control_file.value_or_exit(VCPKG_LINE_INFO), + action.spec.triplet(), + paths.port_dir(action.spec), + action.build_options, + action.feature_list}; return Build::build_package(paths, build_config, status_db); }(); @@ -315,18 +314,6 @@ namespace vcpkg::Install return {code, std::move(bcf)}; } - if (plan_type == InstallPlanType::INSTALL) - { - if (use_head_version && is_user_requested) - { - System::println( - System::Color::warning, "Package %s is already built -- not building from HEAD", display_name); - } - auto code = aux_install(display_name_with_features, - action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO)); - return code; - } - if (plan_type == InstallPlanType::EXCLUDED) { System::println(System::Color::warning, "Package %s is excluded", display_name); @@ -662,11 +649,10 @@ namespace vcpkg::Install if (action) if (auto p_install_plan = action->install_action.get()) { - if (auto p_bcf = p_install_plan->any_paragraph.binary_control_file.get()) - return &p_bcf->core_paragraph; - else if (auto p_status = p_install_plan->any_paragraph.status_paragraph.get()) + if (auto p_status = p_install_plan->status_paragraphs.get()) { - return &p_status->package; + Checks::check_exit(VCPKG_LINE_INFO, p_status->size() > 0); + return &(*p_status->begin())->package; } } return nullptr; diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp index 19919b76f..61c04d72a 100644 --- a/toolsrc/src/vcpkg/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -18,7 +18,28 @@ namespace vcpkg { if (p->package.spec.name() == name && p->package.spec.triplet() == triplet) { - spghs.emplace_back(&p); + if (p->package.feature.empty()) + spghs.emplace(spghs.begin(), &p); + else + spghs.emplace_back(&p); + } + } + return spghs; + } + + std::vector*> StatusParagraphs::find_all_installed( + const PackageSpec& spec) const + { + std::vector*> spghs; + for (auto&& p : *this) + { + if (p->package.spec.name() == spec.name() && p->package.spec.triplet() == spec.triplet() && + p->is_installed()) + { + if (p->package.feature.empty()) + spghs.emplace(spghs.begin(), &p); + else + spghs.emplace_back(&p); } } return spghs; -- cgit v1.2.3 From 78d3302940f6c11a220008215b6f67daa8cc8bb7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 23 Jan 2018 02:36:39 -0800 Subject: [vcpkg] Remove overload of StatusParagraphs::find_installed() --- toolsrc/src/tests.plan.cpp | 7 ------- toolsrc/src/tests.statusparagraphs.cpp | 10 ++++++---- toolsrc/src/tests.utils.cpp | 7 +++++++ toolsrc/src/vcpkg/build.cpp | 6 +++--- toolsrc/src/vcpkg/statusparagraphs.cpp | 15 +++++++++++---- 5 files changed, 27 insertions(+), 18 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 67abf8de0..86386be14 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -504,13 +504,6 @@ namespace UnitTest1 } }; - static PackageSpec unsafe_pspec(std::string name, Triplet t = Triplet::X86_WINDOWS) - { - auto m_ret = PackageSpec::from_name_and_triplet(name, t); - Assert::IsTrue(m_ret.has_value()); - return m_ret.value_or_exit(VCPKG_LINE_INFO); - } - class RemovePlanTests : public TestClass { TEST_METHOD(basic_remove_scheme) diff --git a/toolsrc/src/tests.statusparagraphs.cpp b/toolsrc/src/tests.statusparagraphs.cpp index ed6eaa764..0d5324a8c 100644 --- a/toolsrc/src/tests.statusparagraphs.cpp +++ b/toolsrc/src/tests.statusparagraphs.cpp @@ -1,5 +1,7 @@ #include "tests.pch.h" +#include + using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace vcpkg; @@ -25,7 +27,7 @@ Status: install ok installed StatusParagraphs status_db(Util::fmap( *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique(std::move(rpgh)); })); - auto it = status_db.find_installed("ffmpeg", Triplet::X64_WINDOWS); + auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); Assert::IsTrue(it != status_db.end()); } @@ -45,7 +47,7 @@ Status: purge ok not-installed StatusParagraphs status_db(Util::fmap( *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique(std::move(rpgh)); })); - auto it = status_db.find_installed("ffmpeg", Triplet::X64_WINDOWS); + auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); Assert::IsTrue(it == status_db.end()); } @@ -73,8 +75,8 @@ Status: purge ok not-installed StatusParagraphs status_db(Util::fmap( *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique(std::move(rpgh)); })); - auto it = status_db.find_installed("ffmpeg", Triplet::X64_WINDOWS); + auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); Assert::IsTrue(it != status_db.end()); } }; -} \ No newline at end of file +} diff --git a/toolsrc/src/tests.utils.cpp b/toolsrc/src/tests.utils.cpp index d155c7238..19e877920 100644 --- a/toolsrc/src/tests.utils.cpp +++ b/toolsrc/src/tests.utils.cpp @@ -59,3 +59,10 @@ std::unique_ptr make_status_feature_pgh(const char* name, {"Depends", depends}, {"Status", "install ok installed"}}); } + +PackageSpec unsafe_pspec(std::string name, Triplet t) +{ + auto m_ret = PackageSpec::from_name_and_triplet(name, t); + Assert::IsTrue(m_ret.has_value()); + return m_ret.value_or_exit(VCPKG_LINE_INFO); +} diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 960ba0400..d583a409e 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -269,10 +269,10 @@ namespace vcpkg::Build std::vector missing_specs; for (auto&& dep : filter_dependencies(config.scf.core_paragraph->depends, triplet)) { - if (status_db.find_installed(dep, triplet) == status_db.end()) + auto spec = PackageSpec::from_name_and_triplet(dep, triplet).value_or_exit(VCPKG_LINE_INFO); + if (!status_db.is_installed(spec)) { - missing_specs.push_back( - PackageSpec::from_name_and_triplet(dep, triplet).value_or_exit(VCPKG_LINE_INFO)); + missing_specs.push_back(spec); } } // Fail the build if any dependencies were missing diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp index 61c04d72a..fb5267b95 100644 --- a/toolsrc/src/vcpkg/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -65,16 +65,23 @@ namespace vcpkg }); } - StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name, - const Triplet& triplet) const + StatusParagraphs::const_iterator StatusParagraphs::find_installed(const PackageSpec& spec) const { - const const_iterator it = find(name, triplet); + auto it = find(spec); if (it != end() && (*it)->is_installed()) { return it; } + else + { + return end(); + } + } - return end(); + bool vcpkg::StatusParagraphs::is_installed(const PackageSpec& spec) const + { + auto it = find(spec); + return it != end() && (*it)->is_installed(); } StatusParagraphs::iterator StatusParagraphs::insert(std::unique_ptr pgh) -- cgit v1.2.3 From 3beeb94ec5ca73636d1a26bd9c2ec386b15df9b7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 23 Jan 2018 06:50:24 -0800 Subject: [vcpkg] Use InstalledPackageView instead of unsorted raw vectors --- toolsrc/src/vcpkg/dependencies.cpp | 56 +++++++++++++--------------------- toolsrc/src/vcpkg/install.cpp | 5 ++- toolsrc/src/vcpkg/remove.cpp | 39 +++++++++++++---------- toolsrc/src/vcpkg/statusparagraph.cpp | 12 ++++++++ toolsrc/src/vcpkg/statusparagraphs.cpp | 17 +++++++---- 5 files changed, 70 insertions(+), 59 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 277de0557..5ce96a3e1 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -22,7 +22,8 @@ namespace vcpkg::Dependencies struct Cluster : Util::MoveOnlyBase { - std::vector status_paragraphs; + InstalledPackageView installed_package; + Optional source_control_file; PackageSpec spec; std::unordered_map edges; @@ -103,17 +104,6 @@ namespace vcpkg::Dependencies const PortFileProvider& m_provider; }; - static std::vector source_paragraphs_dependencies(Span spghs) - { - if (spghs.size() == 0) return {}; - - auto deps = Util::fmap_flatten( - spghs, [](const StatusParagraph* pgh) -> std::vector const& { return pgh->package.depends; }); - - auto&& spec = spghs[0]->package.spec; - return PackageSpec::from_dependencies_of_port(spec.name(), deps, spec.triplet()); - } - std::string to_output_string(RequestType request_type, const CStringView s, const Build::BuildPackageOptions& options) @@ -153,16 +143,15 @@ namespace vcpkg::Dependencies } InstallPlanAction::InstallPlanAction(const PackageSpec& spec, - std::vector&& spghs, + InstalledPackageView&& ipv, const std::unordered_set& features, const RequestType& request_type) : spec(spec) - , status_paragraphs(std::move(spghs)) + , installed_package(std::move(ipv)) , plan_type(InstallPlanType::ALREADY_INSTALLED) , request_type(request_type) , feature_list(features) { - Checks::check_exit(VCPKG_LINE_INFO, status_paragraphs.get()->size() > 0); } std::string InstallPlanAction::displayname() const @@ -213,12 +202,12 @@ namespace vcpkg::Dependencies ExportPlanAction::ExportPlanAction() : plan_type(ExportPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} ExportPlanAction::ExportPlanAction(const PackageSpec& spec, - std::vector&& status_paragraphs, + InstalledPackageView&& installed_package, const RequestType& request_type) : spec(spec) , plan_type(ExportPlanType::ALREADY_BUILT) , request_type(request_type) - , m_spghs(std::move(status_paragraphs)) + , m_installed_package(std::move(installed_package)) { } @@ -229,14 +218,19 @@ namespace vcpkg::Dependencies Optional ExportPlanAction::core_paragraph() const { - auto it = m_spghs.begin(); - if (it == m_spghs.end()) return nullopt; - return (*it)->package; + if (auto p_ip = m_installed_package.get()) + { + return p_ip->core->package; + } + return nullopt; } std::vector ExportPlanAction::dependencies(const Triplet&) const { - return source_paragraphs_dependencies(m_spghs); + if (auto p_ip = m_installed_package.get()) + return p_ip->dependencies(); + else + return {}; } bool RemovePlanAction::compare_by_name(const RemovePlanAction* left, const RemovePlanAction* right) @@ -392,21 +386,15 @@ namespace vcpkg::Dependencies ? RequestType::USER_REQUESTED : RequestType::AUTO_SELECTED; - auto spghs = status_db.find_all_installed(spec); + auto maybe_ipv = status_db.find_all_installed(spec); - if (spghs.size() == 0) + if (auto p_ipv = maybe_ipv.get()) { - return ExportPlanAction{spec, request_type}; + return ExportPlanAction{spec, std::move(*p_ipv), request_type}; } else { - return ExportPlanAction{ - spec, - Util::fmap(spghs, - [](std::unique_ptr const* const& p) -> const StatusParagraph* { - return p->get(); - }), - request_type}; + return ExportPlanAction{spec, request_type}; } } @@ -629,7 +617,7 @@ namespace vcpkg::Dependencies if (p_cluster->request_type != RequestType::USER_REQUESTED) continue; plan.emplace_back(InstallPlanAction{ p_cluster->spec, - {p_cluster->status_paragraphs.begin(), p_cluster->status_paragraphs.end()}, + InstalledPackageView{p_cluster->installed_package}, p_cluster->original_features, p_cluster->request_type, }); @@ -658,12 +646,12 @@ namespace vcpkg::Dependencies if (status_paragraph_feature.empty()) { cluster.original_features.insert("core"); - cluster.status_paragraphs.emplace(cluster.status_paragraphs.begin(), status_paragraph); + cluster.installed_package.core = status_paragraph; } else { cluster.original_features.insert(status_paragraph_feature); - cluster.status_paragraphs.emplace_back(status_paragraph); + cluster.installed_package.features.emplace_back(status_paragraph); } } diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 368ca6487..7a1ba4698 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -649,10 +649,9 @@ namespace vcpkg::Install if (action) if (auto p_install_plan = action->install_action.get()) { - if (auto p_status = p_install_plan->status_paragraphs.get()) + if (auto p_status = p_install_plan->installed_package.get()) { - Checks::check_exit(VCPKG_LINE_INFO, p_status->size() > 0); - return &(*p_status->begin())->package; + return &p_status->core->package; } } return nullptr; diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index e03df2ed2..3815c3ce7 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -18,22 +18,31 @@ namespace vcpkg::Remove using Dependencies::RequestType; using Update::OutdatedPackage; - void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db) + void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, const StatusParagraphs& status_db) { auto& fs = paths.get_filesystem(); - auto spghs = status_db->find_all(spec.name(), spec.triplet()); - const auto core_pkg = **status_db->find(spec.name(), spec.triplet(), ""); + auto maybe_ipv = status_db.find_all_installed(spec); + + Checks::check_exit( + VCPKG_LINE_INFO, maybe_ipv.has_value(), "unable to remove package %s: already removed", spec); + + auto&& ipv = maybe_ipv.value_or_exit(VCPKG_LINE_INFO); + + std::vector spghs; + spghs.emplace_back(*ipv.core); + for (auto&& feature : ipv.features) + { + spghs.emplace_back(*feature); + } for (auto&& spgh : spghs) { - StatusParagraph& pkg = **spgh; - if (pkg.state != InstallState::INSTALLED) continue; - pkg.want = Want::PURGE; - pkg.state = InstallState::HALF_INSTALLED; - write_update(paths, pkg); + spgh.want = Want::PURGE; + spgh.state = InstallState::HALF_INSTALLED; + write_update(paths, spgh); } - auto maybe_lines = fs.read_lines(paths.listfile_path(core_pkg.package)); + auto maybe_lines = fs.read_lines(paths.listfile_path(ipv.core->package)); if (const auto lines = maybe_lines.get()) { @@ -90,15 +99,13 @@ namespace vcpkg::Remove } } - fs.remove(paths.listfile_path(core_pkg.package)); + fs.remove(paths.listfile_path(ipv.core->package)); } for (auto&& spgh : spghs) { - StatusParagraph& pkg = **spgh; - if (pkg.state != InstallState::HALF_INSTALLED) continue; - pkg.state = InstallState::NOT_INSTALLED; - write_update(paths, pkg); + spgh.state = InstallState::NOT_INSTALLED; + write_update(paths, spgh); } } @@ -136,7 +143,7 @@ namespace vcpkg::Remove void perform_remove_plan_action(const VcpkgPaths& paths, const RemovePlanAction& action, const Purge purge, - StatusParagraphs& status_db) + const StatusParagraphs& status_db) { const std::string display_name = action.spec.to_string(); @@ -147,7 +154,7 @@ namespace vcpkg::Remove break; case RemovePlanType::REMOVE: System::println("Removing package %s... ", display_name); - remove_package(paths, action.spec, &status_db); + remove_package(paths, action.spec, status_db); System::println(System::Color::success, "Removing package %s... done", display_name); break; case RemovePlanType::UNKNOWN: diff --git a/toolsrc/src/vcpkg/statusparagraph.cpp b/toolsrc/src/vcpkg/statusparagraph.cpp index 5f00825e1..05238ba8b 100644 --- a/toolsrc/src/vcpkg/statusparagraph.cpp +++ b/toolsrc/src/vcpkg/statusparagraph.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include #include using namespace vcpkg::Parse; @@ -83,4 +84,15 @@ namespace vcpkg default: return "error"; } } + std::vector InstalledPackageView::dependencies() const + { + auto deps = Util::fmap_flatten(features, [](const StatusParagraph* pgh) -> std::vector const& { + return pgh->package.depends; + }); + + deps.insert(deps.end(), core->package.depends.begin(), core->package.depends.end()); + + auto&& spec = core->package.spec; + return PackageSpec::from_dependencies_of_port(spec.name(), deps, spec.triplet()); + } } diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp index fb5267b95..475f86279 100644 --- a/toolsrc/src/vcpkg/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -27,22 +27,27 @@ namespace vcpkg return spghs; } - std::vector*> StatusParagraphs::find_all_installed( - const PackageSpec& spec) const + Optional StatusParagraphs::find_all_installed(const PackageSpec& spec) const { - std::vector*> spghs; + InstalledPackageView ipv; for (auto&& p : *this) { if (p->package.spec.name() == spec.name() && p->package.spec.triplet() == spec.triplet() && p->is_installed()) { if (p->package.feature.empty()) - spghs.emplace(spghs.begin(), &p); + { + Checks::check_exit(VCPKG_LINE_INFO, ipv.core == nullptr); + ipv.core = p.get(); + } else - spghs.emplace_back(&p); + ipv.features.emplace_back(p.get()); } } - return spghs; + if (ipv.core != nullptr) + return std::move(ipv); + else + return nullopt; } StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, -- cgit v1.2.3 From 130fa279f968ad9661ff4614a2b87f1bb0c5aee2 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 23 Jan 2018 14:14:01 -0800 Subject: [vcpkg] Revert making remove_package() take status_db by const The in-memory database must be updated to communicate to future actions that they need to look at this package's files (or not) --- toolsrc/src/vcpkg/install.cpp | 2 +- toolsrc/src/vcpkg/remove.cpp | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 7a1ba4698..081063633 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -386,7 +386,7 @@ namespace vcpkg::Install } else if (const auto remove_action = action.remove_action.get()) { - Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db); + Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, &status_db); } else { diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 3815c3ce7..3eaf991ce 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -18,10 +18,10 @@ namespace vcpkg::Remove using Dependencies::RequestType; using Update::OutdatedPackage; - void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, const StatusParagraphs& status_db) + void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db) { auto& fs = paths.get_filesystem(); - auto maybe_ipv = status_db.find_all_installed(spec); + auto maybe_ipv = status_db->find_all_installed(spec); Checks::check_exit( VCPKG_LINE_INFO, maybe_ipv.has_value(), "unable to remove package %s: already removed", spec); @@ -106,6 +106,8 @@ namespace vcpkg::Remove { spgh.state = InstallState::NOT_INSTALLED; write_update(paths, spgh); + + status_db->insert(std::make_unique(std::move(spgh))); } } @@ -143,7 +145,7 @@ namespace vcpkg::Remove void perform_remove_plan_action(const VcpkgPaths& paths, const RemovePlanAction& action, const Purge purge, - const StatusParagraphs& status_db) + StatusParagraphs* status_db) { const std::string display_name = action.spec.to_string(); @@ -285,7 +287,7 @@ namespace vcpkg::Remove for (const RemovePlanAction& action : remove_plan) { - perform_remove_plan_action(paths, action, purge, status_db); + perform_remove_plan_action(paths, action, purge, &status_db); } Checks::exit_success(VCPKG_LINE_INFO); -- cgit v1.2.3 From 3332326c655714fe2e1f740b5635a29c86581228 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 19 Jan 2018 15:12:21 -0800 Subject: Update CMake to 3.10.2 --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index fa5fb128c..e6daedcd4 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -115,7 +115,7 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { #if defined(_WIN32) - static constexpr std::array EXPECTED_VERSION = {3, 10, 1}; + static constexpr std::array EXPECTED_VERSION = {3, 10, 2}; #else static constexpr std::array EXPECTED_VERSION = {3, 5, 1}; #endif @@ -124,7 +124,7 @@ namespace vcpkg const std::vector from_path = Files::find_from_PATH("cmake"); std::vector candidate_paths; - const fs::path downloaded_copy = downloads_folder / "cmake-3.10.1-win32-x86" / "bin" / "cmake.exe"; + const fs::path downloaded_copy = downloads_folder / "cmake-3.10.2-win32-x86" / "bin" / "cmake.exe"; #if defined(_WIN32) candidate_paths.push_back(downloaded_copy); #endif -- cgit v1.2.3 From 209452755be4e607864481a24eb6383f7e3e984d Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:18:31 -0800 Subject: Fix #include casing --- toolsrc/src/vcpkg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 094ea1dc5..0af6bd76a 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -4,7 +4,7 @@ #pragma warning(push) #pragma warning(disable : 4768) -#include +#include #pragma warning(pop) #else #include -- cgit v1.2.3 From a413b523e2a4e96c2e2cc3eb4e24e11f7ac75b52 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:19:51 -0800 Subject: Add missing initializer --- toolsrc/src/vcpkg/build.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index d583a409e..74b946775 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -61,7 +61,8 @@ namespace vcpkg::Build::Command spec.name()); const StatusParagraphs status_db = database_load_check(paths); - const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; + const Build::BuildPackageOptions build_package_options{ + Build::UseHeadVersion::NO, Build::AllowDownloads::YES, Build::CleanBuildtrees::NO}; const std::unordered_set features_as_set(full_spec.features.begin(), full_spec.features.end()); -- cgit v1.2.3 From 80f1563c6b6204d09b750944433d51047c46afba Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:21:33 -0800 Subject: Use empty() instead of comparing with size() --- toolsrc/src/vcpkg.cpp | 2 +- toolsrc/src/vcpkg/build.cpp | 2 +- toolsrc/src/vcpkg/commands.cache.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 0af6bd76a..9f29dcdd2 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -214,7 +214,7 @@ static void load_config() static std::string trim_path_from_command_line(const std::string& full_command_line) { Checks::check_exit( - VCPKG_LINE_INFO, full_command_line.size() > 0, "Internal failure - cannot have empty command line"); + VCPKG_LINE_INFO, !full_command_line.empty(), "Internal failure - cannot have empty command line"); if (full_command_line[0] == '"') { diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 74b946775..4a6834443 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -296,7 +296,7 @@ namespace vcpkg::Build { features.append(feature + ";"); } - if (features.size() > 0) + if (!features.empty()) { features.pop_back(); } diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp index 6fd123b7c..85bf5fb4d 100644 --- a/toolsrc/src/vcpkg/commands.cache.cpp +++ b/toolsrc/src/vcpkg/commands.cache.cpp @@ -47,7 +47,7 @@ namespace vcpkg::Commands::Cache Checks::exit_success(VCPKG_LINE_INFO); } - if (args.command_arguments.size() == 0) + if (args.command_arguments.empty()) { for (const BinaryParagraph& binary_paragraph : binary_paragraphs) { -- cgit v1.2.3 From 2f6e549223021b446b6b5c2942c665ee9a4b91d7 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:23:21 -0800 Subject: Use emplace_back() instead of push_back() --- toolsrc/src/vcpkg/commands.create.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp index 44f5f7928..25c34cf09 100644 --- a/toolsrc/src/vcpkg/commands.create.cpp +++ b/toolsrc/src/vcpkg/commands.create.cpp @@ -34,7 +34,7 @@ namespace vcpkg::Commands::Create R"(Filename cannot contain invalid chars %s, but was %s)", Files::FILESYSTEM_INVALID_CHARACTERS, zip_file_name); - cmake_args.push_back({"FILENAME", zip_file_name}); + cmake_args.emplace_back("FILENAME", zip_file_name); } const std::string cmd_launch_cmake = make_cmake_cmd(cmake_exe, paths.ports_cmake, cmake_args); -- cgit v1.2.3 From adc8055a90b56cfc2bc45e39deea2d3ab95b8216 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:23:38 -0800 Subject: Rename to avoid variable hiding. Move temp into vector --- toolsrc/src/vcpkg/build.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 4a6834443..db1360ba0 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -270,10 +270,10 @@ namespace vcpkg::Build std::vector missing_specs; for (auto&& dep : filter_dependencies(config.scf.core_paragraph->depends, triplet)) { - auto spec = PackageSpec::from_name_and_triplet(dep, triplet).value_or_exit(VCPKG_LINE_INFO); - if (!status_db.is_installed(spec)) + auto dep_spec = PackageSpec::from_name_and_triplet(dep, triplet).value_or_exit(VCPKG_LINE_INFO); + if (!status_db.is_installed(dep_spec)) { - missing_specs.push_back(spec); + missing_specs.push_back(std::move(dep_spec)); } } // Fail the build if any dependencies were missing -- cgit v1.2.3 From bbf1a737b6da91a452d93579b5162bd7c6239316 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:27:38 -0800 Subject: Use for-each loop --- toolsrc/src/vcpkg/commands.exportifw.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.exportifw.cpp b/toolsrc/src/vcpkg/commands.exportifw.cpp index b25982e4b..58d9aa0be 100644 --- a/toolsrc/src/vcpkg/commands.exportifw.cpp +++ b/toolsrc/src/vcpkg/commands.exportifw.cpp @@ -138,13 +138,13 @@ namespace vcpkg::Export::IFW )###", create_release_date())); - for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) + for (const auto& unique_package : unique_packages) { - const ExportPlanAction& action = *(package->second); + const ExportPlanAction& action = *(unique_package.second); const BinaryParagraph& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO); package_xml_file_path = - raw_exported_dir_path / Strings::format("packages.%s", package->first) / "meta" / "package.xml"; + raw_exported_dir_path / Strings::format("packages.%s", unique_package.first) / "meta" / "package.xml"; package_xml_dir_path = package_xml_file_path.parent_path(); fs.create_directories(package_xml_dir_path, ec); Checks::check_exit(VCPKG_LINE_INFO, -- cgit v1.2.3 From 9d85ed4c17bd871cfc4b267c3231fc207f4f0006 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:28:20 -0800 Subject: Use char instead of string when string-searching for a single char --- toolsrc/src/vcpkg/commands.hash.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 1e3e5b23d..fa3d80f27 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -7,7 +7,7 @@ namespace vcpkg::Commands::Hash { - static void do_file_hash(fs::path const &cmake_exe_path, fs::path const& path, std::string const& hash_type) + static void do_file_hash(fs::path const& cmake_exe_path, fs::path const& path, std::string const& hash_type) { const std::string cmd_line = Strings::format( R"("%s" -E %ssum %s)", cmake_exe_path.u8string(), Strings::ascii_to_lowercase(hash_type), path.u8string()); @@ -17,7 +17,7 @@ namespace vcpkg::Commands::Hash std::string const& output = ec_data.output; - const auto start = output.find_first_of(" "); + const auto start = output.find_first_of(' '); Checks::check_exit( VCPKG_LINE_INFO, start != std::string::npos, "Unexpected output format from command: %s", cmd_line); -- cgit v1.2.3 From bff50291c209e7864ec1a58f8bc8d646ae7d7240 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:28:55 -0800 Subject: Use empty() instead of size() == 0 --- toolsrc/src/vcpkg/commands.list.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp index 2570c8a6d..a5efd5442 100644 --- a/toolsrc/src/vcpkg/commands.list.cpp +++ b/toolsrc/src/vcpkg/commands.list.cpp @@ -58,7 +58,7 @@ namespace vcpkg::Commands::List return lhs->package.displayname() < rhs->package.displayname(); }); - if (args.command_arguments.size() == 0) + if (args.command_arguments.empty()) { for (const StatusParagraph* status_paragraph : installed_packages) { -- cgit v1.2.3 From 47833bb39310c0c76a02f3724faf07b41488c736 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:31:39 -0800 Subject: Parameter name consistency between declaration and definition --- toolsrc/src/vcpkg/dependencies.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 5ce96a3e1..236d38bea 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -415,10 +415,10 @@ namespace vcpkg::Dependencies static MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, - ClusterGraph& pkg_to_cluster, + ClusterGraph& graph, GraphPlan& graph_plan); - static void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + static void mark_minus(Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan); MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { -- cgit v1.2.3 From 5be6975cd53892479aae4ce5e9af6cc9ea88634e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:33:13 -0800 Subject: Use =default for trivial destructor --- toolsrc/src/vcpkg/dependencies.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 236d38bea..af2e8b431 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -682,7 +682,7 @@ namespace vcpkg::Dependencies { } - PackageGraph::~PackageGraph() {} + PackageGraph::~PackageGraph() = default; void print_plan(const std::vector& action_plan, const bool is_recursive) { -- cgit v1.2.3 From acf3f30d7a4b8cd4b568f6faa3314bcf1940521d Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:33:47 -0800 Subject: Init order should match order of fields --- toolsrc/src/vcpkg/dependencies.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index af2e8b431..26ee19e66 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -678,7 +678,7 @@ namespace vcpkg::Dependencies } PackageGraph::PackageGraph(const PortFileProvider& provider, const StatusParagraphs& status_db) - : m_graph(create_feature_install_graph(provider, status_db)), m_graph_plan(std::make_unique()) + : m_graph_plan(std::make_unique()), m_graph(create_feature_install_graph(provider, status_db)) { } -- cgit v1.2.3 From f3a43d98abecb61a7628f415d9bbe886c4bb26ec Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:36:06 -0800 Subject: Remove unneeded else --- toolsrc/src/vcpkg/dependencies.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 26ee19e66..a4ef991fc 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -392,10 +392,8 @@ namespace vcpkg::Dependencies { return ExportPlanAction{spec, std::move(*p_ipv), request_type}; } - else - { - return ExportPlanAction{spec, request_type}; - } + + return ExportPlanAction{spec, request_type}; } std::string to_string(const PackageSpec& spec) const override { return spec.to_string(); } -- cgit v1.2.3 From 639f99379847a95a7dacd8874dc41276b6fe4862 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:38:08 -0800 Subject: Add missing method const --- toolsrc/src/vcpkg/dependencies.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index a4ef991fc..71cfd52c1 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -527,7 +527,7 @@ namespace vcpkg::Dependencies return create_feature_install_plan(provider, specs, status_db); } - void PackageGraph::install(const FeatureSpec& spec) + void PackageGraph::install(const FeatureSpec& spec) const { Cluster& spec_cluster = m_graph->get(spec.spec()); spec_cluster.request_type = RequestType::USER_REQUESTED; @@ -565,7 +565,7 @@ namespace vcpkg::Dependencies m_graph_plan->install_graph.add_vertex(ClusterPtr{&spec_cluster}); } - void PackageGraph::upgrade(const PackageSpec& spec) + void PackageGraph::upgrade(const PackageSpec& spec) const { Cluster& spec_cluster = m_graph->get(spec); spec_cluster.request_type = RequestType::USER_REQUESTED; -- cgit v1.2.3 From 67755f9415cb8c7aae971084aa5313bfa71c97bb Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 23 Jan 2018 15:40:25 -0800 Subject: Use !empty() instead of size() > 0 --- toolsrc/src/vcpkg/dependencies.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 71cfd52c1..4842fde96 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -743,29 +743,29 @@ namespace vcpkg::Dependencies }); }; - if (excluded.size() > 0) + if (!excluded.empty()) { System::println("The following packages are excluded:\n%s", actions_to_output_string(excluded)); } - if (already_installed_plans.size() > 0) + if (!already_installed_plans.empty()) { System::println("The following packages are already installed:\n%s", actions_to_output_string(already_installed_plans)); } - if (rebuilt_plans.size() > 0) + if (!rebuilt_plans.empty()) { System::println("The following packages will be rebuilt:\n%s", actions_to_output_string(rebuilt_plans)); } - if (new_plans.size() > 0) + if (!new_plans.empty()) { System::println("The following packages will be built and installed:\n%s", actions_to_output_string(new_plans)); } - if (only_install_plans.size() > 0) + if (!only_install_plans.empty()) { System::println("The following packages will be directly installed:\n%s", actions_to_output_string(only_install_plans)); @@ -774,7 +774,7 @@ namespace vcpkg::Dependencies if (has_non_user_requested_packages) System::println("Additional packages (*) will be modified to complete this operation."); - if (remove_plans.size() > 0 && !is_recursive) + if (!remove_plans.empty() && !is_recursive) { System::println(System::Color::warning, "If you are sure you want to rebuild the above packages, run the command with the " -- cgit v1.2.3 From 9eda2e04d161503672bf4250e304892e4ab39c03 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 24 Jan 2018 14:20:24 -0800 Subject: [vcpkg] Fix issue with any command executing more than 10 transactions with mixed types. Fixes #2600. Fixes #2582. --- toolsrc/src/vcpkg/vcpkglib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkglib.cpp b/toolsrc/src/vcpkg/vcpkglib.cpp index de6ffefed..220c29720 100644 --- a/toolsrc/src/vcpkg/vcpkglib.cpp +++ b/toolsrc/src/vcpkg/vcpkglib.cpp @@ -92,7 +92,7 @@ namespace vcpkg const auto my_update_id = update_id++; const auto tmp_update_filename = paths.vcpkg_dir_updates / "incomplete"; - const auto update_filename = paths.vcpkg_dir_updates / std::to_string(my_update_id); + const auto update_filename = paths.vcpkg_dir_updates / Strings::format("%010d", my_update_id); fs.write_contents(tmp_update_filename, Strings::serialize(p)); fs.rename(tmp_update_filename, update_filename); -- cgit v1.2.3 From 75f19a58ba27f79da4c57d22e4a9e92afcb55d4c Mon Sep 17 00:00:00 2001 From: atkawa7 Date: Sat, 27 Jan 2018 00:44:07 +0200 Subject: [vcpkg] Add string constructor (#2429) * [vcpkg] Add string constructor * Update versiont.h --- toolsrc/src/vcpkg/versiont.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/versiont.cpp b/toolsrc/src/vcpkg/versiont.cpp index 91f7e23ef..0d4a39255 100644 --- a/toolsrc/src/vcpkg/versiont.cpp +++ b/toolsrc/src/vcpkg/versiont.cpp @@ -6,6 +6,7 @@ namespace vcpkg { VersionT::VersionT() : value("0.0.0") {} + VersionT::VersionT(std::string&& value) : value(std::move(value)) {} VersionT::VersionT(const std::string& value) : value(value) {} const std::string& VersionT::to_string() const { return value; } bool operator==(const VersionT& left, const VersionT& right) { return left.to_string() == right.to_string(); } -- cgit v1.2.3 From 99e5f4ac5090a9558dec13ad11d95024404005e1 Mon Sep 17 00:00:00 2001 From: Squareys Date: Sat, 3 Feb 2018 21:41:49 +0100 Subject: [vcpkg] Add cmake variable containing all features in the package Signed-off-by: Squareys --- toolsrc/src/vcpkg/build.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index db1360ba0..295bd240e 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -290,6 +290,7 @@ namespace vcpkg::Build const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); std::string features; + std::string all_features; if (GlobalState::feature_packages) { for (auto&& feature : config.feature_list) @@ -300,6 +301,10 @@ namespace vcpkg::Build { features.pop_back(); } + for (auto& feature : config.scf.feature_paragraphs) + { + all_features.append(feature->name + ";"); + } } const Toolset& toolset = paths.get_toolset(pre_build_info); @@ -317,6 +322,7 @@ namespace vcpkg::Build {"_VCPKG_NO_DOWNLOADS", !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, {"GIT", git_exe_path}, {"FEATURES", features}, + {"ALL_FEATURES", all_features}, }); const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); -- cgit v1.2.3 From 0ef1bbb38cf187064e55bcab50de5012e502b3af Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 3 Feb 2018 21:24:30 -0800 Subject: [vcpkg] Fix crash when trying to enumerate nonexistent directory. --- toolsrc/src/vcpkg/base/files.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 8c9e137ed..060a14da3 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -74,6 +74,7 @@ namespace vcpkg::Files std::error_code ec; fs::stdfs::recursive_directory_iterator b(dir, ec), e{}; + if (ec) return ret; for (; b != e; ++b) { ret.push_back(b->path()); @@ -86,7 +87,9 @@ namespace vcpkg::Files { std::vector ret; - fs::stdfs::directory_iterator b(dir), e{}; + std::error_code ec; + fs::stdfs::directory_iterator b(dir, ec), e{}; + if (ec) return ret; for (; b != e; ++b) { ret.push_back(b->path()); -- cgit v1.2.3 From b2465a175570df33730937c250357bd1f092b277 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 9 Feb 2018 19:46:43 -0800 Subject: [vcpkg-ci] Delete intermediate build folders even on unsuccesful builds --- toolsrc/src/vcpkg/build.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 295bd240e..7de276f4f 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -258,9 +258,9 @@ namespace vcpkg::Build paths.get_filesystem().write_contents(binary_control_file, start); } - ExtendedBuildResult build_package(const VcpkgPaths& paths, - const BuildPackageConfig& config, - const StatusParagraphs& status_db) + static ExtendedBuildResult do_build_package(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const StatusParagraphs& status_db) { const PackageSpec spec = PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, config.triplet) .value_or_exit(VCPKG_LINE_INFO); @@ -369,10 +369,19 @@ namespace vcpkg::Build write_binary_control_file(paths, *bcf); + return {BuildResult::SUCCEEDED, std::move(bcf)}; + } + + ExtendedBuildResult build_package(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const StatusParagraphs& status_db) + { + ExtendedBuildResult result = do_build_package(paths, config, status_db); + if (config.build_package_options.clean_buildtrees == CleanBuildtrees::YES) { auto& fs = paths.get_filesystem(); - auto buildtrees_dir = paths.buildtrees / spec.name(); + auto buildtrees_dir = paths.buildtrees / config.scf.core_paragraph->name; auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir); for (auto&& file : buildtree_files) { @@ -384,7 +393,7 @@ namespace vcpkg::Build } } - return {BuildResult::SUCCEEDED, std::move(bcf)}; + return result; } const std::string& to_string(const BuildResult build_result) -- cgit v1.2.3 From 9d97db3daa08168bcc4e9ac61af1df73d85ab649 Mon Sep 17 00:00:00 2001 From: ChrisBFX Date: Sat, 10 Feb 2018 23:05:50 +0100 Subject: fixed typo in warning message (#2773) --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index e6daedcd4..06e0c01ab 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -524,7 +524,7 @@ namespace vcpkg { System::println( System::Color::warning, - "Warning: The following VS instances are exluded because the English language pack is unavailable."); + "Warning: The following VS instances are excluded because the English language pack is unavailable."); for (const Toolset& toolset : excluded_toolsets) { System::println(" %s", toolset.visual_studio_root_path.u8string()); -- cgit v1.2.3 From 425d07ef7f82541e50cc8cb1e2716fc33bba7b12 Mon Sep 17 00:00:00 2001 From: Jonathan Hale Date: Thu, 15 Feb 2018 01:18:25 +0100 Subject: [vcpkg] Implement Default-Features (#2697) * [vcpkg] Add Default-Feature to make_status_pgh utility function Signed-off-by: Squareys * [vcpkg] Parse "Default-Features" as dependencies and add test for parsing Signed-off-by: Squareys * [vcpkg] Document some methods and structures Signed-off-by: Squareys * [vcpkg] Add install_default_features_test Signed-off-by: Squareys * [vcpkg] Change install_default_features_test to not have preinstalled package * [vcpkg] Test install behaviour of default features Signed-off-by: Squareys * [vcpkg] Implement default features Signed-off-by: Squareys * [vcpkg] Test default features upgrade behavior Signed-off-by: Squareys * [vcpkg] Implement upgrade with default features Signed-off-by: Squareys * [vcpkg] Test behaviour of upgrade with default features in dependencies Signed-off-by: Squareys * [vcpkg] Make upgrade install new default features Signed-off-by: Squareys * [vcpkg] Move collecting of packages for which to prevent defaults Further down the line to create_feature_install_plan. Signed-off-by: Squareys * [vcpkg] Fix core missing from default features and potential inf loop Signed-off-by: Squareys * [vcpkg] Rename, fix and move some tests Signed-off-by: Squareys --- toolsrc/src/tests.paragraph.cpp | 35 +++++- toolsrc/src/tests.plan.cpp | 245 +++++++++++++++++++++++++++++++++++-- toolsrc/src/tests.utils.cpp | 6 +- toolsrc/src/vcpkg/dependencies.cpp | 129 +++++++++++++++++-- toolsrc/src/vcpkg/install.cpp | 5 + 5 files changed, 395 insertions(+), 25 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.paragraph.cpp b/toolsrc/src/tests.paragraph.cpp index 9cddd7bdb..dca89bc59 100644 --- a/toolsrc/src/tests.paragraph.cpp +++ b/toolsrc/src/tests.paragraph.cpp @@ -1,4 +1,4 @@ -#include "tests.pch.h" +#include "tests.pch.h" #pragma comment(lib, "version") #pragma comment(lib, "winhttp") @@ -47,6 +47,7 @@ namespace UnitTest1 {"Maintainer", "m"}, {"Description", "d"}, {"Build-Depends", "bd"}, + {"Default-Features", "df"}, {"Supports", "x64"}, }}); Assert::IsTrue(m_pgh.has_value()); @@ -58,6 +59,8 @@ namespace UnitTest1 Assert::AreEqual("d", pgh->core_paragraph->description.c_str()); Assert::AreEqual(size_t(1), pgh->core_paragraph->depends.size()); Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name().c_str()); + Assert::AreEqual(size_t(1), pgh->core_paragraph->default_features.size()); + Assert::AreEqual("df", pgh->core_paragraph->default_features[0].c_str()); Assert::AreEqual(size_t(1), pgh->core_paragraph->supports.size()); Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str()); } @@ -134,6 +137,21 @@ namespace UnitTest1 Assert::AreEqual("uwp", pgh->core_paragraph->depends[1].qualifier.c_str()); } + TEST_METHOD(SourceParagraph_Default_Features) + { + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector>{{ + {"Source", "a"}, + {"Version", "1.0"}, + {"Default-Features", "a1"}, + }}); + Assert::IsTrue(m_pgh.has_value()); + auto& pgh = *m_pgh.get(); + + Assert::AreEqual(size_t(1), pgh->core_paragraph->default_features.size()); + Assert::AreEqual("a1", pgh->core_paragraph->default_features[0].c_str()); + } + TEST_METHOD(BinaryParagraph_Construct_Minimum) { vcpkg::BinaryParagraph pgh({ @@ -200,6 +218,21 @@ namespace UnitTest1 Assert::IsTrue(pgh.abi == "abcd123"); } + TEST_METHOD(BinaryParagraph_Default_Features) + { + vcpkg::BinaryParagraph pgh({ + {"Package", "a"}, + {"Version", "1.0"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Default-Features", "a1"}, + }); + + Assert::AreEqual(size_t(0), pgh.depends.size()); + Assert::AreEqual(size_t(1), pgh.default_features.size()); + Assert::IsTrue(pgh.default_features[0] == "a1"); + } + TEST_METHOD(parse_paragraphs_empty) { const char* str = ""; diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 86386be14..a4c628bf6 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -9,15 +9,17 @@ using namespace vcpkg; namespace UnitTest1 { static std::unique_ptr make_control_file( - const char* name, const char* depends, const std::vector>& features = {}) + const char* name, + const char* depends, + const std::vector>& features = {}, + const std::vector& default_features = {}) { using Pgh = std::unordered_map; std::vector scf_pghs; - scf_pghs.push_back(Pgh{ - {"Source", name}, - {"Version", "0"}, - {"Build-Depends", depends}, - }); + scf_pghs.push_back(Pgh{{"Source", name}, + {"Version", "0"}, + {"Build-Depends", depends}, + {"Default-Features", Strings::join(", ", default_features)}}); for (auto&& feature : features) { scf_pghs.push_back(Pgh{ @@ -31,11 +33,15 @@ namespace UnitTest1 return std::move(*m_pgh.get()); } + /// + /// Assert that the given action an install of given features from given package. + /// static void features_check(Dependencies::AnyAction* install_action, std::string pkg_name, std::vector vec, const Triplet& triplet = Triplet::X86_WINDOWS) { + Assert::IsTrue(install_action->install_action.has_value()); const auto& plan = install_action->install_action.value_or_exit(VCPKG_LINE_INFO); const auto& feature_list = plan.feature_list; @@ -56,6 +62,9 @@ namespace UnitTest1 } } + /// + /// Assert that the given action is a remove of given package. + /// static void remove_plan_check(Dependencies::AnyAction* remove_action, std::string pkg_name, const Triplet& triplet = Triplet::X86_WINDOWS) @@ -65,6 +74,9 @@ namespace UnitTest1 Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); } + /// + /// Map of source control files by their package name. + /// struct PackageSpecMap { std::unordered_map map; @@ -73,9 +85,10 @@ namespace UnitTest1 PackageSpec emplace(const char* name, const char* depends = "", - const std::vector>& features = {}) + const std::vector>& features = {}, + const std::vector& default_features = {}) { - return emplace(std::move(*make_control_file(name, depends, features))); + return emplace(std::move(*make_control_file(name, depends, features, default_features))); } PackageSpec emplace(vcpkg::SourceControlFile&& scf) { @@ -434,6 +447,190 @@ namespace UnitTest1 features_check(&install_plan[0], "a", {"0", "1", "core"}, Triplet::X64_WINDOWS); } + TEST_METHOD(install_default_features_test_1) + { + std::vector> status_paragraphs; + + // Add a port "a" with default features "1" and features "0" and "1". + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}, {"1"}); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect the default feature "1" to be installed, but not "0" + Assert::IsTrue(install_plan.size() == 1); + features_check(&install_plan[0], "a", {"1", "core"}, Triplet::X64_WINDOWS); + } + + TEST_METHOD(install_default_features_test_2) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.spec = + PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + // Add a port "a" of which "core" is already installed, but we will + // install the default features "explicitly" + // "a" has two features, of which "a1" is default. + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "", {{"a0", ""}, {"a1", ""}}, {"a1"}); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect "a" to get removed for rebuild and then installed with default + // features. + Assert::IsTrue(install_plan.size() == 2); + remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); + features_check(&install_plan[1], "a", {"a1", "core"}, Triplet::X64_WINDOWS); + } + + TEST_METHOD(install_default_features_test_3) + { + std::vector> status_paragraphs; + + // "a" has two features, of which "a1" is default. + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "", {{"a0", ""}, {"a1", ""}}, {"a1"}); + + // Explicitly install "a" without default features + auto install_specs = FullPackageSpec::from_string("a[core]", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect the default feature not to get installed. + Assert::IsTrue(install_plan.size() == 1); + features_check(&install_plan[0], "a", {"core"}, Triplet::X64_WINDOWS); + } + + TEST_METHOD(install_default_features_of_dependency_test_1) + { + std::vector> status_paragraphs; + + // Add a port "a" which depends on the core of "b" + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "b[core]"); + // "b" has two features, of which "b1" is default. + spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"}); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect "a" to get installed and defaults of "b" through the dependency, + // as no explicit features of "b" are installed by the user. + Assert::IsTrue(install_plan.size() == 2); + features_check(&install_plan[1], "a", {"core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[0], "b", {"b1", "core"}, Triplet::X64_WINDOWS); + } + + TEST_METHOD(install_default_features_of_dependency_test_2) + { + std::vector> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("b")); + status_paragraphs.back()->package.spec = + PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + // Add a port "a" which depends on the core of "b", which was already + // installed explicitly + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "b[core]"); + // "b" has two features, of which "b1" is default. + spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"}); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect "a" to get installed, not the defaults of "b", as the required + // dependencies are already there, installed explicitly by the user. + Assert::IsTrue(install_plan.size() == 1); + features_check(&install_plan[0], "a", {"core"}, Triplet::X64_WINDOWS); + } + + TEST_METHOD(upgrade_with_default_features_1) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a", "", "1")); + pghs.push_back(make_status_feature_pgh("a", "0")); + pghs.back()->package.spec = + PackageSpec::from_name_and_triplet("a", Triplet::X86_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + StatusParagraphs status_db(std::move(pghs)); + + // Add a port "a" of which "core" and "0" are already installed. + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}, {"1"}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + auto plan = graph.serialize(); + + // The upgrade should not install the default feature + Assert::AreEqual(size_t(2), plan.size()); + + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + + Assert::AreEqual("a", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].install_action.has_value()); + features_check(&plan[1], "a", {"core", "0"}, Triplet::X86_WINDOWS); + } + + TEST_METHOD(upgrade_with_default_features_2) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("b")); + pghs.push_back(make_status_pgh("a", "b[core]")); + pghs.back()->package.spec = + PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + StatusParagraphs status_db(std::move(pghs)); + + // Add a port "a" of which "core" and "0" are already installed. + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a = spec_map.emplace("a", "b[core]"); + spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b0"}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + auto plan = graph.serialize(); + + // The upgrade should not install the default feature + Assert::AreEqual(size_t(3), plan.size()); + + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + + Assert::AreEqual("b", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].install_action.has_value()); + features_check(&plan[1], "b", {"b0", "core"}, Triplet::X64_WINDOWS); + + Assert::AreEqual("a", plan[2].spec().name().c_str()); + Assert::IsTrue(plan[2].install_action.has_value()); + features_check(&plan[2], "a", {"core"}, Triplet::X64_WINDOWS); + } + TEST_METHOD(transitive_features_test) { std::vector> status_paragraphs; @@ -567,9 +764,9 @@ namespace UnitTest1 TEST_METHOD(features_depend_remove_scheme_once_removed_x64) { std::vector> pghs; - pghs.push_back(make_status_pgh("expat", "", "x64")); - pghs.push_back(make_status_pgh("vtk", "expat", "x64")); - pghs.push_back(make_status_pgh("opencv", "", "x64")); + pghs.push_back(make_status_pgh("expat", "", "", "x64")); + pghs.push_back(make_status_pgh("vtk", "expat", "", "x64")); + pghs.push_back(make_status_pgh("opencv", "", "", "x64")); pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk", "x64")); StatusParagraphs status_db(std::move(pghs)); @@ -715,5 +912,31 @@ namespace UnitTest1 features_check(&plan[1], "a", {"core", "a1"}); } + + TEST_METHOD(basic_upgrade_scheme_with_new_default_feature) + { + // only core of package "a" is installed + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + // a1 was added as a default feature and should be installed in upgrade + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}, {"a1"}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(2), plan.size()); + + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + + features_check(&plan[1], "a", {"core", "a1"}); + } }; } diff --git a/toolsrc/src/tests.utils.cpp b/toolsrc/src/tests.utils.cpp index 19e877920..a3d8ffc7d 100644 --- a/toolsrc/src/tests.utils.cpp +++ b/toolsrc/src/tests.utils.cpp @@ -35,7 +35,10 @@ namespace Microsoft::VisualStudio::CppUnitTestFramework std::wstring ToString(const vcpkg::PackageSpec& t) { return ToString(t.to_string()); } } -std::unique_ptr make_status_pgh(const char* name, const char* depends, const char* triplet) +std::unique_ptr make_status_pgh(const char* name, + const char* depends, + const char* default_features, + const char* triplet) { using Pgh = std::unordered_map; return std::make_unique(Pgh{{"Package", name}, @@ -43,6 +46,7 @@ std::unique_ptr make_status_pgh(const char* name, const char* d {"Architecture", triplet}, {"Multi-Arch", "same"}, {"Depends", depends}, + {"Default-Features", default_features}, {"Status", "install ok installed"}}); } std::unique_ptr make_status_feature_pgh(const char* name, diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 4842fde96..307c779c8 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -20,6 +20,9 @@ namespace vcpkg::Dependencies bool plus = false; }; + /// + /// Representation of a package and its features in a ClusterGraph. + /// struct Cluster : Util::MoveOnlyBase { InstalledPackageView installed_package; @@ -64,10 +67,18 @@ namespace vcpkg::Dependencies Graphs::Graph install_graph; }; + /// + /// Directional graph representing a collection of packages with their features connected by their dependencies. + /// struct ClusterGraph : Util::MoveOnlyBase { explicit ClusterGraph(const PortFileProvider& provider) : m_provider(provider) {} + /// + /// Find the cluster associated with spec or if not found, create it from the PortFileProvider. + /// + /// Package spec to get the cluster for. + /// The cluster found or created for spec. Cluster& get(const PackageSpec& spec) { auto it = m_graph.find(spec); @@ -414,16 +425,52 @@ namespace vcpkg::Dependencies static MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, - GraphPlan& graph_plan); + GraphPlan& graph_plan, + const std::unordered_set& prevent_default_features = {}); static void mark_minus(Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan); - MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) + MarkPlusResult mark_plus(const std::string& feature, + Cluster& cluster, + ClusterGraph& graph, + GraphPlan& graph_plan, + const std::unordered_set& prevent_default_features) { if (feature.empty()) { - // Indicates that core was not specified in the reference - return mark_plus("core", cluster, graph, graph_plan); + if (prevent_default_features.find(cluster.spec.name()) == prevent_default_features.end()) + { + // Indicates that core was not specified in the reference + + // Add default features for this package, if this is the "core" feature and we + // are not supposed to prevent default features for this package + if (auto scf = cluster.source_control_file.value_or(nullptr)) + { + for (auto&& default_feature : scf->core_paragraph.get()->default_features) + { + auto res = mark_plus(default_feature, cluster, graph, graph_plan, prevent_default_features); + if (res != MarkPlusResult::SUCCESS) + { + return res; + } + } + + // "core" is always an implicit default feature. In case we did not add it as + // a dependency above (e.g. no default features), add it here. + auto res = mark_plus("core", cluster, graph, graph_plan, prevent_default_features); + if (res != MarkPlusResult::SUCCESS) + { + return res; + } + } + + return MarkPlusResult::SUCCESS; + } + else + { + // Skip adding the default features, as explicitly told not to. + return MarkPlusResult::SUCCESS; + } } auto it = cluster.edges.find(feature); @@ -454,16 +501,21 @@ namespace vcpkg::Dependencies if (feature != "core") { // All features implicitly depend on core - auto res = mark_plus("core", cluster, graph, graph_plan); + auto res = mark_plus("core", cluster, graph, graph_plan, prevent_default_features); // Should be impossible for "core" to not exist Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS); } + else + { + // Add the default features of this package. + auto res = mark_plus("", cluster, graph, graph_plan, prevent_default_features); + } for (auto&& depend : cluster.edges[feature].build_edges) { auto& depend_cluster = graph.get(depend.spec()); - auto res = mark_plus(depend.feature(), depend_cluster, graph, graph_plan); + auto res = mark_plus(depend.feature(), depend_cluster, graph, graph_plan, prevent_default_features); Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, @@ -483,6 +535,18 @@ namespace vcpkg::Dependencies if (cluster.will_remove) return; cluster.will_remove = true; + std::unordered_set prevent_default_features; + + if (cluster.request_type == RequestType::USER_REQUESTED) + { + // Do not install default features for packages which the user + // installed explicitly. New default features for dependent + // clusters should still be upgraded. + prevent_default_features.insert(cluster.spec.name()); + + // For dependent packages this is handles through the recursion + } + graph_plan.remove_graph.add_vertex({&cluster}); for (auto&& pair : cluster.edges) { @@ -498,7 +562,7 @@ namespace vcpkg::Dependencies cluster.transient_uninstalled = true; for (auto&& original_feature : cluster.original_features) { - auto res = mark_plus(original_feature, cluster, graph, graph_plan); + auto res = mark_plus(original_feature, cluster, graph, graph_plan, prevent_default_features); if (res != MarkPlusResult::SUCCESS) { System::println(System::Color::warning, @@ -506,19 +570,54 @@ namespace vcpkg::Dependencies FeatureSpec{cluster.spec, original_feature}); } } + + // Check if any default features have been added + if (auto scf = cluster.source_control_file.value_or(nullptr)) + { + auto& previous_df = cluster.installed_package.core->package.default_features; + for (auto&& default_feature : scf->core_paragraph->default_features) + { + if (std::find(previous_df.begin(), previous_df.end(), default_feature) == previous_df.end()) + { + // this is a new default feature, mark it for installation + auto res = mark_plus(default_feature, cluster, graph, graph_plan); + if (res != MarkPlusResult::SUCCESS) + { + System::println(System::Color::warning, + "Warning: could not install new default feature %s", + FeatureSpec{cluster.spec, default_feature}); + } + } + } + } } + /// Figure out which actions are required to install features specifications in `specs`. + /// Contains the ports of the current environment. + /// Feature specifications to resolve dependencies for. + /// Status of installed packages in the current environment. std::vector create_feature_install_plan(const PortFileProvider& provider, const std::vector& specs, const StatusParagraphs& status_db) { + std::unordered_set prevent_default_features; + for (auto&& spec : specs) + { + // When "core" is explicitly listed, default features should not be installed. + if (spec.feature() == "core") prevent_default_features.insert(spec.name()); + } + PackageGraph pgraph(provider, status_db); for (auto&& spec : specs) - pgraph.install(spec); + pgraph.install(spec, prevent_default_features); return pgraph.serialize(); } + /// Figure out which actions are required to install features specifications in `specs`. + /// Map of all source files in the current environment. + /// Feature specifications to resolve dependencies for. + /// Status of installed packages in the current environment. std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db) @@ -527,7 +626,12 @@ namespace vcpkg::Dependencies return create_feature_install_plan(provider, specs, status_db); } - void PackageGraph::install(const FeatureSpec& spec) const + /// + /// List of package names for which default features should not be installed instead of the core package (e.g. if + /// the user is currently installing specific features of that package). + /// + void PackageGraph::install(const FeatureSpec& spec, + const std::unordered_set& prevent_default_features) const { Cluster& spec_cluster = m_graph->get(spec.spec()); spec_cluster.request_type = RequestType::USER_REQUESTED; @@ -537,13 +641,14 @@ namespace vcpkg::Dependencies { for (auto&& feature : p_scf->feature_paragraphs) { - auto res = mark_plus(feature->name, spec_cluster, *m_graph, *m_graph_plan); + auto res = + mark_plus(feature->name, spec_cluster, *m_graph, *m_graph_plan, prevent_default_features); Checks::check_exit( VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); } - auto res = mark_plus("core", spec_cluster, *m_graph, *m_graph_plan); + auto res = mark_plus("core", spec_cluster, *m_graph, *m_graph_plan, prevent_default_features); Checks::check_exit( VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); @@ -556,7 +661,7 @@ namespace vcpkg::Dependencies } else { - auto res = mark_plus(spec.feature(), spec_cluster, *m_graph, *m_graph_plan); + auto res = mark_plus(spec.feature(), spec_cluster, *m_graph, *m_graph_plan, prevent_default_features); Checks::check_exit( VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 081063633..595945d39 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -513,6 +513,11 @@ namespace vcpkg::Install } } + /// + /// + /// Run "install" command. + /// + /// void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { // input sanitization -- cgit v1.2.3 From bfac7b57161168b8b54ea159bbf2c88794098c1c Mon Sep 17 00:00:00 2001 From: Fujii Hironori Date: Fri, 16 Feb 2018 21:25:12 +0900 Subject: [vcpkg] http_proxy and https_proxy should be lowercase (#2815) Pacman of Msys understands only lowercase environment variables http_proxy and https_proxy. --- toolsrc/src/vcpkg/base/system.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 84721bf6e..f71fd8445 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -175,8 +175,8 @@ namespace vcpkg::System L"USERPROFILE", L"windir", // Enables proxy information to be passed to Curl, the underlying download library in cmake.exe - L"HTTP_PROXY", - L"HTTPS_PROXY", + L"http_proxy", + L"https_proxy", // Enables find_package(CUDA) in CMake L"CUDA_PATH", // Environmental variable generated automatically by CUDA after installation -- cgit v1.2.3 From 16faed678540be37ea623fa7f0f2c2e7c442b147 Mon Sep 17 00:00:00 2001 From: Squareys Date: Fri, 16 Feb 2018 14:27:04 +0100 Subject: [vcpkg] Add find/find_installed/is_installed for FeatureSpec Signed-off-by: Squareys --- toolsrc/src/tests.statusparagraphs.cpp | 33 +++++++++++++++++++++++++++++++++ toolsrc/src/vcpkg/statusparagraphs.cpp | 19 +++++++++++++++++++ 2 files changed, 52 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.statusparagraphs.cpp b/toolsrc/src/tests.statusparagraphs.cpp index 0d5324a8c..fa0d54fac 100644 --- a/toolsrc/src/tests.statusparagraphs.cpp +++ b/toolsrc/src/tests.statusparagraphs.cpp @@ -77,6 +77,39 @@ Status: purge ok not-installed auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); Assert::IsTrue(it != status_db.end()); + + // Feature "openssl" is not installed and should not be found + auto it1 = status_db.find_installed({unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS), "openssl"}); + Assert::IsTrue(it1 == status_db.end()); + } + + TEST_METHOD(find_for_feature_packages) + { + auto pghs = parse_paragraphs(R"( +Package: ffmpeg +Version: 3.3.3 +Architecture: x64-windows +Multi-Arch: same +Description: +Status: install ok installed + +Package: ffmpeg +Feature: openssl +Depends: openssl +Architecture: x64-windows +Multi-Arch: same +Description: +Status: install ok installed +)"); + Assert::IsTrue(!!pghs); + if (!pghs) return; + + StatusParagraphs status_db(Util::fmap( + *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique(std::move(rpgh)); })); + + // Feature "openssl" is installed and should therefore be found + auto it = status_db.find_installed({unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS), "openssl"}); + Assert::IsTrue(it != status_db.end()); } }; } diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp index 475f86279..b23d8b884 100644 --- a/toolsrc/src/vcpkg/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -83,12 +83,31 @@ namespace vcpkg } } + StatusParagraphs::const_iterator StatusParagraphs::find_installed(const FeatureSpec& spec) const + { + auto it = find(spec); + if (it != end() && (*it)->is_installed()) + { + return it; + } + else + { + return end(); + } + } + bool vcpkg::StatusParagraphs::is_installed(const PackageSpec& spec) const { auto it = find(spec); return it != end() && (*it)->is_installed(); } + bool vcpkg::StatusParagraphs::is_installed(const FeatureSpec& spec) const + { + auto it = find(spec); + return it != end() && (*it)->is_installed(); + } + StatusParagraphs::iterator StatusParagraphs::insert(std::unique_ptr pgh) { Checks::check_exit(VCPKG_LINE_INFO, pgh != nullptr, "Inserted null paragraph"); -- cgit v1.2.3 From f1ce125a28c98fd5a87bf509ac965b06c219d8f3 Mon Sep 17 00:00:00 2001 From: Squareys Date: Fri, 16 Feb 2018 14:27:32 +0100 Subject: [vcpkg] Fix build command for packages that depend of features Signed-off-by: Squareys --- toolsrc/src/vcpkg/build.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 7de276f4f..cc376c773 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -267,13 +267,16 @@ namespace vcpkg::Build const Triplet& triplet = config.triplet; { - std::vector missing_specs; + std::vector missing_specs; for (auto&& dep : filter_dependencies(config.scf.core_paragraph->depends, triplet)) { - auto dep_spec = PackageSpec::from_name_and_triplet(dep, triplet).value_or_exit(VCPKG_LINE_INFO); - if (!status_db.is_installed(dep_spec)) + auto dep_specs = FeatureSpec::from_strings_and_triplet({dep}, triplet); + for (auto&& feature : dep_specs) { - missing_specs.push_back(std::move(dep_spec)); + if (!status_db.is_installed(feature)) + { + missing_specs.push_back(std::move(feature)); + } } } // Fail the build if any dependencies were missing @@ -600,7 +603,7 @@ namespace vcpkg::Build : code(code), binary_control_file(std::move(bcf)) { } - ExtendedBuildResult::ExtendedBuildResult(BuildResult code, std::vector&& unmet_deps) + ExtendedBuildResult::ExtendedBuildResult(BuildResult code, std::vector&& unmet_deps) : code(code), unmet_dependencies(std::move(unmet_deps)) { } -- cgit v1.2.3 From 72bc3647b61ad3e8df8d1e620daa7d919b5241d6 Mon Sep 17 00:00:00 2001 From: Jonathan Hale Date: Fri, 16 Feb 2018 23:50:36 +0100 Subject: [vcpkg] Fix bug with missing dependencies introduced in #2697 (#2819) When a package dependency was not found (has no source control file), install would exit with "Value was null" when trying to install its default features, as the dependency would be marked erroneously as found in this case. Signed-off-by: Squareys --- toolsrc/src/vcpkg/dependencies.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 307c779c8..fedda56ab 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -454,14 +454,14 @@ namespace vcpkg::Dependencies return res; } } + } - // "core" is always an implicit default feature. In case we did not add it as - // a dependency above (e.g. no default features), add it here. - auto res = mark_plus("core", cluster, graph, graph_plan, prevent_default_features); - if (res != MarkPlusResult::SUCCESS) - { - return res; - } + // "core" is always an implicit default feature. In case we did not add it as + // a dependency above (e.g. no default features), add it here. + auto res = mark_plus("core", cluster, graph, graph_plan, prevent_default_features); + if (res != MarkPlusResult::SUCCESS) + { + return res; } return MarkPlusResult::SUCCESS; -- cgit v1.2.3 From 452c8ba1ff4c06e5cf7b2f2c4ff449eaefb83f79 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 16 Feb 2018 15:40:22 -0800 Subject: [vcpkg] Avoid using s::status_known() -- it does not do what you think it does --- toolsrc/src/vcpkg/install.cpp | 61 ++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 32 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 595945d39..631b16c59 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -69,7 +69,7 @@ namespace vcpkg::Install continue; } - const std::string filename = file.filename().generic_string(); + const std::string filename = file.filename().u8string(); if (fs::is_regular_file(status) && (Strings::case_insensitive_ascii_equals(filename.c_str(), "CONTROL") || Strings::case_insensitive_ascii_equals(filename.c_str(), "BUILD_INFO"))) { @@ -80,44 +80,41 @@ namespace vcpkg::Install const std::string suffix = file.generic_u8string().substr(prefix_length + 1); const fs::path target = destination / suffix; - if (fs::is_directory(status)) + switch (status.type()) { - fs.create_directory(target, ec); - if (ec) + case fs::file_type::directory: { - System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); - } - - // Trailing backslash for directories - output.push_back(Strings::format(R"(%s/%s/)", destination_subdirectory, suffix)); - continue; - } + fs.create_directory(target, ec); + if (ec) + { + System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); + } - if (fs::is_regular_file(status)) - { - if (fs.exists(target)) - { - System::println(System::Color::warning, - "File %s was already present and will be overwritten", - target.u8string(), - ec.message()); + // Trailing backslash for directories + output.push_back(Strings::format(R"(%s/%s/)", destination_subdirectory, suffix)); + break; } - fs.copy_file(file, target, fs::copy_options::overwrite_existing, ec); - if (ec) + case fs::file_type::regular: { - System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); + if (fs.exists(target)) + { + System::println(System::Color::warning, + "File %s was already present and will be overwritten", + target.u8string(), + ec.message()); + } + fs.copy_file(file, target, fs::copy_options::overwrite_existing, ec); + if (ec) + { + System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); + } + output.push_back(Strings::format(R"(%s/%s)", destination_subdirectory, suffix)); + break; } - output.push_back(Strings::format(R"(%s/%s)", destination_subdirectory, suffix)); - continue; - } - - if (!fs::status_known(status)) - { - System::println(System::Color::error, "failed: %s: unknown status", file.u8string()); - continue; + default: + System::println(System::Color::error, "failed: %s: cannot handle file type", file.u8string()); + break; } - - System::println(System::Color::error, "failed: %s: cannot handle file type", file.u8string()); } std::sort(output.begin(), output.end()); -- cgit v1.2.3 From 12f19c7a30e14a89c0bac9279bb8bcda64158496 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 19 Feb 2018 07:11:30 -0800 Subject: [vcpkg] Remove create_install_plan in favor of create_feature_install_plan --- toolsrc/src/tests.plan.cpp | 38 ++++++++++++++++++++------------------ toolsrc/src/vcpkg/commands.ci.cpp | 38 +++++++++++++++----------------------- toolsrc/src/vcpkg/dependencies.cpp | 27 --------------------------- 3 files changed, 35 insertions(+), 68 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index a4c628bf6..546e20b0d 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -111,13 +111,13 @@ namespace UnitTest1 auto spec_c = spec_map.emplace("c"); Dependencies::MapPortFileProvider map_port(spec_map.map); - auto install_plan = - Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = Dependencies::create_feature_install_plan( + map_port, {FeatureSpec{spec_a, ""}}, StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(3), install_plan.size()); - Assert::AreEqual("c", install_plan[0].spec.name().c_str()); - Assert::AreEqual("b", install_plan[1].spec.name().c_str()); - Assert::AreEqual("a", install_plan[2].spec.name().c_str()); + Assert::AreEqual("c", install_plan[0].spec().name().c_str()); + Assert::AreEqual("b", install_plan[1].spec().name().c_str()); + Assert::AreEqual("a", install_plan[2].spec().name().c_str()); } TEST_METHOD(multiple_install_scheme) @@ -135,12 +135,14 @@ namespace UnitTest1 auto spec_h = spec_map.emplace("h"); Dependencies::MapPortFileProvider map_port(spec_map.map); - auto install_plan = Dependencies::create_install_plan( - map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = Dependencies::create_feature_install_plan( + map_port, + {FeatureSpec{spec_a, ""}, FeatureSpec{spec_b, ""}, FeatureSpec{spec_c, ""}}, + StatusParagraphs(std::move(status_paragraphs))); auto iterator_pos = [&](const PackageSpec& spec) -> int { auto it = std::find_if( - install_plan.begin(), install_plan.end(), [&](auto& action) { return action.spec == spec; }); + install_plan.begin(), install_plan.end(), [&](auto& action) { return action.spec() == spec; }); Assert::IsTrue(it != install_plan.end()); return (int)(it - install_plan.begin()); }; @@ -228,18 +230,18 @@ namespace UnitTest1 auto spec_k = spec_map.emplace("k"); Dependencies::MapPortFileProvider map_port(spec_map.map); - auto install_plan = - Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = Dependencies::create_feature_install_plan( + map_port, {FeatureSpec{spec_a, ""}}, StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(8), install_plan.size()); - Assert::AreEqual("h", install_plan[0].spec.name().c_str()); - Assert::AreEqual("g", install_plan[1].spec.name().c_str()); - Assert::AreEqual("f", install_plan[2].spec.name().c_str()); - Assert::AreEqual("e", install_plan[3].spec.name().c_str()); - Assert::AreEqual("d", install_plan[4].spec.name().c_str()); - Assert::AreEqual("c", install_plan[5].spec.name().c_str()); - Assert::AreEqual("b", install_plan[6].spec.name().c_str()); - Assert::AreEqual("a", install_plan[7].spec.name().c_str()); + Assert::AreEqual("h", install_plan[0].spec().name().c_str()); + Assert::AreEqual("g", install_plan[1].spec().name().c_str()); + Assert::AreEqual("f", install_plan[2].spec().name().c_str()); + Assert::AreEqual("e", install_plan[3].spec().name().c_str()); + Assert::AreEqual("d", install_plan[4].spec().name().c_str()); + Assert::AreEqual("c", install_plan[5].spec().name().c_str()); + Assert::AreEqual("b", install_plan[6].spec().name().c_str()); + Assert::AreEqual("a", install_plan[7].spec().name().c_str()); } TEST_METHOD(basic_feature_test_1) diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 4636a5738..7672755ba 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -20,27 +20,15 @@ namespace vcpkg::Commands::CI static Install::InstallSummary run_ci_on_triplet(const Triplet& triplet, const VcpkgPaths& paths, - const std::vector& ports, - const std::set& exclusions_set) + const std::vector& ports) { Input::check_triplet(triplet, paths); - - const std::vector specs = PackageSpec::to_package_specs(ports, triplet); + std::vector specs = PackageSpec::to_package_specs(ports, triplet); + auto featurespecs = Util::fmap(specs, [](auto& spec) { return FeatureSpec(spec, ""); }); StatusParagraphs status_db = database_load_check(paths); const auto& paths_port_file = Dependencies::PathsPortFileProvider(paths); - std::vector install_plan = - Dependencies::create_install_plan(paths_port_file, specs, status_db); - - for (InstallPlanAction& plan : install_plan) - { - if (Util::Sets::contains(exclusions_set, plan.spec.name())) - { - plan.plan_type = InstallPlanType::EXCLUDED; - } - } - - Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); + auto action_plan = Dependencies::create_feature_install_plan(paths_port_file, featurespecs, status_db); const Build::BuildPackageOptions install_plan_options = { Build::UseHeadVersion::NO, @@ -48,11 +36,13 @@ namespace vcpkg::Commands::CI Build::CleanBuildtrees::YES, }; - const std::vector action_plan = - Util::fmap(install_plan, [&install_plan_options](InstallPlanAction& install_action) { - install_action.build_options = install_plan_options; - return Dependencies::AnyAction(std::move(install_action)); - }); + for (auto&& action : action_plan) + { + if (auto p = action.install_action.get()) + { + p->build_options = install_plan_options; + } + } return Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db); } @@ -102,11 +92,13 @@ namespace vcpkg::Commands::CI triplets.push_back(default_triplet); } - const std::vector ports = Install::get_all_port_names(paths); + std::vector ports = Install::get_all_port_names(paths); + Util::erase_remove_if(ports, [&](auto&& port) { return Util::Sets::contains(exclusions_set, port); }); + std::vector results; for (const Triplet& triplet : triplets) { - Install::InstallSummary summary = run_ci_on_triplet(triplet, paths, ports, exclusions_set); + Install::InstallSummary summary = run_ci_on_triplet(triplet, paths, ports); results.push_back({triplet, std::move(summary)}); } diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index fedda56ab..793951ab5 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -280,33 +280,6 @@ namespace vcpkg::Dependencies return nullopt; } - std::vector create_install_plan(const PortFileProvider& port_file_provider, - const std::vector& specs, - const StatusParagraphs& status_db) - { - auto fspecs = Util::fmap(specs, [](const PackageSpec& spec) { return FeatureSpec(spec, ""); }); - auto plan = create_feature_install_plan(port_file_provider, fspecs, status_db); - - std::vector ret; - ret.reserve(plan.size()); - - for (auto&& action : plan) - { - if (auto p_install = action.install_action.get()) - { - ret.push_back(std::move(*p_install)); - } - else - { - Checks::exit_with_message(VCPKG_LINE_INFO, - "The installation plan requires feature packages support. Please re-run the " - "command with --featurepackages."); - } - } - - return ret; - } - std::vector create_remove_plan(const std::vector& specs, const StatusParagraphs& status_db) { -- cgit v1.2.3 From adb0930bc54dbff26acf131971199c3f57bdd0fb Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 20 Feb 2018 18:02:00 -0800 Subject: [vcpkg-metrics] Adjust reporting of build times --- toolsrc/src/vcpkg/build.cpp | 3 ++- toolsrc/src/vcpkg/metrics.cpp | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index cc376c773..7d249bd0c 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -339,7 +339,8 @@ namespace vcpkg::Build { auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_metric("buildtimeus-" + spec_string, buildtimeus); + locked_metrics->track_buildtime(spec.to_string() + ":[" + Strings::join(",", config.feature_list) + "]", + buildtimeus); if (return_code != 0) { locked_metrics->track_property("error", "build failed"); diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index cdb21d260..1f9ddde38 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -150,6 +150,9 @@ namespace vcpkg::Metrics std::string properties; std::string measurements; + std::vector buildtime_names; + std::vector buildtime_times; + void track_property(const std::string& name, const std::string& value) { if (properties.size() != 0) properties.push_back(','); @@ -166,8 +169,23 @@ namespace vcpkg::Metrics measurements.append(std::to_string(value)); } + void track_buildtime(const std::string& name, double value) + { + buildtime_names.push_back(name); + buildtime_times.push_back(std::to_string(value)); + } + std::string format_event_data_template() const { + auto props_plus_buildtimes = properties; + if (buildtime_names.size() > 0) + { + if (props_plus_buildtimes.size() > 0) props_plus_buildtimes.push_back(','); + props_plus_buildtimes.append(Strings::format(R"("buildnames": [%s], "buildtimes": [%s])", + Strings::join(",", buildtime_names, to_json_string), + Strings::join(",", buildtime_times))); + } + const std::string& session_id = get_session_id(); return Strings::format(R"([{ "ver": 1, @@ -199,7 +217,7 @@ namespace vcpkg::Metrics session_id, user_id, user_timestamp, - properties, + props_plus_buildtimes, measurements); } }; @@ -274,6 +292,11 @@ namespace vcpkg::Metrics void Metrics::track_metric(const std::string& name, double value) { g_metricmessage.track_metric(name, value); } + void Metrics::track_buildtime(const std::string& name, double value) + { + g_metricmessage.track_buildtime(name, value); + } + void Metrics::track_property(const std::string& name, const std::string& value) { g_metricmessage.track_property(name, value); -- cgit v1.2.3 From 8a4afe16193f274eb4d60357d81b8827ed055fb8 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 20 Feb 2018 17:58:21 -0800 Subject: Update git to 2.16.2 --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 06e0c01ab..d574b7c4d 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -167,7 +167,7 @@ namespace vcpkg fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { #if defined(_WIN32) - static constexpr std::array EXPECTED_VERSION = {2, 15, 0}; + static constexpr std::array EXPECTED_VERSION = {2, 16, 2}; #else static constexpr std::array EXPECTED_VERSION = {2, 7, 4}; #endif @@ -175,7 +175,7 @@ namespace vcpkg const std::vector from_path = Files::find_from_PATH("git"); - const fs::path downloaded_copy = downloads_folder / "MinGit-2.15.0-32-bit" / "cmd" / "git.exe"; + const fs::path downloaded_copy = downloads_folder / "MinGit-2.16.2-32-bit" / "cmd" / "git.exe"; std::vector candidate_paths; #if defined(_WIN32) candidate_paths.push_back(downloaded_copy); -- cgit v1.2.3 From 494f3002bfdf80c363ae51ca426cabc231c73339 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 21 Feb 2018 15:32:20 -0800 Subject: Add internal option to clean packages\ after the build --- toolsrc/src/vcpkg/build.cpp | 18 +++++++++++++++--- toolsrc/src/vcpkg/commands.ci.cpp | 11 +++++------ toolsrc/src/vcpkg/commands.upgrade.cpp | 9 ++++----- toolsrc/src/vcpkg/install.cpp | 2 +- 4 files changed, 25 insertions(+), 15 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 7d249bd0c..f6c995f2a 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -61,8 +61,10 @@ namespace vcpkg::Build::Command spec.name()); const StatusParagraphs status_db = database_load_check(paths); - const Build::BuildPackageOptions build_package_options{ - Build::UseHeadVersion::NO, Build::AllowDownloads::YES, Build::CleanBuildtrees::NO}; + const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, + Build::AllowDownloads::YES, + Build::CleanBuildtrees::NO, + Build::CleanPackages::NO}; const std::unordered_set features_as_set(full_spec.features.begin(), full_spec.features.end()); @@ -385,7 +387,7 @@ namespace vcpkg::Build if (config.build_package_options.clean_buildtrees == CleanBuildtrees::YES) { auto& fs = paths.get_filesystem(); - auto buildtrees_dir = paths.buildtrees / config.scf.core_paragraph->name; + const fs::path buildtrees_dir = paths.buildtrees / config.scf.core_paragraph->name; auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir); for (auto&& file : buildtree_files) { @@ -397,6 +399,16 @@ namespace vcpkg::Build } } + if (config.build_package_options.clean_packages == CleanPackages::YES) + { + auto& fs = paths.get_filesystem(); + const PackageSpec spec = PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, config.triplet) + .value_or_exit(VCPKG_LINE_INFO); + const fs::path package_dir = paths.package_dir(spec); + std::error_code ec; + fs.remove_all(package_dir, ec); + } + return result; } diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 7672755ba..313582b7b 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -24,17 +24,16 @@ namespace vcpkg::Commands::CI { Input::check_triplet(triplet, paths); std::vector specs = PackageSpec::to_package_specs(ports, triplet); - auto featurespecs = Util::fmap(specs, [](auto& spec) { return FeatureSpec(spec, ""); }); + const auto featurespecs = Util::fmap(specs, [](auto& spec) { return FeatureSpec(spec, ""); }); StatusParagraphs status_db = database_load_check(paths); const auto& paths_port_file = Dependencies::PathsPortFileProvider(paths); auto action_plan = Dependencies::create_feature_install_plan(paths_port_file, featurespecs, status_db); - const Build::BuildPackageOptions install_plan_options = { - Build::UseHeadVersion::NO, - Build::AllowDownloads::YES, - Build::CleanBuildtrees::YES, - }; + const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, + Build::AllowDownloads::YES, + Build::CleanBuildtrees::YES, + Build::CleanPackages::YES}; for (auto&& action : action_plan) { diff --git a/toolsrc/src/vcpkg/commands.upgrade.cpp b/toolsrc/src/vcpkg/commands.upgrade.cpp index bb26dc735..c5b48f2a2 100644 --- a/toolsrc/src/vcpkg/commands.upgrade.cpp +++ b/toolsrc/src/vcpkg/commands.upgrade.cpp @@ -141,11 +141,10 @@ namespace vcpkg::Commands::Upgrade Checks::check_exit(VCPKG_LINE_INFO, !plan.empty()); - const Build::BuildPackageOptions install_plan_options = { - Build::UseHeadVersion::NO, - Build::AllowDownloads::YES, - Build::CleanBuildtrees::NO, - }; + const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, + Build::AllowDownloads::YES, + Build::CleanBuildtrees::NO, + Build::CleanPackages::NO}; // Set build settings for all install actions for (auto&& action : plan) diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 631b16c59..d032f77d8 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -547,7 +547,7 @@ namespace vcpkg::Install Util::Enum::to_enum(use_head_version), Util::Enum::to_enum(!no_downloads), Build::CleanBuildtrees::NO, - }; + Build::CleanPackages::NO}; // Note: action_plan will hold raw pointers to SourceControlFiles from this map std::vector action_plan; -- cgit v1.2.3 From e02c9e535493842a26b4426ce602c60f90ace671 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 21 Feb 2018 19:57:14 -0800 Subject: [CI] Fix too early deletion of files --- toolsrc/src/vcpkg/build.cpp | 10 ---------- toolsrc/src/vcpkg/install.cpp | 9 +++++++++ 2 files changed, 9 insertions(+), 10 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index f6c995f2a..c169a778e 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -399,16 +399,6 @@ namespace vcpkg::Build } } - if (config.build_package_options.clean_packages == CleanPackages::YES) - { - auto& fs = paths.get_filesystem(); - const PackageSpec spec = PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, config.triplet) - .value_or_exit(VCPKG_LINE_INFO); - const fs::path package_dir = paths.package_dir(spec); - std::error_code ec; - fs.remove_all(package_dir, ec); - } - return result; } diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index d032f77d8..46c7c53b8 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -308,6 +308,15 @@ namespace vcpkg::Install auto bcf = std::make_unique( Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO)); auto code = aux_install(display_name_with_features, *bcf); + + if (action.build_options.clean_packages == Build::CleanPackages::YES) + { + auto& fs = paths.get_filesystem(); + const fs::path package_dir = paths.package_dir(action.spec); + std::error_code ec; + fs.remove_all(package_dir, ec); + } + return {code, std::move(bcf)}; } -- cgit v1.2.3 From 65e241cf8b47a07b85efae85bac14e723864dccb Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 21 Feb 2018 22:18:15 -0800 Subject: [vcpkg] Add non-throwing implementation of write_contents() --- toolsrc/src/vcpkg/base/checks.cpp | 4 ++++ toolsrc/src/vcpkg/base/files.cpp | 21 +++++++++++++++------ toolsrc/src/vcpkg/metrics.cpp | 5 +++-- toolsrc/src/vcpkg/userconfig.cpp | 3 ++- 4 files changed, 24 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp index 23f2cc630..2977a1d8b 100644 --- a/toolsrc/src/vcpkg/base/checks.cpp +++ b/toolsrc/src/vcpkg/base/checks.cpp @@ -10,6 +10,10 @@ namespace vcpkg::Checks { [[noreturn]] static void cleanup_and_exit(const int exit_code) { + static std::atomic have_entered = false; + if (have_entered) std::terminate(); + have_entered = true; + const auto elapsed_us = GlobalState::timer.lock()->microseconds(); auto metrics = Metrics::g_metrics.lock(); diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 060a14da3..95ae0fd33 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -164,21 +164,30 @@ namespace vcpkg::Files { return fs::stdfs::status(path, ec); } - virtual void write_contents(const fs::path& file_path, const std::string& data) override + virtual void write_contents(const fs::path& file_path, const std::string& data, std::error_code& ec) override { + ec = std::error_code(); + FILE* f = nullptr; #if defined(_WIN32) - auto ec = _wfopen_s(&f, file_path.native().c_str(), L"wb"); + auto err = _wfopen_s(&f, file_path.native().c_str(), L"wb"); #else f = fopen(file_path.native().c_str(), "wb"); - int ec = f != nullptr ? 0 : 1; + int err = f != nullptr ? 0 : 1; #endif - Checks::check_exit( - VCPKG_LINE_INFO, ec == 0, "Error: Could not open file for writing: %s", file_path.u8string().c_str()); + if (err != 0) + { + ec.assign(err, std::system_category()); + return; + } + auto count = fwrite(data.data(), sizeof(data[0]), data.size(), f); fclose(f); - Checks::check_exit(VCPKG_LINE_INFO, count == data.size()); + if (count != data.size()) + { + ec = std::make_error_code(std::errc::no_space_on_device); + } } }; diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 1f9ddde38..1a322e99c 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -427,8 +427,9 @@ namespace vcpkg::Metrics } const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); - fs.write_contents(vcpkg_metrics_txt_path, payload); - + std::error_code ec; + fs.write_contents(vcpkg_metrics_txt_path, payload, ec); + if (ec) return; const std::string cmd_line = Strings::format("start \"vcpkgmetricsuploader.exe\" \"%s\" \"%s\"", temp_folder_path_exe.u8string(), vcpkg_metrics_txt_path.u8string()); diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp index 906594691..c7c57ce26 100644 --- a/toolsrc/src/vcpkg/userconfig.cpp +++ b/toolsrc/src/vcpkg/userconfig.cpp @@ -78,7 +78,8 @@ namespace vcpkg user_id, user_time, user_mac, - last_completed_survey)); + last_completed_survey), + ec); } catch (...) { -- cgit v1.2.3 From 0ef0300b8eefcdfe119e0bbaa3ce7b0f8c30ee4c Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 19 Feb 2018 12:20:16 -0800 Subject: [vcpkg] Enable metrics on linux --- toolsrc/src/vcpkg.cpp | 6 ++- toolsrc/src/vcpkg/base/checks.cpp | 2 +- toolsrc/src/vcpkg/base/files.cpp | 2 +- toolsrc/src/vcpkg/base/strings.cpp | 10 +++++ toolsrc/src/vcpkg/commands.contact.cpp | 9 ++-- toolsrc/src/vcpkg/commands.version.cpp | 4 ++ toolsrc/src/vcpkg/metrics.cpp | 75 ++++++++++++++++++++++------------ toolsrc/src/vcpkg/userconfig.cpp | 22 ++++++---- 8 files changed, 90 insertions(+), 40 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 9f29dcdd2..adb32c723 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -171,7 +171,6 @@ static void inner(const VcpkgCmdArguments& args) static void load_config() { -#if defined(_WIN32) auto& fs = Files::get_real_filesystem(); auto config = UserConfig::try_read_data(fs); @@ -185,16 +184,20 @@ static void load_config() write_config = true; } +#if defined(_WIN32) if (config.user_mac.empty()) { config.user_mac = Metrics::get_MAC_user(); write_config = true; } +#endif { auto locked_metrics = Metrics::g_metrics.lock(); locked_metrics->set_user_information(config.user_id, config.user_time); +#if defined(_WIN32) locked_metrics->track_property("user_mac", config.user_mac); +#endif } if (config.last_completed_survey.empty()) @@ -208,7 +211,6 @@ static void load_config() { config.try_write_data(fs); } -#endif } static std::string trim_path_from_command_line(const std::string& full_command_line) diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp index 2977a1d8b..1b3ed5ec9 100644 --- a/toolsrc/src/vcpkg/base/checks.cpp +++ b/toolsrc/src/vcpkg/base/checks.cpp @@ -31,7 +31,7 @@ namespace vcpkg::Checks #if defined(_WIN32) ::TerminateProcess(::GetCurrentProcess(), exit_code); #else - ::exit(exit_code); + std::exit(exit_code); #endif } diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 95ae0fd33..b59104a59 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -166,7 +166,7 @@ namespace vcpkg::Files } virtual void write_contents(const fs::path& file_path, const std::string& data, std::error_code& ec) override { - ec = std::error_code(); + ec.clear(); FILE* f = nullptr; #if defined(_WIN32) diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index 27cfcbe71..d912734e3 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -74,6 +74,16 @@ namespace vcpkg::Strings #endif } + std::string escape_string(const CStringView& s, char char_to_escape, char escape_char) + { + std::string ret = s.c_str(); + // Replace '\' with '\\' or '`' with '``' + ret = Strings::replace_all(std::move(ret), {escape_char}, {escape_char, escape_char}); + // Replace '"' with '\"' or '`"' + ret = Strings::replace_all(std::move(ret), {char_to_escape}, {escape_char, char_to_escape}); + return ret; + } + std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern) { const std::string pattern_as_lower_case(ascii_to_lowercase(pattern)); diff --git a/toolsrc/src/vcpkg/commands.contact.cpp b/toolsrc/src/vcpkg/commands.contact.cpp index 8063fe317..ffed07557 100644 --- a/toolsrc/src/vcpkg/commands.contact.cpp +++ b/toolsrc/src/vcpkg/commands.contact.cpp @@ -30,7 +30,6 @@ namespace vcpkg::Commands::Contact if (Util::Sets::contains(parsed_args.switches, switches[0].name)) { -#if defined(_WIN32) auto maybe_now = Chrono::CTime::get_current_date_time(); if (auto p_now = maybe_now.get()) { @@ -39,10 +38,14 @@ namespace vcpkg::Commands::Contact config.last_completed_survey = p_now->to_string(); config.try_write_data(fs); } -#endif +#if defined(_WIN32) System::cmd_execute("start https://aka.ms/NPS_vcpkg"); - System::println("Default browser launched to https://aka.ms/NPS_vcpkg, thank you for your feedback!"); + System::println("Default browser launched to https://aka.ms/NPS_vcpkg; thank you for your feedback!"); +#else + System::println( + "Please navigate to https://aka.ms/NPS_vcpkg in your preferred browser. Thank you for your feedback!"); +#endif } else { diff --git a/toolsrc/src/vcpkg/commands.version.cpp b/toolsrc/src/vcpkg/commands.version.cpp index c21e8cafd..ffc5d2c8f 100644 --- a/toolsrc/src/vcpkg/commands.version.cpp +++ b/toolsrc/src/vcpkg/commands.version.cpp @@ -8,7 +8,11 @@ #define STRINGIFY(...) #__VA_ARGS__ #define MACRO_TO_STRING(X) STRINGIFY(X) +#if defined(VCPKG_VERSION) #define VCPKG_VERSION_AS_STRING MACRO_TO_STRING(VCPKG_VERSION) +#else +#define VCPKG_VERSION_AS_STRING "-unknownhash" +#endif namespace vcpkg::Commands::Version { diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 1a322e99c..f81c53583 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -196,8 +196,8 @@ namespace vcpkg::Metrics "iKey": "b4e88960-4393-4dd9-ab8e-97e8fe6d7603", "flags": 0.000000, "tags": { - "ai.device.os": "Windows", - "ai.device.osVersion": "%s", + "ai.device.os": "Other", + "ai.device.osVersion": "%s-%s", "ai.session.id": "%s", "ai.user.id": "%s", "ai.user.accountAcquisitionDate": "%s" @@ -213,6 +213,17 @@ namespace vcpkg::Metrics } }])", timestamp, +#if defined(_WIN32) + "Windows", +#elif defined(__APPLE__) + "OSX", +#elif defined(__linux__) + "Linux", +#elif defined(__unix__) + "Unix", +#elif defined(__unix__) + "Other", +#endif get_os_version_string(), session_id, user_id, @@ -390,50 +401,62 @@ namespace vcpkg::Metrics void Metrics::flush() { -#if defined(_WIN32) const std::string payload = g_metricmessage.format_event_data_template(); if (g_should_print_metrics) std::cerr << payload << "\n"; if (!g_should_send_metrics) return; - // upload(payload); - +#if defined(_WIN32) wchar_t temp_folder[MAX_PATH]; GetTempPathW(MAX_PATH, temp_folder); const fs::path temp_folder_path = fs::path(temp_folder) / "vcpkg"; const fs::path temp_folder_path_exe = temp_folder_path / Strings::format("vcpkgmetricsuploader-%s.exe", Commands::Version::base_version()); +#endif auto& fs = Files::get_real_filesystem(); - if (true) - { - const fs::path exe_path = [&fs]() -> fs::path { - auto vcpkgdir = System::get_exe_path_of_current_process().parent_path(); - auto path = vcpkgdir / "vcpkgmetricsuploader.exe"; - if (fs.exists(path)) return path; - - path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; - if (fs.exists(path)) return path; - - return ""; - }(); - - std::error_code ec; - fs.create_directories(temp_folder_path, ec); - if (ec) return; - fs.copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec); - if (ec) return; - } +#if defined(_WIN32) - const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); + const fs::path exe_path = [&fs]() -> fs::path { + auto vcpkgdir = System::get_exe_path_of_current_process().parent_path(); + auto path = vcpkgdir / "vcpkgmetricsuploader.exe"; + if (fs.exists(path)) return path; + + path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; + if (fs.exists(path)) return path; + + return ""; + }(); + + std::error_code ec; + fs.create_directories(temp_folder_path, ec); + if (ec) return; + fs.copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec); + if (ec) return; +#else + if (!fs.exists("/tmp")) return; + const fs::path temp_folder_path = "/tmp/vcpkg"; std::error_code ec; + fs.create_directory(temp_folder_path, ec); + // ignore error + ec.clear(); +#endif + const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); fs.write_contents(vcpkg_metrics_txt_path, payload, ec); if (ec) return; + +#if defined(_WIN32) const std::string cmd_line = Strings::format("start \"vcpkgmetricsuploader.exe\" \"%s\" \"%s\"", temp_folder_path_exe.u8string(), vcpkg_metrics_txt_path.u8string()); - System::cmd_execute_clean(cmd_line); +#else + auto escaped_path = Strings::escape_string(vcpkg_metrics_txt_path.u8string(), '\'', '\\'); + const std::string cmd_line = Strings::format( + R"((curl "https://dc.services.visualstudio.com/v2/track" -H "Content-Type: application/json" -X POST --data '@%s' >/dev/null 2>&1; rm '%s') &)", + escaped_path, + escaped_path); #endif + System::cmd_execute_clean(cmd_line); } } diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp index c7c57ce26..9db2e5d47 100644 --- a/toolsrc/src/vcpkg/userconfig.cpp +++ b/toolsrc/src/vcpkg/userconfig.cpp @@ -29,13 +29,22 @@ namespace namespace vcpkg { + static fs::path get_config_path() + { +#if defined(_WIN32) + return get_localappdata() / "vcpkg" / "config"; +#else + auto maybe_home = System::get_environment_variable("HOME"); + return fs::path(maybe_home.value_or("/var")) / "vcpkg" / "config"; +#endif + } + UserConfig UserConfig::try_read_data(const Files::Filesystem& fs) { UserConfig ret; -#if defined(_WIN32) try { - auto maybe_pghs = Paragraphs::get_paragraphs(fs, get_localappdata() / "vcpkg" / "config"); + auto maybe_pghs = Paragraphs::get_paragraphs(fs, get_config_path()); if (const auto p_pghs = maybe_pghs.get()) { const auto& pghs = *p_pghs; @@ -58,19 +67,19 @@ namespace vcpkg catch (...) { } -#endif return ret; } void UserConfig::try_write_data(Files::Filesystem& fs) const { -#if defined(_WIN32) try { + auto config_path = get_config_path(); + auto config_dir = config_path.parent_path(); std::error_code ec; - fs.create_directory(get_localappdata() / "vcpkg", ec); - fs.write_contents(get_localappdata() / "vcpkg" / "config", + fs.create_directory(config_dir, ec); + fs.write_contents(config_path, Strings::format("User-Id: %s\n" "User-Since: %s\n" "Mac-Hash: %s\n" @@ -84,6 +93,5 @@ namespace vcpkg catch (...) { } -#endif } } -- cgit v1.2.3 From fe41bfecd6bee02d16347802436a72e12b244d6d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 22 Feb 2018 00:10:25 -0800 Subject: [vcpkg] Fix previous commit's typo --- toolsrc/src/vcpkg/metrics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index f81c53583..d49cadbe2 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -221,7 +221,7 @@ namespace vcpkg::Metrics "Linux", #elif defined(__unix__) "Unix", -#elif defined(__unix__) +#else "Other", #endif get_os_version_string(), -- cgit v1.2.3 From 4a25962307ae3317c94ce1e923ed8aea713931a3 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 22 Feb 2018 17:07:50 -0800 Subject: [vcpkg] Avoid use of atomic copy constructor on older compilers --- toolsrc/src/vcpkg/base/checks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp index 1b3ed5ec9..d96cb98ff 100644 --- a/toolsrc/src/vcpkg/base/checks.cpp +++ b/toolsrc/src/vcpkg/base/checks.cpp @@ -10,7 +10,7 @@ namespace vcpkg::Checks { [[noreturn]] static void cleanup_and_exit(const int exit_code) { - static std::atomic have_entered = false; + static std::atomic have_entered{false}; if (have_entered) std::terminate(); have_entered = true; -- cgit v1.2.3 From 407767858336479eebe759404db689a9b1e16671 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 23 Feb 2018 16:34:31 -0800 Subject: Rename "depenencies" to tools. Rework xml file to reduce fields. --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index d574b7c4d..8ec7ba4cc 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -80,10 +80,10 @@ namespace vcpkg return data_lines; } - static fs::path fetch_dependency(const fs::path& scripts_folder, - const std::string& tool_name, - const fs::path& expected_downloaded_path, - const std::array& version) + static fs::path fetch_tool(const fs::path& scripts_folder, + const std::string& tool_name, + const fs::path& expected_downloaded_path, + const std::array& version) { const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", @@ -91,22 +91,21 @@ namespace vcpkg version_as_string, tool_name, version_as_string); - const fs::path script = scripts_folder / "fetchDependency.ps1"; + const fs::path script = scripts_folder / "fetchtool.ps1"; const std::string title = Strings::format( "Fetching %s version %s (No sufficient installed version was found)", tool_name, version_as_string); - const System::PowershellParameter dependency_param("Dependency", tool_name); - const std::string output = System::powershell_execute_and_capture_output(title, script, {dependency_param}); + const System::PowershellParameter tool_param("tool", tool_name); + const std::string output = System::powershell_execute_and_capture_output(title, script, {tool_param}); - const std::vector dependency_path = keep_data_lines(output); - Checks::check_exit( - VCPKG_LINE_INFO, dependency_path.size() == 1, "Expected dependency path, but got %s", output); + const std::vector tool_path = keep_data_lines(output); + Checks::check_exit(VCPKG_LINE_INFO, tool_path.size() == 1, "Expected tool path, but got %s", output); - const fs::path actual_downloaded_path = Strings::trim(std::string{dependency_path.at(0)}); + const fs::path actual_downloaded_path = Strings::trim(std::string{tool_path.at(0)}); std::error_code ec; const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); Checks::check_exit(VCPKG_LINE_INFO, eq && !ec, - "Expected dependency downloaded path to be %s, but was %s", + "Expected tool downloaded path to be %s, but was %s", expected_downloaded_path.u8string(), actual_downloaded_path.u8string()); return actual_downloaded_path; @@ -141,7 +140,7 @@ namespace vcpkg return *p; } - return fetch_dependency(scripts_folder, "cmake", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(scripts_folder, "cmake", downloaded_copy, EXPECTED_VERSION); } fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) @@ -161,7 +160,7 @@ namespace vcpkg return *p; } - return fetch_dependency(scripts_folder, "nuget", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(scripts_folder, "nuget", downloaded_copy, EXPECTED_VERSION); } fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) @@ -193,7 +192,7 @@ namespace vcpkg return *p; } - return fetch_dependency(scripts_folder, "git", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(scripts_folder, "git", downloaded_copy, EXPECTED_VERSION); } static fs::path get_ifw_installerbase_path(const fs::path& downloads_folder, const fs::path& scripts_folder) @@ -221,7 +220,7 @@ namespace vcpkg return *p; } - return fetch_dependency(scripts_folder, "installerbase", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(scripts_folder, "installerbase", downloaded_copy, EXPECTED_VERSION); } Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir) -- cgit v1.2.3 From 7f5efbe14419412d8c24df836a0b3b5192661aa3 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 23 Feb 2018 18:15:26 -0800 Subject: [vcpkgTools.xml] Reuse in vcpkg.exe --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 171 ++++++++++++++++++++++++++------------- 1 file changed, 113 insertions(+), 58 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 8ec7ba4cc..bf231cecd 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -15,35 +15,99 @@ namespace vcpkg static constexpr CStringView V_140 = "v140"; static constexpr CStringView V_141 = "v141"; - static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, - const std::array& expected_version) + struct ToolData { - static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###"); + std::array required_version; + fs::path downloaded_exe_path; + }; - const auto rc = System::cmd_execute_and_capture_output(Strings::format(R"(%s)", version_cmd)); - if (rc.exit_code != 0) - { - return false; - } + static Optional> parse_version_string(const std::string& version_as_string) + { + static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###"); std::match_results match; - const auto found = std::regex_search(rc.output, match, RE); + const auto found = std::regex_search(version_as_string, match, RE); if (!found) { - return false; + return {}; } const int d1 = atoi(match[1].str().c_str()); const int d2 = atoi(match[2].str().c_str()); const int d3 = atoi(match[3].str().c_str()); - if (d1 > expected_version[0] || (d1 == expected_version[0] && d2 > expected_version[1]) || - (d1 == expected_version[0] && d2 == expected_version[1] && d3 >= expected_version[2])) + const std::array result = {d1, d2, d3}; + return result; + } + + static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool) + { + static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; + + const auto get_string_inside_tags = + [](const std::string& input, const std::regex& regex, const std::string& tag_name) -> std::string { + std::smatch match; + const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); + Checks::check_exit( + VCPKG_LINE_INFO, has_match, "Could not find tag <%s> in %s", tag_name, XML_PATH.generic_string()); + + return match[1]; + }; + + static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO); + static const std::regex VERSION_REGEX{ + Strings::format(R"###(([\s\S]*?))###", tool)}; + static const std::regex EXE_RELATIVE_PATH_REGEX{ + Strings::format(R"###(([\s\S]*?))###", tool)}; + + const std::regex tool_regex{Strings::format(R"###(([\s\S]*?))###", tool)}; + + std::smatch match_tool; + const bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); + Checks::check_exit(VCPKG_LINE_INFO, + has_match_tool, + "Could not find entry for tool [%s] in %s", + tool, + XML_PATH.generic_string()); + + const std::string tool_data_as_string = get_string_inside_tags(XML, tool_regex, tool); + + const std::string required_version_as_string = + get_string_inside_tags(tool_data_as_string, VERSION_REGEX, "requiredVersion"); + + const std::string exe_relative_path = + get_string_inside_tags(tool_data_as_string, EXE_RELATIVE_PATH_REGEX, "exeRelativePath"); + + const Optional> required_version = parse_version_string(required_version_as_string); + Checks::check_exit(VCPKG_LINE_INFO, + required_version.has_value(), + "Could not parse version for tool %s. Version string was: %s", + tool, + required_version_as_string); + + const fs::path exe_path = paths.downloads / exe_relative_path; + return ToolData{*required_version.get(), exe_path}; + } + + static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, + const std::array& expected_version) + { + const auto rc = System::cmd_execute_and_capture_output(Strings::format(R"(%s)", version_cmd)); + if (rc.exit_code != 0) + { + return false; + } + + const Optional> v = parse_version_string(rc.output); + if (!v.has_value()) { - // satisfactory version found - return true; + return false; } - return false; + const std::array actual_version = *v.get(); + return (actual_version[0] > expected_version[0] || + (actual_version[0] == expected_version[0] && actual_version[1] > expected_version[1]) || + (actual_version[0] == expected_version[0] && actual_version[1] == expected_version[1] && + actual_version[2] >= expected_version[2])); } static Optional find_if_has_equal_or_greater_version(const std::vector& candidate_paths, @@ -80,11 +144,10 @@ namespace vcpkg return data_lines; } - static fs::path fetch_tool(const fs::path& scripts_folder, - const std::string& tool_name, - const fs::path& expected_downloaded_path, - const std::array& version) + static fs::path fetch_tool(const fs::path& scripts_folder, const std::string& tool_name, const ToolData& tool_data) { + const std::array& version = tool_data.required_version; + const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", tool_name, @@ -101,6 +164,7 @@ namespace vcpkg Checks::check_exit(VCPKG_LINE_INFO, tool_path.size() == 1, "Expected tool path, but got %s", output); const fs::path actual_downloaded_path = Strings::trim(std::string{tool_path.at(0)}); + const fs::path& expected_downloaded_path = tool_data.downloaded_exe_path; std::error_code ec; const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); Checks::check_exit(VCPKG_LINE_INFO, @@ -111,22 +175,20 @@ namespace vcpkg return actual_downloaded_path; } - static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + static fs::path get_cmake_path(const VcpkgPaths& paths) { #if defined(_WIN32) - static constexpr std::array EXPECTED_VERSION = {3, 10, 2}; + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "cmake"); #else - static constexpr std::array EXPECTED_VERSION = {3, 5, 1}; + static const ToolData TOOL_DATA = ToolData{{3, 5, 1}, ""}; #endif static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - const std::vector from_path = Files::find_from_PATH("cmake"); - std::vector candidate_paths; - const fs::path downloaded_copy = downloads_folder / "cmake-3.10.2-win32-x86" / "bin" / "cmake.exe"; #if defined(_WIN32) - candidate_paths.push_back(downloaded_copy); + candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); #endif + const std::vector from_path = Files::find_from_PATH("cmake"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); #if defined(_WIN32) candidate_paths.push_back(System::get_program_files_platform_bitness() / "CMake" / "bin" / "cmake.exe"); @@ -134,51 +196,47 @@ namespace vcpkg #endif const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); if (const auto p = path.get()) { return *p; } - return fetch_tool(scripts_folder, "cmake", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(paths.scripts, "cmake", TOOL_DATA); } - fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + static fs::path get_nuget_path(const VcpkgPaths& paths) { - static constexpr std::array EXPECTED_VERSION = {4, 4, 0}; - - const fs::path downloaded_copy = downloads_folder / "nuget-4.4.0" / "nuget.exe"; - const std::vector from_path = Files::find_from_PATH("nuget"); + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "nuget"); std::vector candidate_paths; - candidate_paths.push_back(downloaded_copy); + candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); + const std::vector from_path = Files::find_from_PATH("nuget"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - auto path = find_if_has_equal_or_greater_version(candidate_paths, "", EXPECTED_VERSION); + auto path = find_if_has_equal_or_greater_version(candidate_paths, "", TOOL_DATA.required_version); if (const auto p = path.get()) { return *p; } - return fetch_tool(scripts_folder, "nuget", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(paths.scripts, "nuget", TOOL_DATA); } - fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + static fs::path get_git_path(const VcpkgPaths& paths) { #if defined(_WIN32) - static constexpr std::array EXPECTED_VERSION = {2, 16, 2}; + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "git"); #else - static constexpr std::array EXPECTED_VERSION = {2, 7, 4}; + static const ToolData TOOL_DATA = ToolData{{2, 7, 4}, ""}; #endif static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - const std::vector from_path = Files::find_from_PATH("git"); - - const fs::path downloaded_copy = downloads_folder / "MinGit-2.16.2-32-bit" / "cmd" / "git.exe"; std::vector candidate_paths; #if defined(_WIN32) - candidate_paths.push_back(downloaded_copy); + candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); #endif + const std::vector from_path = Files::find_from_PATH("git"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); #if defined(_WIN32) candidate_paths.push_back(System::get_program_files_platform_bitness() / "git" / "cmd" / "git.exe"); @@ -186,25 +244,23 @@ namespace vcpkg #endif const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); if (const auto p = path.get()) { return *p; } - return fetch_tool(scripts_folder, "git", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(paths.scripts, "git", TOOL_DATA); } - static fs::path get_ifw_installerbase_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + static fs::path get_ifw_installerbase_path(const VcpkgPaths& paths) { - static constexpr std::array EXPECTED_VERSION = {3, 1, 81}; - static const std::string VERSION_CHECK_ARGUMENTS = "--framework-version"; + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "installerbase"); - const fs::path downloaded_copy = - downloads_folder / "QtInstallerFramework-win-x86" / "bin" / "installerbase.exe"; + static const std::string VERSION_CHECK_ARGUMENTS = "--framework-version"; std::vector candidate_paths; - candidate_paths.push_back(downloaded_copy); + candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); // TODO: Uncomment later // const std::vector from_path = Files::find_from_PATH("installerbase"); // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); @@ -214,13 +270,13 @@ namespace vcpkg // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); if (const auto p = path.get()) { return *p; } - return fetch_tool(scripts_folder, "installerbase", downloaded_copy, EXPECTED_VERSION); + return fetch_tool(paths.scripts, "installerbase", TOOL_DATA); } Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir) @@ -299,23 +355,22 @@ namespace vcpkg const fs::path& VcpkgPaths::get_cmake_exe() const { - return this->cmake_exe.get_lazy([this]() { return get_cmake_path(this->downloads, this->scripts); }); + return this->cmake_exe.get_lazy([this]() { return get_cmake_path(*this); }); } const fs::path& VcpkgPaths::get_git_exe() const { - return this->git_exe.get_lazy([this]() { return get_git_path(this->downloads, this->scripts); }); + return this->git_exe.get_lazy([this]() { return get_git_path(*this); }); } const fs::path& VcpkgPaths::get_nuget_exe() const { - return this->nuget_exe.get_lazy([this]() { return get_nuget_path(this->downloads, this->scripts); }); + return this->nuget_exe.get_lazy([this]() { return get_nuget_path(*this); }); } const fs::path& VcpkgPaths::get_ifw_installerbase_exe() const { - return this->ifw_installerbase_exe.get_lazy( - [this]() { return get_ifw_installerbase_path(this->downloads, this->scripts); }); + return this->ifw_installerbase_exe.get_lazy([this]() { return get_ifw_installerbase_path(*this); }); } const fs::path& VcpkgPaths::get_ifw_binarycreator_exe() const -- cgit v1.2.3 From 8c8fc1a28afd8fa8ea149528d68c264cc1182dd7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 25 Feb 2018 03:30:31 -0800 Subject: [vcpkg] Fix exclusions in ci --- toolsrc/src/vcpkg/commands.ci.cpp | 59 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 31 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 313582b7b..c43f25b40 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -18,34 +18,6 @@ namespace vcpkg::Commands::CI using Dependencies::InstallPlanAction; using Dependencies::InstallPlanType; - static Install::InstallSummary run_ci_on_triplet(const Triplet& triplet, - const VcpkgPaths& paths, - const std::vector& ports) - { - Input::check_triplet(triplet, paths); - std::vector specs = PackageSpec::to_package_specs(ports, triplet); - const auto featurespecs = Util::fmap(specs, [](auto& spec) { return FeatureSpec(spec, ""); }); - - StatusParagraphs status_db = database_load_check(paths); - const auto& paths_port_file = Dependencies::PathsPortFileProvider(paths); - auto action_plan = Dependencies::create_feature_install_plan(paths_port_file, featurespecs, status_db); - - const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, - Build::AllowDownloads::YES, - Build::CleanBuildtrees::YES, - Build::CleanPackages::YES}; - - for (auto&& action : action_plan) - { - if (auto p = action.install_action.get()) - { - p->build_options = install_plan_options; - } - } - - return Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db); - } - struct TripletAndSummary { Triplet triplet; @@ -91,13 +63,38 @@ namespace vcpkg::Commands::CI triplets.push_back(default_triplet); } - std::vector ports = Install::get_all_port_names(paths); - Util::erase_remove_if(ports, [&](auto&& port) { return Util::Sets::contains(exclusions_set, port); }); + StatusParagraphs status_db = database_load_check(paths); + const auto& paths_port_file = Dependencies::PathsPortFileProvider(paths); + const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, + Build::AllowDownloads::YES, + Build::CleanBuildtrees::YES, + Build::CleanPackages::YES}; + + std::vector ports = Install::get_all_port_names(paths); std::vector results; for (const Triplet& triplet : triplets) { - Install::InstallSummary summary = run_ci_on_triplet(triplet, paths, ports); + Input::check_triplet(triplet, paths); + std::vector specs = PackageSpec::to_package_specs(ports, triplet); + // Install the default features for every package + const auto featurespecs = Util::fmap(specs, [](auto& spec) { return FeatureSpec(spec, ""); }); + + auto action_plan = Dependencies::create_feature_install_plan(paths_port_file, featurespecs, status_db); + + for (auto&& action : action_plan) + { + if (auto p = action.install_action.get()) + { + p->build_options = install_plan_options; + if (Util::Sets::contains(exclusions_set, p->spec.name())) + { + p->plan_type = InstallPlanType::EXCLUDED; + } + } + } + + auto summary = Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db); results.push_back({triplet, std::move(summary)}); } -- cgit v1.2.3 From 8b97ae2dc14672ca83a5a7dc8f1d62af99234476 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 25 Feb 2018 10:13:57 -0800 Subject: [vcpkg] Fix "just-in-time" requirements calculation --- toolsrc/src/vcpkg/build.cpp | 117 +++++++++++++++++++++------------ toolsrc/src/vcpkg/commands.hash.cpp | 10 +-- toolsrc/src/vcpkg/dependencies.cpp | 8 +-- toolsrc/src/vcpkg/statusparagraphs.cpp | 10 +++ 4 files changed, 96 insertions(+), 49 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index c169a778e..ff7554b78 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -66,7 +66,8 @@ namespace vcpkg::Build::Command Build::CleanBuildtrees::NO, Build::CleanPackages::NO}; - const std::unordered_set features_as_set(full_spec.features.begin(), full_spec.features.end()); + std::set features_as_set(full_spec.features.begin(), full_spec.features.end()); + features_as_set.emplace("core"); const Build::BuildPackageConfig build_config{ *scf, spec.triplet(), fs::path{port_dir}, build_package_options, features_as_set}; @@ -260,56 +261,93 @@ namespace vcpkg::Build paths.get_filesystem().write_contents(binary_control_file, start); } - static ExtendedBuildResult do_build_package(const VcpkgPaths& paths, - const BuildPackageConfig& config, - const StatusParagraphs& status_db) + static std::vector compute_required_feature_specs(const BuildPackageConfig& config, + const StatusParagraphs& status_db) { - const PackageSpec spec = PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, config.triplet) - .value_or_exit(VCPKG_LINE_INFO); - const Triplet& triplet = config.triplet; + + auto dep_strings = + Util::fmap_flatten(config.feature_list, [&](std::string const& feature) -> std::vector { + if (feature == "core") + { + return filter_dependencies(config.scf.core_paragraph->depends, triplet); + } + + auto it = + Util::find_if(config.scf.feature_paragraphs, + [&](std::unique_ptr const& fpgh) { return fpgh->name == feature; }); + Checks::check_exit(VCPKG_LINE_INFO, it != config.scf.feature_paragraphs.end()); + + return filter_dependencies(it->get()->depends, triplet); + }); + + auto dep_fspecs = FeatureSpec::from_strings_and_triplet(dep_strings, triplet); + Util::sort_unique_erase(dep_fspecs); + + // expand defaults + std::vector ret; + for (auto&& fspec : dep_fspecs) { - std::vector missing_specs; - for (auto&& dep : filter_dependencies(config.scf.core_paragraph->depends, triplet)) + if (fspec.feature().empty()) { - auto dep_specs = FeatureSpec::from_strings_and_triplet({dep}, triplet); - for (auto&& feature : dep_specs) + // reference to default features + auto it = status_db.find_installed(fspec.spec()); + if (it == status_db.end()) + { + // not currently installed, so just leave the default reference so it will fail later + ret.push_back(fspec); + } + else { - if (!status_db.is_installed(feature)) - { - missing_specs.push_back(std::move(feature)); - } + ret.push_back(FeatureSpec{fspec.spec(), "core"}); + for (auto&& default_feature : it->get()->package.default_features) + ret.push_back(FeatureSpec{fspec.spec(), default_feature}); } } - // Fail the build if any dependencies were missing - if (!missing_specs.empty()) + else { - return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(missing_specs)}; + ret.push_back(fspec); } } + Util::sort_unique_erase(ret); + + return ret; + } + + static ExtendedBuildResult do_build_package(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const StatusParagraphs& status_db) + { + auto& fs = paths.get_filesystem(); + const Triplet& triplet = config.triplet; + + const PackageSpec spec = + PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, triplet).value_or_exit(VCPKG_LINE_INFO); + + std::vector required_fspecs = compute_required_feature_specs(config, status_db); + + // Find all features that aren't installed. This destroys required_fspecs. + Util::unstable_keep_if(required_fspecs, + [&](FeatureSpec const& fspec) { return !status_db.is_installed(fspec); }); + + if (!required_fspecs.empty()) + { + return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; + } const fs::path& cmake_exe_path = paths.get_cmake_exe(); const fs::path& git_exe_path = paths.get_git_exe(); const fs::path ports_cmake_script_path = paths.ports_cmake; + const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); - std::string features; + std::string features = Strings::join(";", config.feature_list); + std::string all_features; - if (GlobalState::feature_packages) + for (auto& feature : config.scf.feature_paragraphs) { - for (auto&& feature : config.feature_list) - { - features.append(feature + ";"); - } - if (!features.empty()) - { - features.pop_back(); - } - for (auto& feature : config.scf.feature_paragraphs) - { - all_features.append(feature->name + ";"); - } + all_features.append(feature->name + ";"); } const Toolset& toolset = paths.get_toolset(pre_build_info); @@ -351,7 +389,7 @@ namespace vcpkg::Build } } - const BuildInfo build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); + const BuildInfo build_info = read_build_info(fs, paths.build_info_file_path(spec)); const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); auto bcf = create_binary_control_file(*config.scf.core_paragraph, triplet, build_info); @@ -360,16 +398,13 @@ namespace vcpkg::Build { return BuildResult::POST_BUILD_CHECKS_FAILED; } - if (GlobalState::feature_packages) + for (auto&& feature : config.feature_list) { - for (auto&& feature : config.feature_list) + for (auto&& f_pgh : config.scf.feature_paragraphs) { - for (auto&& f_pgh : config.scf.feature_paragraphs) - { - if (f_pgh->name == feature) - bcf->features.push_back( - create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet)); - } + if (f_pgh->name == feature) + bcf->features.push_back( + create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet)); } } diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index fa3d80f27..767a1bf26 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -7,7 +7,7 @@ namespace vcpkg::Commands::Hash { - static void do_file_hash(fs::path const& cmake_exe_path, fs::path const& path, std::string const& hash_type) + std::string get_file_hash(fs::path const& cmake_exe_path, fs::path const& path, std::string const& hash_type) { const std::string cmd_line = Strings::format( R"("%s" -E %ssum %s)", cmake_exe_path.u8string(), Strings::ascii_to_lowercase(hash_type), path.u8string()); @@ -27,7 +27,7 @@ namespace vcpkg::Commands::Hash auto hash = output.substr(0, start); Util::erase_remove_if(hash, isspace); - System::println(hash); + return hash; } const CommandStructure COMMAND_STRUCTURE = { @@ -45,11 +45,13 @@ namespace vcpkg::Commands::Hash if (args.command_arguments.size() == 1) { - do_file_hash(paths.get_cmake_exe(), args.command_arguments[0], "SHA512"); + auto hash = get_file_hash(paths.get_cmake_exe(), args.command_arguments[0], "SHA512"); + System::println(hash); } if (args.command_arguments.size() == 2) { - do_file_hash(paths.get_cmake_exe(), args.command_arguments[0], args.command_arguments[1]); + auto hash = get_file_hash(paths.get_cmake_exe(), args.command_arguments[0], args.command_arguments[1]); + System::println(hash); } Checks::exit_success(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 793951ab5..649e8f1d8 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -30,8 +30,8 @@ namespace vcpkg::Dependencies Optional source_control_file; PackageSpec spec; std::unordered_map edges; - std::unordered_set to_install_features; - std::unordered_set original_features; + std::set to_install_features; + std::set original_features; bool will_remove = false; bool transient_uninstalled = true; RequestType request_type = RequestType::AUTO_SELECTED; @@ -143,7 +143,7 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const SourceControlFile& scf, - const std::unordered_set& features, + const std::set& features, const RequestType& request_type) : spec(spec) , source_control_file(scf) @@ -155,7 +155,7 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, InstalledPackageView&& ipv, - const std::unordered_set& features, + const std::set& features, const RequestType& request_type) : spec(spec) , installed_package(std::move(ipv)) diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp index b23d8b884..c642af59b 100644 --- a/toolsrc/src/vcpkg/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -54,6 +54,11 @@ namespace vcpkg const Triplet& triplet, const std::string& feature) { + if (feature == "core") + { + // The core feature maps to .feature == "" + return find(name, triplet, ""); + } return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { const PackageSpec& spec = pgh->package.spec; return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature; @@ -64,6 +69,11 @@ namespace vcpkg const Triplet& triplet, const std::string& feature) const { + if (feature == "core") + { + // The core feature maps to .feature == "" + return find(name, triplet, ""); + } return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { const PackageSpec& spec = pgh->package.spec; return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature; -- cgit v1.2.3 From 2e135bf09677163fc20364f9d46ba4248042ae1a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 26 Feb 2018 05:19:05 -0800 Subject: [vcpkg] Fix issue when removing packages that have explicit feature dependencies. --- toolsrc/src/tests.plan.cpp | 15 +++++++++++++++ toolsrc/src/vcpkg/dependencies.cpp | 30 +++++++++++++++++++----------- 2 files changed, 34 insertions(+), 11 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 546e20b0d..d33ab290d 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -780,6 +780,21 @@ namespace UnitTest1 Assert::AreEqual("vtk", remove_plan[1].spec.name().c_str()); Assert::AreEqual("expat", remove_plan[2].spec.name().c_str()); } + + TEST_METHOD(features_depend_core_remove_scheme) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("curl", "", "", "x64")); + pghs.push_back(make_status_pgh("cpr", "curl[core]", "", "x64")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan( + {unsafe_pspec("curl", Triplet::from_canonical_name("x64"))}, status_db); + + Assert::AreEqual(size_t(2), remove_plan.size()); + Assert::AreEqual("cpr", remove_plan[0].spec.name().c_str()); + Assert::AreEqual("curl", remove_plan[1].spec.name().c_str()); + } }; class UpgradePlanTests : public TestClass diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 649e8f1d8..43e4d2721 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -29,7 +29,7 @@ namespace vcpkg::Dependencies Optional source_control_file; PackageSpec spec; - std::unordered_map edges; + std::unordered_map edges_by_feature; std::set to_install_features; std::set original_features; bool will_remove = false; @@ -100,13 +100,13 @@ namespace vcpkg::Dependencies FeatureNodeEdges core_dependencies; core_dependencies.build_edges = filter_dependencies_to_specs(scf.core_paragraph->depends, out_cluster.spec.triplet()); - out_cluster.edges.emplace("core", std::move(core_dependencies)); + out_cluster.edges_by_feature.emplace("core", std::move(core_dependencies)); for (const auto& feature : scf.feature_paragraphs) { FeatureNodeEdges added_edges; added_edges.build_edges = filter_dependencies_to_specs(feature->depends, out_cluster.spec.triplet()); - out_cluster.edges.emplace(feature->name, std::move(added_edges)); + out_cluster.edges_by_feature.emplace(feature->name, std::move(added_edges)); } out_cluster.source_control_file = &scf; } @@ -309,7 +309,15 @@ namespace vcpkg::Dependencies { if (an_installed_package->package.spec.triplet() != spec.triplet()) continue; - const std::vector& deps = an_installed_package->package.depends; + std::vector deps = an_installed_package->package.depends; + // + // This is a hack to work around existing installations that put featurespecs into binary packages + // (example: curl[core]) Eventually, this can be returned to a simple string search. + for (auto&& dep : deps) + { + dep.erase(std::find(dep.begin(), dep.end(), '['), dep.end()); + } + // if (std::find(deps.begin(), deps.end(), spec.name()) == deps.end()) continue; dependents.push_back(an_installed_package->package.spec); @@ -446,10 +454,10 @@ namespace vcpkg::Dependencies } } - auto it = cluster.edges.find(feature); - if (it == cluster.edges.end()) return MarkPlusResult::FEATURE_NOT_FOUND; + auto it = cluster.edges_by_feature.find(feature); + if (it == cluster.edges_by_feature.end()) return MarkPlusResult::FEATURE_NOT_FOUND; - if (cluster.edges[feature].plus) return MarkPlusResult::SUCCESS; + if (cluster.edges_by_feature[feature].plus) return MarkPlusResult::SUCCESS; if (cluster.original_features.find(feature) == cluster.original_features.end()) { @@ -460,7 +468,7 @@ namespace vcpkg::Dependencies { return MarkPlusResult::SUCCESS; } - cluster.edges[feature].plus = true; + cluster.edges_by_feature[feature].plus = true; if (!cluster.original_features.empty()) { @@ -485,7 +493,7 @@ namespace vcpkg::Dependencies auto res = mark_plus("", cluster, graph, graph_plan, prevent_default_features); } - for (auto&& depend : cluster.edges[feature].build_edges) + for (auto&& depend : cluster.edges_by_feature[feature].build_edges) { auto& depend_cluster = graph.get(depend.spec()); auto res = mark_plus(depend.feature(), depend_cluster, graph, graph_plan, prevent_default_features); @@ -521,7 +529,7 @@ namespace vcpkg::Dependencies } graph_plan.remove_graph.add_vertex({&cluster}); - for (auto&& pair : cluster.edges) + for (auto&& pair : cluster.edges_by_feature) { auto& remove_edges_edges = pair.second.remove_edges; for (auto&& depend : remove_edges_edges) @@ -746,7 +754,7 @@ namespace vcpkg::Dependencies auto depends_name = dependency.feature(); if (depends_name.empty()) depends_name = "core"; - auto& target_node = dep_cluster.edges[depends_name]; + auto& target_node = dep_cluster.edges_by_feature[depends_name]; target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); } } -- cgit v1.2.3 From 71d44cebdb85926bc00241fc08f0dcaaedb868d2 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 26 Feb 2018 06:08:51 -0800 Subject: [vcpkg] Add test for default-features with a preinstalled dependency --- toolsrc/src/tests.plan.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index d33ab290d..2bdb4a465 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -536,8 +536,34 @@ namespace UnitTest1 // Expect "a" to get installed and defaults of "b" through the dependency, // as no explicit features of "b" are installed by the user. Assert::IsTrue(install_plan.size() == 2); - features_check(&install_plan[1], "a", {"core"}, Triplet::X64_WINDOWS); features_check(&install_plan[0], "b", {"b1", "core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[1], "a", {"core"}, Triplet::X64_WINDOWS); + } + + TEST_METHOD(do_not_install_default_features_of_existing_dependency) + { + // Add a port "a" which depends on the core of "b" + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "b[core]"); + // "b" has two features, of which "b1" is default. + spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"}); + + std::vector> status_paragraphs; + // "b[core]" is already installed + status_paragraphs.push_back(make_status_pgh("b")); + status_paragraphs.back()->package.spec = + PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect "a" to get installed, but not require rebuilding "b" + Assert::IsTrue(install_plan.size() == 1); + features_check(&install_plan[0], "a", {"core"}, Triplet::X64_WINDOWS); } TEST_METHOD(install_default_features_of_dependency_test_2) -- cgit v1.2.3 From 65e95f6348e3a23a2afd1c1d25c9501dc826b183 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 26 Feb 2018 14:35:08 -0800 Subject: [vcpkg] Fix inter-feature references --- toolsrc/src/tests.plan.cpp | 15 +++++++++++++++ toolsrc/src/vcpkg/dependencies.cpp | 2 ++ 2 files changed, 17 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 2bdb4a465..aae4d2ee4 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -821,6 +821,21 @@ namespace UnitTest1 Assert::AreEqual("cpr", remove_plan[0].spec.name().c_str()); Assert::AreEqual("curl", remove_plan[1].spec.name().c_str()); } + + TEST_METHOD(features_depend_core_remove_scheme_2) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("curl", "", "", "x64")); + pghs.push_back(make_status_feature_pgh("curl", "a", "", "x64")); + pghs.push_back(make_status_feature_pgh("curl", "b", "curl[a]", "x64")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan( + {unsafe_pspec("curl", Triplet::from_canonical_name("x64"))}, status_db); + + Assert::AreEqual(size_t(1), remove_plan.size()); + Assert::AreEqual("curl", remove_plan[0].spec.name().c_str()); + } }; class UpgradePlanTests : public TestClass diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 43e4d2721..f4a371a2e 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -317,6 +317,8 @@ namespace vcpkg::Dependencies { dep.erase(std::find(dep.begin(), dep.end(), '['), dep.end()); } + Util::unstable_keep_if(deps, + [&](auto&& e) { return e != an_installed_package->package.spec.name(); }); // if (std::find(deps.begin(), deps.end(), spec.name()) == deps.end()) continue; -- cgit v1.2.3 From c267f32bd976ae599fa57d63031352b1c84a9c53 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 26 Feb 2018 14:43:47 -0800 Subject: [vcpkg] Fix feature interdependency during install --- toolsrc/src/vcpkg/build.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index ff7554b78..0e0928a1b 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -327,8 +327,9 @@ namespace vcpkg::Build std::vector required_fspecs = compute_required_feature_specs(config, status_db); // Find all features that aren't installed. This destroys required_fspecs. - Util::unstable_keep_if(required_fspecs, - [&](FeatureSpec const& fspec) { return !status_db.is_installed(fspec); }); + Util::unstable_keep_if(required_fspecs, [&](FeatureSpec const& fspec) { + return !status_db.is_installed(fspec) && fspec.name() != spec.name(); + }); if (!required_fspecs.empty()) { -- cgit v1.2.3 From e2980c8f91327614f24abec6704a5831d8074a8a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 26 Feb 2018 18:18:43 -0800 Subject: [vcpkg] Add 7zip internal tool --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index bf231cecd..f2b39c110 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -205,6 +205,20 @@ namespace vcpkg return fetch_tool(paths.scripts, "cmake", TOOL_DATA); } + static fs::path get_7za_path(const VcpkgPaths& paths) + { +#if defined(_WIN32) + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "7zip"); + if (!paths.get_filesystem().exists(TOOL_DATA.downloaded_exe_path)) + { + return fetch_tool(paths.scripts, "7zip", TOOL_DATA); + } + return TOOL_DATA.downloaded_exe_path; +#else + Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot download 7zip for non-Windows platforms."); +#endif + } + static fs::path get_nuget_path(const VcpkgPaths& paths) { static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "nuget"); @@ -353,6 +367,11 @@ namespace vcpkg return it != this->get_available_triplets().cend(); } + const fs::path& VcpkgPaths::get_7za_exe() const + { + return this->_7za_exe.get_lazy([this]() { return get_7za_path(*this); }); + } + const fs::path& VcpkgPaths::get_cmake_exe() const { return this->cmake_exe.get_lazy([this]() { return get_cmake_path(*this); }); -- cgit v1.2.3 From a2e6ffd86d435f08116e5e80b04796fe6898ebd0 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 26 Feb 2018 18:22:17 -0800 Subject: [vcpkg] Refactor VcpkgCmdArguments to not utilize global state --- toolsrc/src/vcpkg.cpp | 1 + toolsrc/src/vcpkg/vcpkgcmdarguments.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index adb32c723..ffda7ede9 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -265,6 +265,7 @@ int main(const int argc, const char* const* const argv) const VcpkgCmdArguments args = VcpkgCmdArguments::create_from_command_line(argc, argv); + if (const auto p = args.featurepackages.get()) GlobalState::feature_packages = *p; if (const auto p = args.printmetrics.get()) Metrics::g_metrics.lock()->set_print_metrics(*p); if (const auto p = args.sendmetrics.get()) Metrics::g_metrics.lock()->set_send_metrics(*p); if (const auto p = args.debug.get()) GlobalState::debugging = *p; diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp index 84ad17fe3..18acf8e12 100644 --- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp +++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp @@ -126,12 +126,13 @@ namespace vcpkg } if (arg == "--featurepackages") { - GlobalState::feature_packages = true; + parse_switch(true, "featurepackages", args.featurepackages); continue; } if (arg == "--no-featurepackages") { - GlobalState::feature_packages = false; + parse_switch(false, "featurepackages", args.featurepackages); + continue; continue; } -- cgit v1.2.3 From 9eb9eca48766289b6377eb479cd5eb5f3da7441d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 26 Feb 2018 18:25:01 -0800 Subject: [vcpkg-hash] Fix target paths containing spaces --- toolsrc/src/vcpkg/commands.hash.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 767a1bf26..bbbbed036 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -10,7 +10,10 @@ namespace vcpkg::Commands::Hash std::string get_file_hash(fs::path const& cmake_exe_path, fs::path const& path, std::string const& hash_type) { const std::string cmd_line = Strings::format( - R"("%s" -E %ssum %s)", cmake_exe_path.u8string(), Strings::ascii_to_lowercase(hash_type), path.u8string()); + R"("%s" -E %ssum "%s")", + cmake_exe_path.u8string(), + Strings::ascii_to_lowercase(hash_type), + path.u8string()); const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line); -- cgit v1.2.3 From 25b8f25dadcb2af28ae5be2e6d31884ca67f1b26 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 26 Feb 2018 18:38:25 -0800 Subject: [vcpkg] Initial commit of experimental compressed binary archiving behind a flag --- toolsrc/src/vcpkg.cpp | 9 ++ toolsrc/src/vcpkg/binaryparagraph.cpp | 11 +- toolsrc/src/vcpkg/build.cpp | 263 ++++++++++++++++++++++++++------ toolsrc/src/vcpkg/globalstate.cpp | 1 + toolsrc/src/vcpkg/vcpkgcmdarguments.cpp | 9 ++ 5 files changed, 235 insertions(+), 58 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index ffda7ede9..ef68e6f72 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -263,9 +263,18 @@ int main(const int argc, const char* const* const argv) } load_config(); + const auto vcpkg_feature_flags_env = System::get_environment_variable("VCPKG_FEATURE_FLAGS"); + if (const auto v = vcpkg_feature_flags_env.get()) + { + auto flags = Strings::split(*v, ","); + if (std::find(flags.begin(), flags.end(), "binarycaching") != flags.end()) GlobalState::g_binary_caching = true; + } + const VcpkgCmdArguments args = VcpkgCmdArguments::create_from_command_line(argc, argv); if (const auto p = args.featurepackages.get()) GlobalState::feature_packages = *p; + if (const auto p = args.binarycaching.get()) GlobalState::g_binary_caching = *p; + if (const auto p = args.printmetrics.get()) Metrics::g_metrics.lock()->set_print_metrics(*p); if (const auto p = args.sendmetrics.get()) Metrics::g_metrics.lock()->set_send_metrics(*p); if (const auto p = args.debug.get()) GlobalState::debugging = *p; diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp index 7c9e905e8..7a8b0d577 100644 --- a/toolsrc/src/vcpkg/binaryparagraph.cpp +++ b/toolsrc/src/vcpkg/binaryparagraph.cpp @@ -71,22 +71,17 @@ namespace vcpkg Checks::check_exit(VCPKG_LINE_INFO, multi_arch == "same", "Multi-Arch must be 'same' but was %s", multi_arch); } - BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const Triplet& triplet) + BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const Triplet& triplet, const std::string& abi_tag) + : version(spgh.version), description(spgh.description), maintainer(spgh.maintainer), abi(abi_tag) { this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); - this->version = spgh.version; - this->description = spgh.description; - this->maintainer = spgh.maintainer; this->depends = filter_dependencies(spgh.depends, triplet); } BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, const Triplet& triplet) + : version(), feature(fpgh.name), description(fpgh.description), maintainer() { this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); - this->version = ""; - this->feature = fpgh.name; - this->description = fpgh.description; - this->maintainer = ""; this->depends = filter_dependencies(fpgh.depends, triplet); } diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 0e0928a1b..0486039b7 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -238,10 +238,11 @@ namespace vcpkg::Build static std::unique_ptr create_binary_control_file(const SourceParagraph& source_paragraph, const Triplet& triplet, - const BuildInfo& build_info) + const BuildInfo& build_info, + const std::string& abi_tag) { auto bcf = std::make_unique(); - BinaryParagraph bpgh(source_paragraph, triplet); + BinaryParagraph bpgh(source_paragraph, triplet, abi_tag); if (const auto p_ver = build_info.version.get()) { bpgh.version = *p_ver; @@ -321,11 +322,23 @@ namespace vcpkg::Build auto& fs = paths.get_filesystem(); const Triplet& triplet = config.triplet; + struct AbiEntry + { + std::string key; + std::string value; + }; + + std::vector abi_tag_entries; + const PackageSpec spec = PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, triplet).value_or_exit(VCPKG_LINE_INFO); std::vector required_fspecs = compute_required_feature_specs(config, status_db); + // extract out the actual package ids + auto dep_pspecs = Util::fmap(required_fspecs, [](FeatureSpec const& fspec) { return fspec.spec(); }); + Util::sort_unique_erase(dep_pspecs); + // Find all features that aren't installed. This destroys required_fspecs. Util::unstable_keep_if(required_fspecs, [&](FeatureSpec const& fspec) { return !status_db.is_installed(fspec) && fspec.name() != spec.name(); @@ -336,81 +349,210 @@ namespace vcpkg::Build return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; } + // dep_pspecs was not destroyed + for (auto&& pspec : dep_pspecs) + { + if (pspec == spec) continue; + auto status_it = status_db.find_installed(pspec); + Checks::check_exit(VCPKG_LINE_INFO, status_it != status_db.end()); + abi_tag_entries.emplace_back( + AbiEntry{status_it->get()->package.spec.name(), status_it->get()->package.abi}); + } + const fs::path& cmake_exe_path = paths.get_cmake_exe(); const fs::path& git_exe_path = paths.get_git_exe(); const fs::path ports_cmake_script_path = paths.ports_cmake; + if (GlobalState::g_binary_caching) + { + abi_tag_entries.emplace_back(AbiEntry{ + "portfile", Commands::Hash::get_file_hash(cmake_exe_path, config.port_dir / "portfile.cmake", "SHA1")}); + abi_tag_entries.emplace_back(AbiEntry{ + "control", Commands::Hash::get_file_hash(cmake_exe_path, config.port_dir / "CONTROL", "SHA1")}); + } + const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); + abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag}); std::string features = Strings::join(";", config.feature_list); + abi_tag_entries.emplace_back(AbiEntry{"features", features}); - std::string all_features; - for (auto& feature : config.scf.feature_paragraphs) - { - all_features.append(feature->name + ";"); - } + if (config.build_package_options.use_head_version == UseHeadVersion::YES) + abi_tag_entries.emplace_back(AbiEntry{"head", ""}); - const Toolset& toolset = paths.get_toolset(pre_build_info); - const std::string cmd_launch_cmake = System::make_cmake_cmd( - cmake_exe_path, - ports_cmake_script_path, - { - {"CMD", "BUILD"}, - {"PORT", config.scf.core_paragraph->name}, - {"CURRENT_PORT_DIR", config.port_dir / "/."}, - {"TARGET_TRIPLET", triplet.canonical_name()}, - {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, - {"VCPKG_USE_HEAD_VERSION", - Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, - {"_VCPKG_NO_DOWNLOADS", !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, - {"GIT", git_exe_path}, - {"FEATURES", features}, - {"ALL_FEATURES", all_features}, - }); + std::string full_abi_info = + Strings::join("", abi_tag_entries, [](const AbiEntry& p) { return p.key + " " + p.value + "\n"; }); - const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); - const std::string command = Strings::format(R"(%s && %s)", cmd_set_environment, cmd_launch_cmake); + std::string abi_tag; + + if (GlobalState::g_binary_caching) + { + if (GlobalState::debugging) + { + System::println("[DEBUG] "); + for (auto&& entry : abi_tag_entries) + { + System::println("[DEBUG] %s|%s", entry.key, entry.value); + } + System::println("[DEBUG] "); + } - const auto timer = Chrono::ElapsedTimer::create_started(); + auto abi_tag_entries_missing = abi_tag_entries; + Util::stable_keep_if(abi_tag_entries_missing, [](const AbiEntry& p) { return p.value.empty(); }); - const int return_code = System::cmd_execute_clean(command); - const auto buildtimeus = timer.microseconds(); - const auto spec_string = spec.to_string(); + if (abi_tag_entries_missing.empty()) + { + std::error_code ec; + fs.create_directories(paths.buildtrees / spec.name(), ec); + auto abi_file_path = paths.buildtrees / spec.name() / "vcpkg_abi_info"; + fs.write_contents(abi_file_path, full_abi_info); - { - auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_buildtime(spec.to_string() + ":[" + Strings::join(",", config.feature_list) + "]", - buildtimeus); - if (return_code != 0) + abi_tag = Commands::Hash::get_file_hash(paths.get_cmake_exe(), abi_file_path, "SHA1"); + } + else { - locked_metrics->track_property("error", "build failed"); - locked_metrics->track_property("build_error", spec_string); - return BuildResult::BUILD_FAILED; + System::println("Warning: binary caching disabled because abi keys are missing values:\n%s", + Strings::join("", abi_tag_entries_missing, [](const AbiEntry& e) { + return " " + e.key + "\n"; + })); } } - const BuildInfo build_info = read_build_info(fs, paths.build_info_file_path(spec)); - const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); + std::unique_ptr bcf; - auto bcf = create_binary_control_file(*config.scf.core_paragraph, triplet, build_info); + auto archives_dir = paths.root / "archives"; + if (!abi_tag.empty()) + { + archives_dir /= abi_tag.substr(0, 2); + } + auto archive_path = archives_dir / (abi_tag + ".zip"); - if (error_count != 0) + if (GlobalState::g_binary_caching && !abi_tag.empty() && fs.exists(archive_path)) { - return BuildResult::POST_BUILD_CHECKS_FAILED; + System::println("Using cached binary package: %s", archive_path.u8string()); + + auto pkg_path = paths.package_dir(spec); + std::error_code ec; + fs.remove_all(pkg_path, ec); + fs.create_directories(pkg_path, ec); + auto files = fs.get_files_non_recursive(pkg_path); + Checks::check_exit(VCPKG_LINE_INFO, files.empty(), "unable to clear path: %s", pkg_path.u8string()); + + auto&& _7za = paths.get_7za_exe(); + + System::cmd_execute_clean(Strings::format( + R"("%s" x "%s" -o"%s" -y >nul)", _7za.u8string(), archive_path.u8string(), pkg_path.u8string())); + + auto maybe_bcf = Paragraphs::try_load_cached_control_package(paths, spec); + bcf = std::make_unique(std::move(maybe_bcf).value_or_exit(VCPKG_LINE_INFO)); } - for (auto&& feature : config.feature_list) + else { - for (auto&& f_pgh : config.scf.feature_paragraphs) + if (GlobalState::g_binary_caching && !abi_tag.empty()) { - if (f_pgh->name == feature) - bcf->features.push_back( - create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet)); + System::println("Could not locate cached archive: %s", archive_path.u8string()); } - } - write_binary_control_file(paths, *bcf); + std::string all_features; + for (auto& feature : config.scf.feature_paragraphs) + { + all_features.append(feature->name + ";"); + } + + const Toolset& toolset = paths.get_toolset(pre_build_info); + const std::string cmd_launch_cmake = System::make_cmake_cmd( + cmake_exe_path, + ports_cmake_script_path, + { + {"CMD", "BUILD"}, + {"PORT", config.scf.core_paragraph->name}, + {"CURRENT_PORT_DIR", config.port_dir / "/."}, + {"TARGET_TRIPLET", triplet.canonical_name()}, + {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, + {"VCPKG_USE_HEAD_VERSION", + Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, + {"_VCPKG_NO_DOWNLOADS", + !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, + {"GIT", git_exe_path}, + {"FEATURES", features}, + {"ALL_FEATURES", all_features}, + }); + + const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); + const std::string command = Strings::format(R"(%s && %s)", cmd_set_environment, cmd_launch_cmake); + + const auto timer = Chrono::ElapsedTimer::create_started(); + + const int return_code = System::cmd_execute_clean(command); + const auto buildtimeus = timer.microseconds(); + const auto spec_string = spec.to_string(); + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_buildtime(spec.to_string() + ":[" + Strings::join(",", config.feature_list) + "]", + buildtimeus); + if (return_code != 0) + { + locked_metrics->track_property("error", "build failed"); + locked_metrics->track_property("build_error", spec_string); + return BuildResult::BUILD_FAILED; + } + } + + const BuildInfo build_info = read_build_info(fs, paths.build_info_file_path(spec)); + const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); + + bcf = create_binary_control_file(*config.scf.core_paragraph, triplet, build_info, abi_tag); + + if (error_count != 0) + { + return BuildResult::POST_BUILD_CHECKS_FAILED; + } + for (auto&& feature : config.feature_list) + { + for (auto&& f_pgh : config.scf.feature_paragraphs) + { + if (f_pgh->name == feature) + bcf->features.push_back( + create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet)); + } + } + + if (GlobalState::g_binary_caching && !abi_tag.empty()) + { + std::error_code ec; + fs.write_contents( + paths.package_dir(spec) / "share" / spec.name() / "vcpkg_abi_info.txt", full_abi_info, ec); + } + + write_binary_control_file(paths, *bcf); + + if (GlobalState::g_binary_caching && !abi_tag.empty()) + { + auto tmp_archive_path = paths.buildtrees / spec.name() / (spec.triplet().to_string() + ".zip"); + + std::error_code ec; + fs.remove(tmp_archive_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !fs.exists(tmp_archive_path), + "Could not remove file: %s", + tmp_archive_path.u8string()); + auto&& _7za = paths.get_7za_exe(); + + System::cmd_execute_clean(Strings::format( + R"("%s" a "%s" "%s\*" >nul)", + _7za.u8string(), + tmp_archive_path.u8string(), + paths.package_dir(spec).u8string())); + + fs.create_directories(archives_dir, ec); + + fs.rename(tmp_archive_path, archive_path); + + System::println("Stored binary cache: %s", archive_path.u8string()); + } + } return {BuildResult::SUCCEEDED, std::move(bcf)}; } @@ -549,6 +691,26 @@ namespace vcpkg::Build const fs::path ports_cmake_script_path = paths.scripts / "get_triplet_environment.cmake"; const fs::path triplet_file_path = paths.triplets / (triplet.canonical_name() + ".cmake"); + auto triplet_abi_tag = [&]() { + static std::map s_hash_cache; + + if (GlobalState::g_binary_caching) + { + auto it_hash = s_hash_cache.find(triplet_file_path); + if (it_hash != s_hash_cache.end()) + { + return it_hash->second; + } + auto hash = Commands::Hash::get_file_hash(paths.get_cmake_exe(), triplet_file_path, "SHA1"); + s_hash_cache.emplace(triplet_file_path, hash); + return hash; + } + else + { + return std::string(); + } + }(); + const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path, ports_cmake_script_path, { @@ -560,6 +722,7 @@ namespace vcpkg::Build const std::vector lines = Strings::split(ec_data.output, "\n"); PreBuildInfo pre_build_info; + pre_build_info.triplet_abi_tag = triplet_abi_tag; const auto e = lines.cend(); auto cur = std::find(lines.cbegin(), e, FLAG_GUID); diff --git a/toolsrc/src/vcpkg/globalstate.cpp b/toolsrc/src/vcpkg/globalstate.cpp index eac69d9f5..a4100acf7 100644 --- a/toolsrc/src/vcpkg/globalstate.cpp +++ b/toolsrc/src/vcpkg/globalstate.cpp @@ -9,6 +9,7 @@ namespace vcpkg std::atomic GlobalState::debugging(false); std::atomic GlobalState::feature_packages(true); + std::atomic GlobalState::g_binary_caching(false); std::atomic GlobalState::g_init_console_cp(0); std::atomic GlobalState::g_init_console_output_cp(0); diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp index 18acf8e12..8909e1552 100644 --- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp +++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp @@ -133,6 +133,15 @@ namespace vcpkg { parse_switch(false, "featurepackages", args.featurepackages); continue; + } + if (arg == "--binarycaching") + { + parse_switch(true, "binarycaching", args.binarycaching); + continue; + } + if (arg == "--no-binarycaching") + { + parse_switch(false, "binarycaching", args.binarycaching); continue; } -- cgit v1.2.3 From ef4febc7ef08d1aaa3fb97efadf09e2ad2b9464d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 28 Feb 2018 11:54:40 -0800 Subject: [vcpkg] Fix exporting packages with features-depending-on-features --- toolsrc/src/vcpkg/packagespec.cpp | 21 --------------------- toolsrc/src/vcpkg/statusparagraph.cpp | 31 ++++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 22 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/packagespec.cpp b/toolsrc/src/vcpkg/packagespec.cpp index a9e072094..789aaca80 100644 --- a/toolsrc/src/vcpkg/packagespec.cpp +++ b/toolsrc/src/vcpkg/packagespec.cpp @@ -112,27 +112,6 @@ namespace vcpkg }); } - std::vector PackageSpec::from_dependencies_of_port(const std::string& port, - const std::vector& dependencies, - const Triplet& triplet) - { - return Util::fmap(dependencies, [&](const std::string& spec_as_string) -> PackageSpec { - auto maybe_spec = PackageSpec::from_name_and_triplet(spec_as_string, triplet); - if (auto spec = maybe_spec.get()) - { - return std::move(*spec); - } - - const PackageSpecParseResult error_type = maybe_spec.error(); - Checks::exit_with_message(VCPKG_LINE_INFO, - "Invalid dependency [%s] in package [%s]\n" - "%s", - spec_as_string, - port, - vcpkg::to_string(error_type)); - }); - } - const std::string& PackageSpec::name() const { return this->m_name; } const Triplet& PackageSpec::triplet() const { return this->m_triplet; } diff --git a/toolsrc/src/vcpkg/statusparagraph.cpp b/toolsrc/src/vcpkg/statusparagraph.cpp index 05238ba8b..62d1d4b42 100644 --- a/toolsrc/src/vcpkg/statusparagraph.cpp +++ b/toolsrc/src/vcpkg/statusparagraph.cpp @@ -86,13 +86,42 @@ namespace vcpkg } std::vector InstalledPackageView::dependencies() const { + // accumulate all features in installed dependencies + // Todo: make this unneeded by collapsing all package dependencies into the core package auto deps = Util::fmap_flatten(features, [](const StatusParagraph* pgh) -> std::vector const& { return pgh->package.depends; }); + // Add the core paragraph dependencies to the list deps.insert(deps.end(), core->package.depends.begin(), core->package.depends.end()); auto&& spec = core->package.spec; - return PackageSpec::from_dependencies_of_port(spec.name(), deps, spec.triplet()); + + // + // This is a hack to work around existing installations that put featurespecs into binary packages + // (example: curl[core]) + for (auto&& dep : deps) + { + dep.erase(std::find(dep.begin(), dep.end(), '['), dep.end()); + } + Util::unstable_keep_if(deps, [&](auto&& e) { return e != spec.name(); }); + // + Util::sort_unique_erase(deps); + + return Util::fmap(deps, [&](const std::string& dep) -> PackageSpec { + auto maybe_dependency_spec = PackageSpec::from_name_and_triplet(dep, spec.triplet()); + if (auto dependency_spec = maybe_dependency_spec.get()) + { + return std::move(*dependency_spec); + } + + const PackageSpecParseResult error_type = maybe_dependency_spec.error(); + Checks::exit_with_message(VCPKG_LINE_INFO, + "Invalid dependency [%s] in package [%s]\n" + "%s", + dep, + spec.name(), + vcpkg::to_string(error_type)); + }); } } -- cgit v1.2.3 From bbbbfb9e79a201a7c479fbc9e8ca14cd8569703d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 28 Feb 2018 12:15:16 -0800 Subject: [vcpkg] Add tests for create_export_plan and remove unused arguments --- toolsrc/src/tests.plan.cpp | 94 ++++++++++++++++++++++++++++++++++++++ toolsrc/src/vcpkg/dependencies.cpp | 19 +++----- toolsrc/src/vcpkg/export.cpp | 9 ++-- 3 files changed, 104 insertions(+), 18 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index aae4d2ee4..08d3c1dab 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -997,4 +997,98 @@ namespace UnitTest1 features_check(&plan[1], "a", {"core", "a1"}); } }; + + class ExportPlanTests : public TestClass + { + TEST_METHOD(basic_export_scheme) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a"); + + auto plan = Dependencies::create_export_plan({spec_a}, status_db); + + Assert::AreEqual(size_t(1), plan.size()); + Assert::AreEqual("a", plan[0].spec.name().c_str()); + Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); + } + + TEST_METHOD(basic_export_scheme_with_recurse) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b", "a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a"); + auto spec_b = spec_map.emplace("b", "a"); + + auto plan = Dependencies::create_export_plan({spec_b}, status_db); + + Assert::AreEqual(size_t(2), plan.size()); + Assert::AreEqual("a", plan[0].spec.name().c_str()); + Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); + + Assert::AreEqual("b", plan[1].spec.name().c_str()); + Assert::IsTrue(plan[1].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); + } + + TEST_METHOD(basic_export_scheme_with_bystander) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a"); + auto spec_b = spec_map.emplace("b", "a"); + + auto plan = Dependencies::create_export_plan({spec_a}, status_db); + + Assert::AreEqual(size_t(1), plan.size()); + Assert::AreEqual("a", plan[0].spec.name().c_str()); + Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); + } + + TEST_METHOD(basic_export_scheme_with_missing) + { + StatusParagraphs status_db; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a"); + + auto plan = Dependencies::create_export_plan({spec_a}, status_db); + + Assert::AreEqual(size_t(1), plan.size()); + Assert::AreEqual("a", plan[0].spec.name().c_str()); + Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::NOT_BUILT); + } + + TEST_METHOD(basic_upgrade_scheme_with_features) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("b")); + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_feature_pgh("a", "a1", "b[core]")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}); + + auto plan = Dependencies::create_export_plan({spec_a}, status_db); + + Assert::AreEqual(size_t(2), plan.size()); + + Assert::AreEqual("b", plan[0].spec.name().c_str()); + Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); + + Assert::AreEqual("a", plan[1].spec.name().c_str()); + Assert::IsTrue(plan[1].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); + } + }; } diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index f4a371a2e..1f853014b 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -223,7 +223,7 @@ namespace vcpkg::Dependencies } ExportPlanAction::ExportPlanAction(const PackageSpec& spec, const RequestType& request_type) - : spec(spec), plan_type(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT), request_type(request_type) + : spec(spec), plan_type(ExportPlanType::NOT_BUILT), request_type(request_type) { } @@ -349,23 +349,16 @@ namespace vcpkg::Dependencies return Graphs::topological_sort(specs, RemoveAdjacencyProvider{status_db, installed_ports, specs_as_set}); } - std::vector create_export_plan(const PortFileProvider& port_file_provider, - const VcpkgPaths& paths, - const std::vector& specs, + std::vector create_export_plan(const std::vector& specs, const StatusParagraphs& status_db) { struct ExportAdjacencyProvider final : Graphs::AdjacencyProvider { - const VcpkgPaths& paths; const StatusParagraphs& status_db; - const PortFileProvider& provider; const std::unordered_set& specs_as_set; - ExportAdjacencyProvider(const VcpkgPaths& p, - const StatusParagraphs& s, - const PortFileProvider& prov, - const std::unordered_set& specs_as_set) - : paths(p), status_db(s), provider(prov), specs_as_set(specs_as_set) + ExportAdjacencyProvider(const StatusParagraphs& s, const std::unordered_set& specs_as_set) + : status_db(s), specs_as_set(specs_as_set) { } @@ -394,8 +387,8 @@ namespace vcpkg::Dependencies }; const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); - std::vector toposort = Graphs::topological_sort( - specs, ExportAdjacencyProvider{paths, status_db, port_file_provider, specs_as_set}); + std::vector toposort = + Graphs::topological_sort(specs, ExportAdjacencyProvider{status_db, specs_as_set}); return toposort; } diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index a9c407dd8..831058007 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -69,7 +69,7 @@ namespace vcpkg::Export static void print_plan(const std::map>& group_by_plan_type) { static constexpr std::array ORDER = {ExportPlanType::ALREADY_BUILT, - ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT}; + ExportPlanType::NOT_BUILT}; static constexpr Build::BuildPackageOptions build_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; @@ -92,7 +92,7 @@ namespace vcpkg::Export case ExportPlanType::ALREADY_BUILT: System::println("The following packages are already built and will be exported:\n%s", as_string); continue; - case ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT: + case ExportPlanType::NOT_BUILT: System::println("The following packages need to be built:\n%s", as_string); continue; default: Checks::unreachable(VCPKG_LINE_INFO); @@ -486,8 +486,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console // create the plan const StatusParagraphs status_db = database_load_check(paths); Dependencies::PathsPortFileProvider provider(paths); - std::vector export_plan = - Dependencies::create_export_plan(provider, paths, opts.specs, status_db); + std::vector export_plan = Dependencies::create_export_plan(opts.specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty"); std::map> group_by_plan_type; @@ -505,7 +504,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console "Additional packages (*) need to be exported to complete this operation."); } - const auto it = group_by_plan_type.find(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT); + const auto it = group_by_plan_type.find(ExportPlanType::NOT_BUILT); if (it != group_by_plan_type.cend() && !it->second.empty()) { System::println(System::Color::error, "There are packages that have not been built."); -- cgit v1.2.3 From bad51b04626f25d323433ec159af1d60f93cadb1 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 2 Mar 2018 08:59:17 -0800 Subject: [vcpkg] Improve handling of external toolchain files --- toolsrc/src/vcpkg/base/cofffilereader.cpp | 3 --- toolsrc/src/vcpkg/build.cpp | 9 ++++----- toolsrc/src/vcpkg/commands.env.cpp | 6 +++++- toolsrc/src/vcpkg/postbuildlint.cpp | 33 ++++++++++++++++++++----------- toolsrc/src/vcpkg/vcpkgpaths.cpp | 7 +------ 5 files changed, 32 insertions(+), 26 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp index 1927e0b5e..96d280108 100644 --- a/toolsrc/src/vcpkg/base/cofffilereader.cpp +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -306,8 +306,5 @@ namespace vcpkg::CoffFileReader return {std::vector(machine_types.cbegin(), machine_types.cend())}; } -#else - DllInfo read_dll(const fs::path& path) { exit(-1); } - LibInfo read_lib(const fs::path& path) { exit(-1); } #endif } diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 0486039b7..5870bd187 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -208,9 +208,7 @@ namespace vcpkg::Build std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset) { - if (pre_build_info.external_toolchain_file) - return Strings::format( - R"("%s" %s 2>&1)", toolset.vcvarsall.u8string(), Strings::join(" ", toolset.vcvarsall_options)); + if (pre_build_info.external_toolchain_file.has_value()) return ""; const char* tonull = " >nul"; if (GlobalState::debugging) @@ -479,8 +477,9 @@ namespace vcpkg::Build {"ALL_FEATURES", all_features}, }); - const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); - const std::string command = Strings::format(R"(%s && %s)", cmd_set_environment, cmd_launch_cmake); + auto command = make_build_env_cmd(pre_build_info, toolset); + if (!command.empty()) command.append(" && "); + command.append(cmd_launch_cmake); const auto timer = Chrono::ElapsedTimer::create_started(); diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp index 6e52383d8..f3beef6cd 100644 --- a/toolsrc/src/vcpkg/commands.env.cpp +++ b/toolsrc/src/vcpkg/commands.env.cpp @@ -21,7 +21,11 @@ namespace vcpkg::Commands::Env const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); const Toolset& toolset = paths.get_toolset(pre_build_info); - System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, toolset) + " && cmd"); + auto env_cmd = Build::make_build_env_cmd(pre_build_info, toolset); + if (env_cmd.empty()) + System::cmd_execute_clean("cmd"); + else + System::cmd_execute_clean(env_cmd + " && cmd"); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp index 2b427737a..a31518ad7 100644 --- a/toolsrc/src/vcpkg/postbuildlint.cpp +++ b/toolsrc/src/vcpkg/postbuildlint.cpp @@ -391,6 +391,7 @@ namespace vcpkg::PostBuildLint static LintStatus check_dll_architecture(const std::string& expected_architecture, const std::vector& files) { +#if defined(_WIN32) std::vector binaries_with_invalid_architecture; for (const fs::path& file : files) @@ -413,6 +414,7 @@ namespace vcpkg::PostBuildLint print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture); return LintStatus::ERROR_DETECTED; } +#endif return LintStatus::SUCCESS; } @@ -420,6 +422,7 @@ namespace vcpkg::PostBuildLint static LintStatus check_lib_architecture(const std::string& expected_architecture, const std::vector& files) { +#if defined(_WIN32) std::vector binaries_with_invalid_architecture; for (const fs::path& file : files) @@ -451,6 +454,7 @@ namespace vcpkg::PostBuildLint print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture); return LintStatus::ERROR_DETECTED; } +#endif return LintStatus::SUCCESS; } @@ -790,11 +794,15 @@ namespace vcpkg::PostBuildLint dlls.insert(dlls.cend(), debug_dlls.cbegin(), debug_dlls.cend()); dlls.insert(dlls.cend(), release_dlls.cbegin(), release_dlls.cend()); - error_count += check_exports_of_dlls(dlls, toolset.dumpbin); - error_count += check_uwp_bit_of_dlls(pre_build_info.cmake_system_name, dlls, toolset.dumpbin); - error_count += check_dll_architecture(pre_build_info.target_architecture, dlls); + if (!toolset.dumpbin.empty()) + { + error_count += check_exports_of_dlls(dlls, toolset.dumpbin); + error_count += check_uwp_bit_of_dlls(pre_build_info.cmake_system_name, dlls, toolset.dumpbin); + error_count += + check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info, pre_build_info); + } - error_count += check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info, pre_build_info); + error_count += check_dll_architecture(pre_build_info.target_architecture, dlls); break; } case Build::LinkageType::STATIC: @@ -805,17 +813,20 @@ namespace vcpkg::PostBuildLint error_count += check_bin_folders_are_not_present_in_static_build(fs, package_dir); - if (!build_info.policies.is_enabled(BuildPolicy::ONLY_RELEASE_CRT)) + if (!toolset.dumpbin.empty()) { + if (!build_info.policies.is_enabled(BuildPolicy::ONLY_RELEASE_CRT)) + { + error_count += check_crt_linkage_of_libs( + BuildType::value_of(Build::ConfigurationType::DEBUG, build_info.crt_linkage), + debug_libs, + toolset.dumpbin); + } error_count += check_crt_linkage_of_libs( - BuildType::value_of(Build::ConfigurationType::DEBUG, build_info.crt_linkage), - debug_libs, + BuildType::value_of(Build::ConfigurationType::RELEASE, build_info.crt_linkage), + release_libs, toolset.dumpbin); } - error_count += check_crt_linkage_of_libs( - BuildType::value_of(Build::ConfigurationType::RELEASE, build_info.crt_linkage), - release_libs, - toolset.dumpbin); break; } default: Checks::unreachable(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index f2b39c110..e62ef8662 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -628,13 +628,8 @@ namespace vcpkg ret.dumpbin = ""; ret.supported_architectures = { ToolsetArchOption{"", System::get_host_processor(), System::get_host_processor()}}; -#if defined(_WIN32) - ret.vcvarsall = "cmd"; - ret.vcvarsall_options = {"/c", "echo done"}; -#else - ret.vcvarsall = "true"; + ret.vcvarsall = ""; ret.vcvarsall_options = {}; -#endif ret.version = "external"; ret.visual_studio_root_path = ""; return ret; -- cgit v1.2.3 From 709ced580d1af1a0704660e355f5a3f0f06c8899 Mon Sep 17 00:00:00 2001 From: Jacob Zhong Date: Wed, 7 Mar 2018 10:19:24 +0800 Subject: Fix export information --- toolsrc/src/vcpkg/export.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 831058007..16c84f99d 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -228,6 +228,7 @@ namespace vcpkg::Export {fs::path{"scripts"} / "getWindowsSDK.ps1"}, {fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"}, {fs::path{"scripts"} / "getProgramFiles32bit.ps1"}, + {fs::path{"scripts"} / "VcpkgPowershellUtils.ps1"}, }; for (const fs::path& file : integration_files_relative_to_root) @@ -428,7 +429,7 @@ namespace vcpkg::Export { System::println( System::Color::success, R"(Files exported at: "%s")", raw_exported_dir_path.generic_string()); - print_next_step_info(export_to_path); + print_next_step_info(raw_exported_dir_path); } if (opts.nuget) -- cgit v1.2.3 From 1b4bc5e27eeb037c299d3f57e9bed7e3c20c6d76 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 7 Mar 2018 15:01:49 -0800 Subject: [vcpkg] Add case for exe path discovery for macos --- toolsrc/src/vcpkg/base/system.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index f71fd8445..e55db9461 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -7,6 +7,10 @@ #include +#if defined(__APPLE__) +# include +#endif + #pragma comment(lib, "Advapi32") namespace vcpkg::System @@ -31,7 +35,15 @@ namespace vcpkg::System const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); if (bytes == 0) std::abort(); return fs::path(buf, buf + bytes); -#else +#elif __APPLE__ + uint32_t size = 1024 * 32; + char buf[size] = {}; + bool result = _NSGetExecutablePath(buf, &size); + Checks::check_exit(VCPKG_LINE_INFO, result != -1, "Could not determine current executable path."); + std::unique_ptr canonicalPath (realpath(buf, NULL)); + Checks::check_exit(VCPKG_LINE_INFO, result != -1, "Could not determine current executable path."); + return fs::path(std::string(canonicalPath.get())); +#else /* LINUX */ std::array buf; auto written = readlink("/proc/self/exe", buf.data(), buf.size()); Checks::check_exit(VCPKG_LINE_INFO, written != -1, "Could not determine current executable path."); -- cgit v1.2.3 From 965e99cf268b32cc32e0599d99e6c9a1991e95f4 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 8 Mar 2018 23:51:55 -0800 Subject: [rttr] Fix executables. Fix read-only permissions. --- toolsrc/src/vcpkg/remove.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 3eaf991ce..32433b234 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -58,7 +58,7 @@ namespace vcpkg::Remove const auto status = fs.status(target, ec); if (ec) { - System::println(System::Color::error, "failed: %s", ec.message()); + System::println(System::Color::error, "failed: status(%s): %s", target.u8string(), ec.message()); continue; } @@ -71,12 +71,23 @@ namespace vcpkg::Remove fs.remove(target, ec); if (ec) { - System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); +#if defined(_WIN32) + fs::stdfs::permissions(target, fs::stdfs::perms::owner_all | fs::stdfs::perms::group_all, ec); + fs.remove(target, ec); + if (ec) + { + System::println( + System::Color::error, "failed: remove(%s): %s", target.u8string(), ec.message()); + } +#else + System::println( + System::Color::error, "failed: remove(%s): %s", target.u8string(), ec.message()); +#endif } } - else if (!fs::status_known(status)) + else if (!fs::stdfs::exists(status)) { - System::println(System::Color::warning, "Warning: unknown status: %s", target.u8string()); + System::println(System::Color::warning, "Warning: %s: file not found", target.u8string()); } else { -- cgit v1.2.3 From ac8b9a13e40082d24afa1fc06757d25136a35b20 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 6 Mar 2018 09:55:22 -0800 Subject: [vcpkg] Enable qualifiers to use ! for inversion --- toolsrc/src/vcpkg/sourceparagraph.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp index 2a9480538..0b4baf189 100644 --- a/toolsrc/src/vcpkg/sourceparagraph.cpp +++ b/toolsrc/src/vcpkg/sourceparagraph.cpp @@ -202,7 +202,15 @@ namespace vcpkg std::vector ret; for (auto&& dep : deps) { - if (dep.qualifier.empty() || t.canonical_name().find(dep.qualifier) != std::string::npos) + auto qualifiers = Strings::split(dep.qualifier, "&"); + if (std::all_of(qualifiers.begin(), qualifiers.end(), [&](const std::string& qualifier) { + if (qualifier.empty()) return true; + if (qualifier[0] == '!') + { + return t.canonical_name().find(qualifier.substr(1)) == std::string::npos; + } + return t.canonical_name().find(qualifier) != std::string::npos; + })) { ret.emplace_back(dep.name()); } -- cgit v1.2.3 From 63e1e1f7117df20c9fe445ed9db8a808fc611ea4 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 9 Mar 2018 21:53:29 -0800 Subject: [vcpkg] Fix issue in upgrade dependency resolution where self-referencing features cause cycles --- toolsrc/src/tests.plan.cpp | 30 +++++++++++++++++++++++++++++- toolsrc/src/vcpkg/dependencies.cpp | 2 +- 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 08d3c1dab..95056810c 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -996,6 +996,34 @@ namespace UnitTest1 features_check(&plan[1], "a", {"core", "a1"}); } + + TEST_METHOD(basic_upgrade_scheme_with_self_features) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_feature_pgh("a", "a1", "")); + pghs.push_back(make_status_feature_pgh("a", "a2", "a[a1]")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "", {{"a1", ""}, {"a2", "a[a1]"}}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(2), plan.size()); + + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + + Assert::AreEqual("a", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].install_action.has_value()); + Assert::IsTrue(plan[1].install_action.get()->feature_list == std::set{"core", "a1", "a2"}); + } }; class ExportPlanTests : public TestClass @@ -1069,7 +1097,7 @@ namespace UnitTest1 Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::NOT_BUILT); } - TEST_METHOD(basic_upgrade_scheme_with_features) + TEST_METHOD(basic_export_scheme_with_features) { std::vector> pghs; pghs.push_back(make_status_pgh("b")); diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 1f853014b..1d017a8d3 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -530,7 +530,7 @@ namespace vcpkg::Dependencies for (auto&& depend : remove_edges_edges) { auto& depend_cluster = graph.get(depend.spec()); - graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); + if (&depend_cluster != &cluster) graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); mark_minus(depend_cluster, graph, graph_plan); } } -- cgit v1.2.3 From 6670b87c18c544bbc9fa167f583b27dc52bce3d9 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 10 Mar 2018 14:19:07 -0800 Subject: [vcpkg] Add VCPKG_DEFAULT_VS_PATH environment variable --- toolsrc/src/vcpkg.cpp | 4 +++- toolsrc/src/vcpkg/vcpkgpaths.cpp | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index ef68e6f72..d9b915367 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -94,7 +94,9 @@ static void inner(const VcpkgCmdArguments& args) Checks::check_exit(VCPKG_LINE_INFO, !vcpkg_root_dir.empty(), "Error: Could not detect vcpkg-root."); - const Expected expected_paths = VcpkgPaths::create(vcpkg_root_dir); + auto default_vs_path = System::get_environment_variable("VCPKG_DEFAULT_VS_PATH").value_or(""); + + const Expected expected_paths = VcpkgPaths::create(vcpkg_root_dir, default_vs_path); Checks::check_exit(VCPKG_LINE_INFO, !expected_paths.error(), "Error: Invalid vcpkg root directory %s: %s", diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index e62ef8662..02bc5f041 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -293,7 +293,7 @@ namespace vcpkg return fetch_tool(paths.scripts, "installerbase", TOOL_DATA); } - Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir) + Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir, const std::string& default_vs_path) { std::error_code ec; const fs::path canonical_vcpkg_root_dir = fs::stdfs::canonical(vcpkg_root_dir, ec); @@ -304,6 +304,7 @@ namespace vcpkg VcpkgPaths paths; paths.root = canonical_vcpkg_root_dir; + paths.default_vs_path = default_vs_path; if (paths.root.empty()) { @@ -643,7 +644,11 @@ namespace vcpkg std::vector candidates = Util::element_pointers(vs_toolsets); const auto tsv = prebuildinfo.platform_toolset.get(); - const auto vsp = prebuildinfo.visual_studio_path.get(); + auto vsp = prebuildinfo.visual_studio_path.get(); + if (!vsp && !default_vs_path.empty()) + { + vsp = &default_vs_path; + } if (tsv && vsp) { -- cgit v1.2.3 From ad7fa55bb004571bc7d2aad337dda978fe4d2bac Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 6 Mar 2018 09:57:37 -0800 Subject: [vcpkg] Improve handling of external toolchains. Extract MSVC settings to a separate toolchain file. --- toolsrc/src/vcpkg/build.cpp | 1 + toolsrc/src/vcpkg/vcpkgpaths.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 5870bd187..aa84b6cf5 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -209,6 +209,7 @@ namespace vcpkg::Build std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset) { if (pre_build_info.external_toolchain_file.has_value()) return ""; + if (!pre_build_info.cmake_system_name.empty() && pre_build_info.cmake_system_name != "WindowsStore") return ""; const char* tonull = " >nul"; if (GlobalState::debugging) diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 02bc5f041..46e80c4a9 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -622,7 +622,8 @@ namespace vcpkg const Toolset& VcpkgPaths::get_toolset(const Build::PreBuildInfo& prebuildinfo) const { - if (prebuildinfo.external_toolchain_file) + if (prebuildinfo.external_toolchain_file || + (!prebuildinfo.cmake_system_name.empty() && prebuildinfo.cmake_system_name != "WindowsStore")) { static Toolset external_toolset = []() -> Toolset { Toolset ret; -- cgit v1.2.3 From 81b58d1868a0f7edf324b2f366426e2973ac80b7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 9 Mar 2018 03:51:19 -0800 Subject: [vcpkg] Use unzip/zip on non-windows --- toolsrc/src/vcpkg/build.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index aa84b6cf5..408dde798 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -438,10 +438,15 @@ namespace vcpkg::Build auto files = fs.get_files_non_recursive(pkg_path); Checks::check_exit(VCPKG_LINE_INFO, files.empty(), "unable to clear path: %s", pkg_path.u8string()); +#if defined(_WIN32) auto&& _7za = paths.get_7za_exe(); System::cmd_execute_clean(Strings::format( R"("%s" x "%s" -o"%s" -y >nul)", _7za.u8string(), archive_path.u8string(), pkg_path.u8string())); +#else + System::cmd_execute_clean(Strings::format( + R"(unzip -qq "%s" "-d%s")", archive_path.u8string(), pkg_path.u8string())); +#endif auto maybe_bcf = Paragraphs::try_load_cached_control_package(paths, spec); bcf = std::make_unique(std::move(maybe_bcf).value_or_exit(VCPKG_LINE_INFO)); @@ -538,6 +543,7 @@ namespace vcpkg::Build !fs.exists(tmp_archive_path), "Could not remove file: %s", tmp_archive_path.u8string()); +#if defined(_WIN32) auto&& _7za = paths.get_7za_exe(); System::cmd_execute_clean(Strings::format( @@ -545,7 +551,12 @@ namespace vcpkg::Build _7za.u8string(), tmp_archive_path.u8string(), paths.package_dir(spec).u8string())); - +#else + System::cmd_execute_clean(Strings::format( + R"(cd '%s' && zip --quiet -r '%s' *)", + paths.package_dir(spec).u8string(), + tmp_archive_path.u8string())); +#endif fs.create_directories(archives_dir, ec); fs.rename(tmp_archive_path, archive_path); -- cgit v1.2.3 From 81b9ab1291bd322b5de8ad0cec2f21ce4d828a28 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 13 Mar 2018 04:26:00 -0700 Subject: [vcpkg] Refactor do_build_package and add archive tombstoning --- toolsrc/src/vcpkg/build.cpp | 238 +++++++++++++++++++++------------------ toolsrc/src/vcpkg/install.cpp | 2 +- toolsrc/src/vcpkg/paragraphs.cpp | 2 +- 3 files changed, 131 insertions(+), 111 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 408dde798..7abd5ae0a 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -315,8 +315,90 @@ namespace vcpkg::Build } static ExtendedBuildResult do_build_package(const VcpkgPaths& paths, + const PreBuildInfo& pre_build_info, + const PackageSpec& spec, + const std::string& abi_tag, const BuildPackageConfig& config, const StatusParagraphs& status_db) + { + auto& fs = paths.get_filesystem(); + const Triplet& triplet = spec.triplet(); + + const fs::path& cmake_exe_path = paths.get_cmake_exe(); + const fs::path& git_exe_path = paths.get_git_exe(); + + std::string all_features; + for (auto& feature : config.scf.feature_paragraphs) + { + all_features.append(feature->name + ";"); + } + + const Toolset& toolset = paths.get_toolset(pre_build_info); + const std::string cmd_launch_cmake = System::make_cmake_cmd( + cmake_exe_path, + paths.ports_cmake, + { + {"CMD", "BUILD"}, + {"PORT", config.scf.core_paragraph->name}, + {"CURRENT_PORT_DIR", config.port_dir / "/."}, + {"TARGET_TRIPLET", spec.triplet().canonical_name()}, + {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, + {"VCPKG_USE_HEAD_VERSION", + Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, + {"_VCPKG_NO_DOWNLOADS", !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, + {"GIT", git_exe_path}, + {"FEATURES", Strings::join(";", config.feature_list)}, + {"ALL_FEATURES", all_features}, + }); + + auto command = make_build_env_cmd(pre_build_info, toolset); + if (!command.empty()) command.append(" && "); + command.append(cmd_launch_cmake); + + const auto timer = Chrono::ElapsedTimer::create_started(); + + const int return_code = System::cmd_execute_clean(command); + const auto buildtimeus = timer.microseconds(); + const auto spec_string = spec.to_string(); + + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_buildtime(spec.to_string() + ":[" + Strings::join(",", config.feature_list) + "]", + buildtimeus); + if (return_code != 0) + { + locked_metrics->track_property("error", "build failed"); + locked_metrics->track_property("build_error", spec_string); + return BuildResult::BUILD_FAILED; + } + } + + const BuildInfo build_info = read_build_info(fs, paths.build_info_file_path(spec)); + const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); + + auto bcf = create_binary_control_file(*config.scf.core_paragraph, triplet, build_info, abi_tag); + + if (error_count != 0) + { + return BuildResult::POST_BUILD_CHECKS_FAILED; + } + for (auto&& feature : config.feature_list) + { + for (auto&& f_pgh : config.scf.feature_paragraphs) + { + if (f_pgh->name == feature) + bcf->features.push_back( + create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet)); + } + } + + write_binary_control_file(paths, *bcf); + return {BuildResult::SUCCEEDED, std::move(bcf)}; + } + + ExtendedBuildResult build_package(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const StatusParagraphs& status_db) { auto& fs = paths.get_filesystem(); const Triplet& triplet = config.triplet; @@ -359,9 +441,6 @@ namespace vcpkg::Build } const fs::path& cmake_exe_path = paths.get_cmake_exe(); - const fs::path& git_exe_path = paths.get_git_exe(); - - const fs::path ports_cmake_script_path = paths.ports_cmake; if (GlobalState::g_binary_caching) { @@ -420,124 +499,66 @@ namespace vcpkg::Build std::unique_ptr bcf; - auto archives_dir = paths.root / "archives"; - if (!abi_tag.empty()) - { - archives_dir /= abi_tag.substr(0, 2); - } - auto archive_path = archives_dir / (abi_tag + ".zip"); + auto archives_root_dir = paths.root / "archives"; + auto archive_name = abi_tag + ".zip"; + auto archive_subpath = abi_tag.empty() ? fs::path() : fs::u8path(abi_tag.substr(0, 2)) / archive_name; + auto archive_path = archives_root_dir / archive_subpath; + auto archive_tombstone_path = archives_root_dir / "fail" / archive_subpath; - if (GlobalState::g_binary_caching && !abi_tag.empty() && fs.exists(archive_path)) + auto found_archive = false; + + if (GlobalState::g_binary_caching && !abi_tag.empty()) { - System::println("Using cached binary package: %s", archive_path.u8string()); + if (fs.exists(archive_path)) + { + System::println("Using cached binary package: %s", archive_path.u8string()); - auto pkg_path = paths.package_dir(spec); - std::error_code ec; - fs.remove_all(pkg_path, ec); - fs.create_directories(pkg_path, ec); - auto files = fs.get_files_non_recursive(pkg_path); - Checks::check_exit(VCPKG_LINE_INFO, files.empty(), "unable to clear path: %s", pkg_path.u8string()); + auto pkg_path = paths.package_dir(spec); + std::error_code ec; + fs.remove_all(pkg_path, ec); + fs.create_directories(pkg_path, ec); + auto files = fs.get_files_non_recursive(pkg_path); + Checks::check_exit(VCPKG_LINE_INFO, files.empty(), "unable to clear path: %s", pkg_path.u8string()); #if defined(_WIN32) - auto&& _7za = paths.get_7za_exe(); + auto&& _7za = paths.get_7za_exe(); - System::cmd_execute_clean(Strings::format( - R"("%s" x "%s" -o"%s" -y >nul)", _7za.u8string(), archive_path.u8string(), pkg_path.u8string())); + System::cmd_execute_clean(Strings::format( + R"("%s" x "%s" -o"%s" -y >nul)", _7za.u8string(), archive_path.u8string(), pkg_path.u8string())); #else - System::cmd_execute_clean(Strings::format( - R"(unzip -qq "%s" "-d%s")", archive_path.u8string(), pkg_path.u8string())); + System::cmd_execute_clean(Strings::format( + R"(unzip -qq "%s" "-d%s")", archive_path.u8string(), pkg_path.u8string())); #endif - auto maybe_bcf = Paragraphs::try_load_cached_control_package(paths, spec); - bcf = std::make_unique(std::move(maybe_bcf).value_or_exit(VCPKG_LINE_INFO)); - } - else - { - if (GlobalState::g_binary_caching && !abi_tag.empty()) - { - System::println("Could not locate cached archive: %s", archive_path.u8string()); + auto maybe_bcf = Paragraphs::try_load_cached_package(paths, spec); + bcf = std::make_unique(std::move(maybe_bcf).value_or_exit(VCPKG_LINE_INFO)); + found_archive = true; + return {BuildResult::SUCCEEDED, std::move(bcf)}; } - - std::string all_features; - for (auto& feature : config.scf.feature_paragraphs) + else if (fs.exists(archive_tombstone_path)) { - all_features.append(feature->name + ";"); - } - - const Toolset& toolset = paths.get_toolset(pre_build_info); - const std::string cmd_launch_cmake = System::make_cmake_cmd( - cmake_exe_path, - ports_cmake_script_path, - { - {"CMD", "BUILD"}, - {"PORT", config.scf.core_paragraph->name}, - {"CURRENT_PORT_DIR", config.port_dir / "/."}, - {"TARGET_TRIPLET", triplet.canonical_name()}, - {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, - {"VCPKG_USE_HEAD_VERSION", - Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, - {"_VCPKG_NO_DOWNLOADS", - !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, - {"GIT", git_exe_path}, - {"FEATURES", features}, - {"ALL_FEATURES", all_features}, - }); - - auto command = make_build_env_cmd(pre_build_info, toolset); - if (!command.empty()) command.append(" && "); - command.append(cmd_launch_cmake); - - const auto timer = Chrono::ElapsedTimer::create_started(); - - const int return_code = System::cmd_execute_clean(command); - const auto buildtimeus = timer.microseconds(); - const auto spec_string = spec.to_string(); - - { - auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_buildtime(spec.to_string() + ":[" + Strings::join(",", config.feature_list) + "]", - buildtimeus); - if (return_code != 0) - { - locked_metrics->track_property("error", "build failed"); - locked_metrics->track_property("build_error", spec_string); - return BuildResult::BUILD_FAILED; - } + System::println("Found failure tombstone: %s", archive_tombstone_path.u8string()); + return BuildResult::BUILD_FAILED; } + } - const BuildInfo build_info = read_build_info(fs, paths.build_info_file_path(spec)); - const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); + if (GlobalState::g_binary_caching && !abi_tag.empty()) + { + System::println("Could not locate cached archive: %s", archive_path.u8string()); + } - bcf = create_binary_control_file(*config.scf.core_paragraph, triplet, build_info, abi_tag); + ExtendedBuildResult result = do_build_package(paths, pre_build_info, spec, abi_tag, config, status_db); - if (error_count != 0) - { - return BuildResult::POST_BUILD_CHECKS_FAILED; - } - for (auto&& feature : config.feature_list) + if (GlobalState::g_binary_caching && !abi_tag.empty()) + { + if (result.code == BuildResult::SUCCEEDED) { - for (auto&& f_pgh : config.scf.feature_paragraphs) - { - if (f_pgh->name == feature) - bcf->features.push_back( - create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet)); - } - } + auto tmp_archive_path = paths.buildtrees / spec.name() / (triplet.to_string() + ".zip"); - if (GlobalState::g_binary_caching && !abi_tag.empty()) - { std::error_code ec; fs.write_contents( paths.package_dir(spec) / "share" / spec.name() / "vcpkg_abi_info.txt", full_abi_info, ec); - } - - write_binary_control_file(paths, *bcf); - if (GlobalState::g_binary_caching && !abi_tag.empty()) - { - auto tmp_archive_path = paths.buildtrees / spec.name() / (spec.triplet().to_string() + ".zip"); - - std::error_code ec; fs.remove(tmp_archive_path, ec); Checks::check_exit(VCPKG_LINE_INFO, !fs.exists(tmp_archive_path), @@ -557,21 +578,20 @@ namespace vcpkg::Build paths.package_dir(spec).u8string(), tmp_archive_path.u8string())); #endif - fs.create_directories(archives_dir, ec); + fs.create_directories(archive_path.parent_path(), ec); fs.rename(tmp_archive_path, archive_path); System::println("Stored binary cache: %s", archive_path.u8string()); } + else if (result.code == BuildResult::BUILD_FAILED || result.code == BuildResult::POST_BUILD_CHECKS_FAILED) + { + // Build failed, so store failure archive + std::error_code ec; + fs.create_directories(archive_tombstone_path.parent_path(), ec); + fs.write_contents(archive_tombstone_path, "", ec); + } } - return {BuildResult::SUCCEEDED, std::move(bcf)}; - } - - ExtendedBuildResult build_package(const VcpkgPaths& paths, - const BuildPackageConfig& config, - const StatusParagraphs& status_db) - { - ExtendedBuildResult result = do_build_package(paths, config, status_db); if (config.build_package_options.clean_buildtrees == CleanBuildtrees::YES) { diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 46c7c53b8..7d36fba82 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -306,7 +306,7 @@ namespace vcpkg::Install System::println("Building package %s... done", display_name_with_features); auto bcf = std::make_unique( - Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO)); + Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO)); auto code = aux_install(display_name_with_features, *bcf); if (action.build_options.clean_packages == Build::CleanPackages::YES) diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp index b66d53994..d0b0c0abf 100644 --- a/toolsrc/src/vcpkg/paragraphs.cpp +++ b/toolsrc/src/vcpkg/paragraphs.cpp @@ -228,7 +228,7 @@ namespace vcpkg::Paragraphs return error_info; } - Expected try_load_cached_control_package(const VcpkgPaths& paths, const PackageSpec& spec) + Expected try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec) { Expected>> pghs = get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL"); -- cgit v1.2.3 From f72b46690a89a7e19563f93f0eaa5f8a21184254 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 13 Mar 2018 06:25:59 -0700 Subject: [vcpkg] Silence warnings on recent clang --- toolsrc/src/vcpkg/metrics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index d49cadbe2..9e17b237d 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -92,7 +92,7 @@ namespace vcpkg::Metrics { encoded.append("\\\""); } - else if (ch < 0x20 || ch >= 0x80) + else if (ch < 0x20 || static_cast(ch) >= 0x80) { // Note: this treats incoming Strings as Latin-1 static constexpr const char HEX[16] = { -- cgit v1.2.3 From 50a93f01970e499f35edbb57ce0328baeb465635 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 13 Mar 2018 07:32:51 -0700 Subject: [vcpkg] Fix get_executable_path on BSD --- toolsrc/src/vcpkg/base/system.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index e55db9461..e24098f97 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -8,7 +8,11 @@ #include #if defined(__APPLE__) -# include +#include +#endif + +#if defined(__FreeBSD__) +#include #endif #pragma comment(lib, "Advapi32") @@ -35,14 +39,22 @@ namespace vcpkg::System const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); if (bytes == 0) std::abort(); return fs::path(buf, buf + bytes); -#elif __APPLE__ +#elif defined(__APPLE__) uint32_t size = 1024 * 32; char buf[size] = {}; bool result = _NSGetExecutablePath(buf, &size); Checks::check_exit(VCPKG_LINE_INFO, result != -1, "Could not determine current executable path."); - std::unique_ptr canonicalPath (realpath(buf, NULL)); + std::unique_ptr canonicalPath(realpath(buf, NULL)); Checks::check_exit(VCPKG_LINE_INFO, result != -1, "Could not determine current executable path."); return fs::path(std::string(canonicalPath.get())); +#elif defined(__FreeBSD__) + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; + char exePath[2048]; + size_t len = sizeof(exePath); + auto rcode = sysctl(mib, 4, exePath, &len, NULL, 0); + Checks::check_exit(VCPKG_LINE_INFO, rcode == 0, "Could not determine current executable path."); + Checks::check_exit(VCPKG_LINE_INFO, len > 0, "Could not determine current executable path."); + return fs::path(exePath, exePath + len - 1); #else /* LINUX */ std::array buf; auto written = readlink("/proc/self/exe", buf.data(), buf.size()); -- cgit v1.2.3 From 3c7997215bc2e44125912fb7aae672f1b63944a8 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 13 Mar 2018 11:06:22 -0700 Subject: [vcpkg] Improve default triplets for non-windows --- toolsrc/src/vcpkg.cpp | 8 ++++++++ toolsrc/src/vcpkg/base/strings.cpp | 7 +++---- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index d9b915367..a65045aa8 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -157,7 +157,15 @@ static void inner(const VcpkgCmdArguments& args) } else { +#if defined(_WIN32) default_triplet = Triplet::X86_WINDOWS; +#elif defined(__APPLE__) + default_triplet = Triplet::from_canonical_name("x64-osx"); +#elif defined(__FreeBSD__) + default_triplet = Triplet::from_canonical_name("x64-freebsd"); +#else + default_triplet = Triplet::from_canonical_name("x64-linux"); +#endif } } diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index d912734e3..a08512c9f 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -108,11 +108,10 @@ namespace vcpkg::Strings #endif } - std::string ascii_to_lowercase(const std::string& input) + std::string ascii_to_lowercase(std::string s) { - std::string output(input); - std::transform(output.begin(), output.end(), output.begin(), &details::tolower_char); - return output; + std::transform(s.begin(), s.end(), s.begin(), &details::tolower_char); + return s; } bool case_insensitive_ascii_starts_with(const std::string& s, const std::string& pattern) -- cgit v1.2.3 From 90c4b8dbb7a69584a4a36c67e4982cf086b7c578 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 14 Mar 2018 04:33:14 -0700 Subject: [vcpkg] Further refactoring inside `build_package()` --- toolsrc/src/vcpkg/build.cpp | 320 ++++++++++++++++++++---------------- toolsrc/src/vcpkg/commands.ci.cpp | 21 ++- toolsrc/src/vcpkg/commands.hash.cpp | 8 +- 3 files changed, 201 insertions(+), 148 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 7abd5ae0a..99ae5d2a3 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -396,23 +396,160 @@ namespace vcpkg::Build return {BuildResult::SUCCEEDED, std::move(bcf)}; } - ExtendedBuildResult build_package(const VcpkgPaths& paths, - const BuildPackageConfig& config, - const StatusParagraphs& status_db) + static ExtendedBuildResult do_build_package_and_clean_buildtrees(const VcpkgPaths& paths, + const PreBuildInfo& pre_build_info, + const PackageSpec& spec, + const std::string& abi_tag, + const BuildPackageConfig& config, + const StatusParagraphs& status_db) { + auto result = do_build_package(paths, pre_build_info, spec, abi_tag, config, status_db); + + if (config.build_package_options.clean_buildtrees == CleanBuildtrees::YES) + { + auto& fs = paths.get_filesystem(); + const fs::path buildtrees_dir = paths.buildtrees / config.scf.core_paragraph->name; + auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir); + for (auto&& file : buildtree_files) + { + if (fs.is_directory(file) && file.filename() != "src") + { + std::error_code ec; + fs.remove_all(file, ec); + } + } + } + + return result; + } + + struct AbiEntry + { + std::string key; + std::string value; + }; + + struct AbiTagAndFile + { + std::string tag; + fs::path tag_file; + }; + + static Optional compute_abi_tag(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const PreBuildInfo& pre_build_info, + Span dependency_abis) + { + if (!GlobalState::g_binary_caching) return nullopt; + auto& fs = paths.get_filesystem(); const Triplet& triplet = config.triplet; + const std::string& name = config.scf.core_paragraph->name; + + std::vector abi_tag_entries; + + abi_tag_entries.insert(abi_tag_entries.end(), dependency_abis.begin(), dependency_abis.end()); + + abi_tag_entries.emplace_back( + AbiEntry{"portfile", Commands::Hash::get_file_hash(paths, config.port_dir / "portfile.cmake", "SHA1")}); + abi_tag_entries.emplace_back( + AbiEntry{"control", Commands::Hash::get_file_hash(paths, config.port_dir / "CONTROL", "SHA1")}); + + abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag}); + + std::string features = Strings::join(";", config.feature_list); + abi_tag_entries.emplace_back(AbiEntry{"features", features}); - struct AbiEntry + if (config.build_package_options.use_head_version == UseHeadVersion::YES) + abi_tag_entries.emplace_back(AbiEntry{"head", ""}); + + std::string full_abi_info = + Strings::join("", abi_tag_entries, [](const AbiEntry& p) { return p.key + " " + p.value + "\n"; }); + + if (GlobalState::debugging) { - std::string key; - std::string value; - }; + System::println("[DEBUG] "); + for (auto&& entry : abi_tag_entries) + { + System::println("[DEBUG] %s|%s", entry.key, entry.value); + } + System::println("[DEBUG] "); + } - std::vector abi_tag_entries; + auto abi_tag_entries_missing = abi_tag_entries; + Util::stable_keep_if(abi_tag_entries_missing, [](const AbiEntry& p) { return p.value.empty(); }); - const PackageSpec spec = - PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, triplet).value_or_exit(VCPKG_LINE_INFO); + if (abi_tag_entries_missing.empty()) + { + std::error_code ec; + fs.create_directories(paths.buildtrees / name, ec); + auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt"); + fs.write_contents(abi_file_path, full_abi_info); + + return AbiTagAndFile{Commands::Hash::get_file_hash(paths, abi_file_path, "SHA1"), abi_file_path}; + } + else + { + System::println( + "Warning: binary caching disabled because abi keys are missing values:\n%s", + Strings::join("", abi_tag_entries_missing, [](const AbiEntry& e) { return " " + e.key + "\n"; })); + + return nullopt; + } + } + + static void decompress_archive(const VcpkgPaths& paths, const PackageSpec& spec, const fs::path& archive_path) + { + auto& fs = paths.get_filesystem(); + + auto pkg_path = paths.package_dir(spec); + std::error_code ec; + fs.remove_all(pkg_path, ec); + fs.create_directories(pkg_path, ec); + auto files = fs.get_files_non_recursive(pkg_path); + Checks::check_exit(VCPKG_LINE_INFO, files.empty(), "unable to clear path: %s", pkg_path.u8string()); + +#if defined(_WIN32) + auto&& _7za = paths.get_7za_exe(); + + System::cmd_execute_clean(Strings::format( + R"("%s" x "%s" -o"%s" -y >nul)", _7za.u8string(), archive_path.u8string(), pkg_path.u8string())); +#else + System::cmd_execute_clean(Strings::format( + R"(unzip -qq "%s" "-d%s")", archive_path.u8string(), pkg_path.u8string())); +#endif + } + + static void compress_archive(const VcpkgPaths& paths, const PackageSpec& spec, const fs::path& tmp_archive_path) + { + auto& fs = paths.get_filesystem(); + + std::error_code ec; + + fs.remove(tmp_archive_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !fs.exists(tmp_archive_path), "Could not remove file: %s", tmp_archive_path.u8string()); +#if defined(_WIN32) + auto&& _7za = paths.get_7za_exe(); + + System::cmd_execute_clean(Strings::format( + R"("%s" a "%s" "%s\*" >nul)", + _7za.u8string(), + tmp_archive_path.u8string(), + paths.package_dir(spec).u8string())); +#else + System::cmd_execute_clean(Strings::format( + R"(cd '%s' && zip --quiet -r '%s' *)", paths.package_dir(spec).u8string(), tmp_archive_path.u8string())); +#endif + } + + ExtendedBuildResult build_package(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const StatusParagraphs& status_db) + { + auto& fs = paths.get_filesystem(); + const Triplet& triplet = config.triplet; + const std::string& name = config.scf.core_paragraph->name; std::vector required_fspecs = compute_required_feature_specs(config, status_db); @@ -422,7 +559,7 @@ namespace vcpkg::Build // Find all features that aren't installed. This destroys required_fspecs. Util::unstable_keep_if(required_fspecs, [&](FeatureSpec const& fspec) { - return !status_db.is_installed(fspec) && fspec.name() != spec.name(); + return !status_db.is_installed(fspec) && fspec.name() != name; }); if (!required_fspecs.empty()) @@ -430,109 +567,45 @@ namespace vcpkg::Build return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; } + const PackageSpec spec = + PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, triplet).value_or_exit(VCPKG_LINE_INFO); + + std::vector dependency_abis; + // dep_pspecs was not destroyed for (auto&& pspec : dep_pspecs) { if (pspec == spec) continue; auto status_it = status_db.find_installed(pspec); Checks::check_exit(VCPKG_LINE_INFO, status_it != status_db.end()); - abi_tag_entries.emplace_back( + dependency_abis.emplace_back( AbiEntry{status_it->get()->package.spec.name(), status_it->get()->package.abi}); } - const fs::path& cmake_exe_path = paths.get_cmake_exe(); - - if (GlobalState::g_binary_caching) - { - abi_tag_entries.emplace_back(AbiEntry{ - "portfile", Commands::Hash::get_file_hash(cmake_exe_path, config.port_dir / "portfile.cmake", "SHA1")}); - abi_tag_entries.emplace_back(AbiEntry{ - "control", Commands::Hash::get_file_hash(cmake_exe_path, config.port_dir / "CONTROL", "SHA1")}); - } - const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); - abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag}); - std::string features = Strings::join(";", config.feature_list); - abi_tag_entries.emplace_back(AbiEntry{"features", features}); - - if (config.build_package_options.use_head_version == UseHeadVersion::YES) - abi_tag_entries.emplace_back(AbiEntry{"head", ""}); - - std::string full_abi_info = - Strings::join("", abi_tag_entries, [](const AbiEntry& p) { return p.key + " " + p.value + "\n"; }); - - std::string abi_tag; - - if (GlobalState::g_binary_caching) - { - if (GlobalState::debugging) - { - System::println("[DEBUG] "); - for (auto&& entry : abi_tag_entries) - { - System::println("[DEBUG] %s|%s", entry.key, entry.value); - } - System::println("[DEBUG] "); - } - - auto abi_tag_entries_missing = abi_tag_entries; - Util::stable_keep_if(abi_tag_entries_missing, [](const AbiEntry& p) { return p.value.empty(); }); - - if (abi_tag_entries_missing.empty()) - { - std::error_code ec; - fs.create_directories(paths.buildtrees / spec.name(), ec); - auto abi_file_path = paths.buildtrees / spec.name() / "vcpkg_abi_info"; - fs.write_contents(abi_file_path, full_abi_info); - - abi_tag = Commands::Hash::get_file_hash(paths.get_cmake_exe(), abi_file_path, "SHA1"); - } - else - { - System::println("Warning: binary caching disabled because abi keys are missing values:\n%s", - Strings::join("", abi_tag_entries_missing, [](const AbiEntry& e) { - return " " + e.key + "\n"; - })); - } - } + auto abi_tag_and_file = compute_abi_tag(paths, config, pre_build_info, dependency_abis); std::unique_ptr bcf; - auto archives_root_dir = paths.root / "archives"; - auto archive_name = abi_tag + ".zip"; - auto archive_subpath = abi_tag.empty() ? fs::path() : fs::u8path(abi_tag.substr(0, 2)) / archive_name; - auto archive_path = archives_root_dir / archive_subpath; - auto archive_tombstone_path = archives_root_dir / "fail" / archive_subpath; + auto maybe_abi_tag_and_file = abi_tag_and_file.get(); - auto found_archive = false; - - if (GlobalState::g_binary_caching && !abi_tag.empty()) + if (GlobalState::g_binary_caching && maybe_abi_tag_and_file) { + auto archives_root_dir = paths.root / "archives"; + auto archive_name = maybe_abi_tag_and_file->tag + ".zip"; + auto archive_subpath = fs::u8path(maybe_abi_tag_and_file->tag.substr(0, 2)) / archive_name; + auto archive_path = archives_root_dir / archive_subpath; + auto archive_tombstone_path = archives_root_dir / "fail" / archive_subpath; + if (fs.exists(archive_path)) { System::println("Using cached binary package: %s", archive_path.u8string()); - auto pkg_path = paths.package_dir(spec); - std::error_code ec; - fs.remove_all(pkg_path, ec); - fs.create_directories(pkg_path, ec); - auto files = fs.get_files_non_recursive(pkg_path); - Checks::check_exit(VCPKG_LINE_INFO, files.empty(), "unable to clear path: %s", pkg_path.u8string()); - -#if defined(_WIN32) - auto&& _7za = paths.get_7za_exe(); - - System::cmd_execute_clean(Strings::format( - R"("%s" x "%s" -o"%s" -y >nul)", _7za.u8string(), archive_path.u8string(), pkg_path.u8string())); -#else - System::cmd_execute_clean(Strings::format( - R"(unzip -qq "%s" "-d%s")", archive_path.u8string(), pkg_path.u8string())); -#endif + decompress_archive(paths, spec, archive_path); auto maybe_bcf = Paragraphs::try_load_cached_package(paths, spec); bcf = std::make_unique(std::move(maybe_bcf).value_or_exit(VCPKG_LINE_INFO)); - found_archive = true; return {BuildResult::SUCCEEDED, std::move(bcf)}; } else if (fs.exists(archive_tombstone_path)) @@ -540,75 +613,42 @@ namespace vcpkg::Build System::println("Found failure tombstone: %s", archive_tombstone_path.u8string()); return BuildResult::BUILD_FAILED; } - } - if (GlobalState::g_binary_caching && !abi_tag.empty()) - { System::println("Could not locate cached archive: %s", archive_path.u8string()); - } - ExtendedBuildResult result = do_build_package(paths, pre_build_info, spec, abi_tag, config, status_db); + ExtendedBuildResult result = do_build_package_and_clean_buildtrees( + paths, pre_build_info, spec, abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); + + std::error_code ec; + auto abi_file_in_package = paths.package_dir(spec) / "share" / spec.name() / "vcpkg_abi_info.txt"; + fs.copy_file(maybe_abi_tag_and_file->tag_file, abi_file_in_package, fs::stdfs::copy_options::none, ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not copy into file: %s", abi_file_in_package.u8string()); - if (GlobalState::g_binary_caching && !abi_tag.empty()) - { if (result.code == BuildResult::SUCCEEDED) { - auto tmp_archive_path = paths.buildtrees / spec.name() / (triplet.to_string() + ".zip"); + auto tmp_archive_path = paths.buildtrees / spec.name() / (spec.triplet().to_string() + ".zip"); - std::error_code ec; - fs.write_contents( - paths.package_dir(spec) / "share" / spec.name() / "vcpkg_abi_info.txt", full_abi_info, ec); - - fs.remove(tmp_archive_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !fs.exists(tmp_archive_path), - "Could not remove file: %s", - tmp_archive_path.u8string()); -#if defined(_WIN32) - auto&& _7za = paths.get_7za_exe(); + compress_archive(paths, spec, tmp_archive_path); - System::cmd_execute_clean(Strings::format( - R"("%s" a "%s" "%s\*" >nul)", - _7za.u8string(), - tmp_archive_path.u8string(), - paths.package_dir(spec).u8string())); -#else - System::cmd_execute_clean(Strings::format( - R"(cd '%s' && zip --quiet -r '%s' *)", - paths.package_dir(spec).u8string(), - tmp_archive_path.u8string())); -#endif fs.create_directories(archive_path.parent_path(), ec); - fs.rename(tmp_archive_path, archive_path); System::println("Stored binary cache: %s", archive_path.u8string()); } else if (result.code == BuildResult::BUILD_FAILED || result.code == BuildResult::POST_BUILD_CHECKS_FAILED) { - // Build failed, so store failure archive - std::error_code ec; + // Build failed, so store tombstone archive fs.create_directories(archive_tombstone_path.parent_path(), ec); fs.write_contents(archive_tombstone_path, "", ec); } - } - if (config.build_package_options.clean_buildtrees == CleanBuildtrees::YES) + return result; + } + else { - auto& fs = paths.get_filesystem(); - const fs::path buildtrees_dir = paths.buildtrees / config.scf.core_paragraph->name; - auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir); - for (auto&& file : buildtree_files) - { - if (fs.is_directory(file) && file.filename() != "src") - { - std::error_code ec; - fs.remove_all(file, ec); - } - } + return do_build_package_and_clean_buildtrees( + paths, pre_build_info, spec, abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); } - - return result; } const std::string& to_string(const BuildResult build_result) @@ -732,7 +772,7 @@ namespace vcpkg::Build { return it_hash->second; } - auto hash = Commands::Hash::get_file_hash(paths.get_cmake_exe(), triplet_file_path, "SHA1"); + auto hash = Commands::Hash::get_file_hash(paths, triplet_file_path, "SHA1"); s_hash_cache.emplace(triplet_file_path, hash); return hash; } diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index c43f25b40..e01072a0a 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -24,6 +24,7 @@ namespace vcpkg::Commands::CI Install::InstallSummary summary; }; + static constexpr StringLiteral OPTION_DRY_RUN = "--dry-run"; static constexpr StringLiteral OPTION_EXCLUDE = "--exclude"; static constexpr StringLiteral OPTION_XUNIT = "--x-xunit"; @@ -32,11 +33,14 @@ namespace vcpkg::Commands::CI {OPTION_XUNIT, "File to output results in XUnit format (internal)"}, }}; + static constexpr std::array CI_SWITCHES = { + {{OPTION_DRY_RUN, "Print out plan without execution"}}}; + const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("ci x64-windows"), - 0, + 1, SIZE_MAX, - {{}, CI_SETTINGS}, + {CI_SWITCHES, CI_SETTINGS}, nullptr, }; @@ -52,6 +56,8 @@ namespace vcpkg::Commands::CI exclusions_set.insert(exclusions.begin(), exclusions.end()); } + auto is_dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN); + std::vector triplets; for (const std::string& triplet : args.command_arguments) { @@ -94,8 +100,15 @@ namespace vcpkg::Commands::CI } } - auto summary = Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db); - results.push_back({triplet, std::move(summary)}); + if (is_dry_run) + { + Dependencies::print_plan(action_plan); + } + else + { + auto summary = Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db); + results.push_back({triplet, std::move(summary)}); + } } for (auto&& result : results) diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index bbbbed036..cb0a8cc51 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -7,11 +7,11 @@ namespace vcpkg::Commands::Hash { - std::string get_file_hash(fs::path const& cmake_exe_path, fs::path const& path, std::string const& hash_type) + std::string get_file_hash(const VcpkgPaths& paths, fs::path const& path, std::string const& hash_type) { const std::string cmd_line = Strings::format( R"("%s" -E %ssum "%s")", - cmake_exe_path.u8string(), + paths.get_cmake_exe().u8string(), Strings::ascii_to_lowercase(hash_type), path.u8string()); @@ -48,12 +48,12 @@ namespace vcpkg::Commands::Hash if (args.command_arguments.size() == 1) { - auto hash = get_file_hash(paths.get_cmake_exe(), args.command_arguments[0], "SHA512"); + auto hash = get_file_hash(paths, args.command_arguments[0], "SHA512"); System::println(hash); } if (args.command_arguments.size() == 2) { - auto hash = get_file_hash(paths.get_cmake_exe(), args.command_arguments[0], args.command_arguments[1]); + auto hash = get_file_hash(paths, args.command_arguments[0], args.command_arguments[1]); System::println(hash); } -- cgit v1.2.3 From 3a056235b85f34573903a7dc325d45e66549b6ff Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 14 Mar 2018 16:56:33 -0700 Subject: [vcpkg] Create minimal package structure even on failure --- toolsrc/src/vcpkg/build.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 99ae5d2a3..b71bdbf25 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -620,6 +620,7 @@ namespace vcpkg::Build paths, pre_build_info, spec, abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); std::error_code ec; + fs.create_directories(paths.package_dir(spec) / "share" / spec.name(), ec); auto abi_file_in_package = paths.package_dir(spec) / "share" / spec.name() / "vcpkg_abi_info.txt"; fs.copy_file(maybe_abi_tag_and_file->tag_file, abi_file_in_package, fs::stdfs::copy_options::none, ec); Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not copy into file: %s", abi_file_in_package.u8string()); -- cgit v1.2.3 From d253123055e6bdfb181c6a8a14a63e2d6fc68cad Mon Sep 17 00:00:00 2001 From: Jacob Zhong Date: Sun, 18 Mar 2018 20:24:19 +0800 Subject: Add options and documentation for env command (#3007) * [vcpkg] Add options and documentation for env command * [vcpkg-env] Cleanup. Add tools/*. --- toolsrc/src/vcpkg/base/system.cpp | 15 +++++++++-- toolsrc/src/vcpkg/commands.env.cpp | 54 +++++++++++++++++++++++++++++++++----- toolsrc/src/vcpkg/help.cpp | 6 +---- 3 files changed, 62 insertions(+), 13 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index e24098f97..f339afa51 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -153,12 +153,12 @@ namespace vcpkg::System R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args); } - int cmd_execute_clean(const CStringView cmd_line) + int cmd_execute_clean(const CStringView cmd_line, const std::unordered_map& extra_env) { #if defined(_WIN32) static const std::string SYSTEM_ROOT = get_environment_variable("SystemRoot").value_or_exit(VCPKG_LINE_INFO); static const std::string SYSTEM_32 = SYSTEM_ROOT + R"(\system32)"; - static const std::string NEW_PATH = Strings::format( + std::string NEW_PATH = Strings::format( R"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32); std::vector env_wstrings = { @@ -224,11 +224,22 @@ namespace vcpkg::System env_cstr.push_back(L'\0'); } + if (extra_env.find("PATH") != extra_env.end()) + NEW_PATH += Strings::format(";%s", extra_env.find("PATH")->second); env_cstr.append(Strings::to_utf16(NEW_PATH)); env_cstr.push_back(L'\0'); env_cstr.append(L"VSLANG=1033"); env_cstr.push_back(L'\0'); + for (auto item : extra_env) + { + if (item.first == "PATH") continue; + env_cstr.append(Strings::to_utf16(item.first)); + env_cstr.push_back(L'='); + env_cstr.append(Strings::to_utf16(item.second)); + env_cstr.push_back(L'\0'); + } + STARTUPINFOW startup_info; memset(&startup_info, 0, sizeof(STARTUPINFOW)); startup_info.cb = sizeof(STARTUPINFOW); diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp index f3beef6cd..d078baedb 100644 --- a/toolsrc/src/vcpkg/commands.env.cpp +++ b/toolsrc/src/vcpkg/commands.env.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include #include #include #include @@ -7,25 +8,66 @@ namespace vcpkg::Commands::Env { + static constexpr StringLiteral OPTION_BIN = "--bin"; + static constexpr StringLiteral OPTION_INCLUDE = "--include"; + static constexpr StringLiteral OPTION_DEBUG_BIN = "--debug-bin"; + static constexpr StringLiteral OPTION_TOOLS = "--tools"; + static constexpr StringLiteral OPTION_PYTHON = "--python"; + + static constexpr std::array SWITCHES = {{ + {OPTION_BIN, "Add installed bin/ to PATH"}, + {OPTION_INCLUDE, "Add installed include/ to INCLUDE"}, + {OPTION_DEBUG_BIN, "Add installed debug/bin/ to PATH"}, + {OPTION_TOOLS, "Add installed tools/*/ to PATH"}, + {OPTION_PYTHON, "Add installed python/ to PYTHONPATH"}, + }}; + const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("env --triplet x64-windows"), 0, 0, - {}, + {SWITCHES, {}}, nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& triplet) { - args.parse_arguments(COMMAND_STRUCTURE); + const auto& fs = paths.get_filesystem(); + + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); - const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); + const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, triplet); const Toolset& toolset = paths.get_toolset(pre_build_info); auto env_cmd = Build::make_build_env_cmd(pre_build_info, toolset); + + std::unordered_map extra_env = {}; + const bool add_bin = Util::Sets::contains(options.switches, OPTION_BIN); + const bool add_include = Util::Sets::contains(options.switches, OPTION_INCLUDE); + const bool add_debug_bin = Util::Sets::contains(options.switches, OPTION_DEBUG_BIN); + const bool add_tools = Util::Sets::contains(options.switches, OPTION_TOOLS); + const bool add_python = Util::Sets::contains(options.switches, OPTION_PYTHON); + + std::vector path_vars; + if (add_bin) path_vars.push_back((paths.installed / triplet.to_string() / "bin").u8string()); + if (add_debug_bin) path_vars.push_back((paths.installed / triplet.to_string() / "debug" / "bin").u8string()); + if (add_include) extra_env.emplace("INCLUDE", (paths.installed / triplet.to_string() / "include").u8string()); + if (add_tools) + { + auto tools_dir = paths.installed / triplet.to_string() / "tools"; + auto tool_files = fs.get_files_non_recursive(tools_dir); + path_vars.push_back(tools_dir.u8string()); + for (auto&& tool_dir : tool_files) + { + if (fs.is_directory(tool_dir)) path_vars.push_back(tool_dir.u8string()); + } + } + if (add_python) extra_env.emplace("PYTHONPATH", (paths.installed / triplet.to_string() / "python").u8string()); + if (path_vars.size() > 0) extra_env.emplace("PATH", Strings::join(";", path_vars)); + if (env_cmd.empty()) - System::cmd_execute_clean("cmd"); + System::cmd_execute_clean("cmd", extra_env); else - System::cmd_execute_clean(env_cmd + " && cmd"); + System::cmd_execute_clean(env_cmd + " && cmd", extra_env); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index b7d355742..743619937 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -98,14 +98,10 @@ namespace vcpkg::Help " vcpkg create \n" " [archivename] Create a new package\n" " vcpkg owns Search for files in installed packages\n" - " vcpkg cache List cached compiled packages\n" + " vcpkg env Creates a clean shell environment for development or compiling.\n" " vcpkg version Display version information\n" " vcpkg contact Display contact information to send feedback\n" "\n" - //"internal commands:\n" - //" --check-build-deps \n" - //" --create-binary-control \n" - //"\n" "Options:\n" " --triplet Specify the target architecture triplet.\n" " (default: %%VCPKG_DEFAULT_TRIPLET%%, see 'vcpkg help triplet')\n" -- cgit v1.2.3 From eab1d5c531695c2a644276832578e5550dd9abf6 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 14 Mar 2018 10:30:27 -0700 Subject: [vcpkg-ci] Do not rebuild libraries that were previously successful or failed --- toolsrc/src/tests.plan.cpp | 84 ++++++++++++++++++++- toolsrc/src/vcpkg/base/system.cpp | 10 ++- toolsrc/src/vcpkg/build.cpp | 44 ++++------- toolsrc/src/vcpkg/commands.ci.cpp | 138 +++++++++++++++++++++++++++++++++- toolsrc/src/vcpkg/dependencies.cpp | 11 ++- toolsrc/src/vcpkg/install.cpp | 59 ++++++++------- toolsrc/src/vcpkg/sourceparagraph.cpp | 10 +++ 7 files changed, 289 insertions(+), 67 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 95056810c..a99f1abb9 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -593,6 +593,87 @@ namespace UnitTest1 features_check(&install_plan[0], "a", {"core"}, Triplet::X64_WINDOWS); } + TEST_METHOD(install_plan_action_dependencies) + { + std::vector> status_paragraphs; + + // Add a port "a" which depends on the core of "b", which was already + // installed explicitly + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_c = spec_map.emplace("c"); + auto spec_b = spec_map.emplace("b", "c"); + spec_map.emplace("a", "b"); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::IsTrue(install_plan.size() == 3); + features_check(&install_plan[0], "c", {"core"}, Triplet::X64_WINDOWS); + + features_check(&install_plan[1], "b", {"core"}, Triplet::X64_WINDOWS); + Assert::IsTrue(install_plan[1].install_action.get()->computed_dependencies == + std::vector{spec_c}); + + features_check(&install_plan[2], "a", {"core"}, Triplet::X64_WINDOWS); + Assert::IsTrue(install_plan[2].install_action.get()->computed_dependencies == + std::vector{spec_b}); + } + + TEST_METHOD(install_plan_action_dependencies_2) + { + std::vector> status_paragraphs; + + // Add a port "a" which depends on the core of "b", which was already + // installed explicitly + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_c = spec_map.emplace("c"); + auto spec_b = spec_map.emplace("b", "c"); + spec_map.emplace("a", "c, b"); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::IsTrue(install_plan.size() == 3); + features_check(&install_plan[0], "c", {"core"}, Triplet::X64_WINDOWS); + + features_check(&install_plan[1], "b", {"core"}, Triplet::X64_WINDOWS); + Assert::IsTrue(install_plan[1].install_action.get()->computed_dependencies == + std::vector{spec_c}); + + features_check(&install_plan[2], "a", {"core"}, Triplet::X64_WINDOWS); + Assert::IsTrue(install_plan[2].install_action.get()->computed_dependencies == + std::vector{spec_b, spec_c}); + } + + TEST_METHOD(install_plan_action_dependencies_3) + { + std::vector> status_paragraphs; + + // Add a port "a" which depends on the core of "b", which was already + // installed explicitly + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "", {{"0", ""}, {"1", "a[0]"}}, {"1"}); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::IsTrue(install_plan.size() == 1); + features_check(&install_plan[0], "a", {"1", "0", "core"}, Triplet::X64_WINDOWS); + Assert::IsTrue(install_plan[0].install_action.get()->computed_dependencies == std::vector{}); + } + TEST_METHOD(upgrade_with_default_features_1) { std::vector> pghs; @@ -619,7 +700,6 @@ namespace UnitTest1 Assert::IsTrue(plan[0].remove_action.has_value()); Assert::AreEqual("a", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].install_action.has_value()); features_check(&plan[1], "a", {"core", "0"}, Triplet::X86_WINDOWS); } @@ -651,11 +731,9 @@ namespace UnitTest1 Assert::IsTrue(plan[0].remove_action.has_value()); Assert::AreEqual("b", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].install_action.has_value()); features_check(&plan[1], "b", {"b0", "core"}, Triplet::X64_WINDOWS); Assert::AreEqual("a", plan[2].spec().name().c_str()); - Assert::IsTrue(plan[2].install_action.has_value()); features_check(&plan[2], "a", {"core"}, Triplet::X64_WINDOWS); } diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index f339afa51..a315c7880 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -314,6 +314,8 @@ namespace vcpkg::System // Flush stdout before launching external process fflush(stdout); + auto timer = Chrono::ElapsedTimer::create_started(); + #if defined(_WIN32) const auto actual_cmd_line = Strings::format(R"###("%s 2>&1")###", cmd_line); @@ -335,8 +337,10 @@ namespace vcpkg::System } const auto ec = _pclose(pipe); - Debug::println("_pclose() returned %d", ec); remove_byte_order_marks(&output); + + Debug::println("_pclose() returned %d after %8d us", ec, (int)timer.microseconds()); + return {ec, Strings::to_utf8(output)}; #else const auto actual_cmd_line = Strings::format(R"###(%s 2>&1)###", cmd_line); @@ -359,7 +363,9 @@ namespace vcpkg::System } const auto ec = pclose(pipe); - Debug::println("pclose() returned %d", ec); + + Debug::println("_pclose() returned %d after %8d us", ec, (int)timer.microseconds()); + return {ec, output}; #endif } diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index b71bdbf25..bc9eca3ba 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -273,12 +273,10 @@ namespace vcpkg::Build return filter_dependencies(config.scf.core_paragraph->depends, triplet); } - auto it = - Util::find_if(config.scf.feature_paragraphs, - [&](std::unique_ptr const& fpgh) { return fpgh->name == feature; }); - Checks::check_exit(VCPKG_LINE_INFO, it != config.scf.feature_paragraphs.end()); + auto maybe_feature = config.scf.find_feature(feature); + Checks::check_exit(VCPKG_LINE_INFO, maybe_feature.has_value()); - return filter_dependencies(it->get()->depends, triplet); + return filter_dependencies(maybe_feature.get()->depends, triplet); }); auto dep_fspecs = FeatureSpec::from_strings_and_triplet(dep_strings, triplet); @@ -423,22 +421,10 @@ namespace vcpkg::Build return result; } - struct AbiEntry - { - std::string key; - std::string value; - }; - - struct AbiTagAndFile - { - std::string tag; - fs::path tag_file; - }; - - static Optional compute_abi_tag(const VcpkgPaths& paths, - const BuildPackageConfig& config, - const PreBuildInfo& pre_build_info, - Span dependency_abis) + Optional compute_abi_tag(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const PreBuildInfo& pre_build_info, + Span dependency_abis) { if (!GlobalState::g_binary_caching) return nullopt; @@ -584,17 +570,17 @@ namespace vcpkg::Build const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); - auto abi_tag_and_file = compute_abi_tag(paths, config, pre_build_info, dependency_abis); + auto maybe_abi_tag_and_file = compute_abi_tag(paths, config, pre_build_info, dependency_abis); std::unique_ptr bcf; - auto maybe_abi_tag_and_file = abi_tag_and_file.get(); + auto abi_tag_and_file = maybe_abi_tag_and_file.get(); - if (GlobalState::g_binary_caching && maybe_abi_tag_and_file) + if (GlobalState::g_binary_caching && abi_tag_and_file) { auto archives_root_dir = paths.root / "archives"; - auto archive_name = maybe_abi_tag_and_file->tag + ".zip"; - auto archive_subpath = fs::u8path(maybe_abi_tag_and_file->tag.substr(0, 2)) / archive_name; + auto archive_name = abi_tag_and_file->tag + ".zip"; + auto archive_subpath = fs::u8path(abi_tag_and_file->tag.substr(0, 2)) / archive_name; auto archive_path = archives_root_dir / archive_subpath; auto archive_tombstone_path = archives_root_dir / "fail" / archive_subpath; @@ -617,12 +603,12 @@ namespace vcpkg::Build System::println("Could not locate cached archive: %s", archive_path.u8string()); ExtendedBuildResult result = do_build_package_and_clean_buildtrees( - paths, pre_build_info, spec, abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); + paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); std::error_code ec; fs.create_directories(paths.package_dir(spec) / "share" / spec.name(), ec); auto abi_file_in_package = paths.package_dir(spec) / "share" / spec.name() / "vcpkg_abi_info.txt"; - fs.copy_file(maybe_abi_tag_and_file->tag_file, abi_file_in_package, fs::stdfs::copy_options::none, ec); + fs.copy_file(abi_tag_and_file->tag_file, abi_file_in_package, fs::stdfs::copy_options::none, ec); Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not copy into file: %s", abi_file_in_package.u8string()); if (result.code == BuildResult::SUCCEEDED) @@ -648,7 +634,7 @@ namespace vcpkg::Build else { return do_build_package_and_clean_buildtrees( - paths, pre_build_info, spec, abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); + paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); } } diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index e01072a0a..45eb1c83e 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include #include #include #include @@ -7,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -44,8 +46,120 @@ namespace vcpkg::Commands::CI nullptr, }; + UnknownCIPortsResults find_unknown_ports_for_ci(const VcpkgPaths& paths, + const std::set& exclusions, + const Dependencies::PortFileProvider& provider, + const std::vector& fspecs) + { + UnknownCIPortsResults ret; + + auto& fs = paths.get_filesystem(); + + std::map abi_tag_map; + std::set will_fail; + + const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, + Build::AllowDownloads::YES, + Build::CleanBuildtrees::YES, + Build::CleanPackages::YES}; + + vcpkg::Cache pre_build_info_cache; + + auto action_plan = Dependencies::create_feature_install_plan(provider, fspecs, StatusParagraphs{}); + + for (auto&& action : action_plan) + { + if (auto p = action.install_action.get()) + { + // determine abi tag + std::string abi; + if (auto scf = p->source_control_file.get()) + { + auto triplet = p->spec.triplet(); + + const Build::BuildPackageConfig build_config{p->source_control_file.value_or_exit(VCPKG_LINE_INFO), + triplet, + paths.port_dir(p->spec), + install_plan_options, + p->feature_list}; + + auto dependency_abis = + Util::fmap(p->computed_dependencies, [&](const PackageSpec& spec) -> Build::AbiEntry { + auto it = abi_tag_map.find(spec); + + if (it == abi_tag_map.end()) + return {spec.name(), ""}; + else + return {spec.name(), it->second}; + }); + const auto& pre_build_info = pre_build_info_cache.get_lazy( + triplet, [&]() { return Build::PreBuildInfo::from_triplet_file(paths, triplet); }); + + auto maybe_tag_and_file = + Build::compute_abi_tag(paths, build_config, pre_build_info, dependency_abis); + if (auto tag_and_file = maybe_tag_and_file.get()) + { + abi = tag_and_file->tag; + abi_tag_map.emplace(p->spec, abi); + } + } + else if (auto ipv = p->installed_package.get()) + { + abi = ipv->core->package.abi; + if (!abi.empty()) abi_tag_map.emplace(p->spec, abi); + } + + std::string state; + + auto archives_root_dir = paths.root / "archives"; + auto archive_name = abi + ".zip"; + auto archive_subpath = fs::u8path(abi.substr(0, 2)) / archive_name; + auto archive_path = archives_root_dir / archive_subpath; + auto archive_tombstone_path = archives_root_dir / "fail" / archive_subpath; + + bool b_will_build = false; + + if (Util::Sets::contains(exclusions, p->spec.name())) + { + ret.known.emplace(p->spec, BuildResult::EXCLUDED); + will_fail.emplace(p->spec); + } + else if (std::any_of(p->computed_dependencies.begin(), + p->computed_dependencies.end(), + [&](const PackageSpec& spec) { return Util::Sets::contains(will_fail, spec); })) + { + ret.known.emplace(p->spec, BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES); + will_fail.emplace(p->spec); + } + else if (fs.exists(archive_path)) + { + state += "pass"; + ret.known.emplace(p->spec, BuildResult::SUCCEEDED); + } + else if (fs.exists(archive_tombstone_path)) + { + state += "fail"; + ret.known.emplace(p->spec, BuildResult::BUILD_FAILED); + will_fail.emplace(p->spec); + } + else + { + ret.unknown.push_back(p->spec); + b_will_build = true; + } + + System::println("%40s: %1s %8s: %s", p->spec, (b_will_build ? "*" : " "), state, abi); + } + } + + return ret; + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { + Checks::check_exit( + VCPKG_LINE_INFO, GlobalState::g_binary_caching, "The ci command requires binary caching to be enabled."); + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); std::set exclusions_set; @@ -77,16 +191,21 @@ namespace vcpkg::Commands::CI Build::CleanBuildtrees::YES, Build::CleanPackages::YES}; - std::vector ports = Install::get_all_port_names(paths); + std::vector> all_known_results; + + std::vector all_ports = Install::get_all_port_names(paths); std::vector results; for (const Triplet& triplet : triplets) { Input::check_triplet(triplet, paths); - std::vector specs = PackageSpec::to_package_specs(ports, triplet); + + std::vector specs = PackageSpec::to_package_specs(all_ports, triplet); // Install the default features for every package - const auto featurespecs = Util::fmap(specs, [](auto& spec) { return FeatureSpec(spec, ""); }); + auto all_fspecs = Util::fmap(specs, [](auto& spec) { return FeatureSpec(spec, ""); }); + auto split_specs = find_unknown_ports_for_ci(paths, exclusions_set, paths_port_file, all_fspecs); + auto fspecs = Util::fmap(split_specs.unknown, [](auto& spec) { return FeatureSpec(spec, ""); }); - auto action_plan = Dependencies::create_feature_install_plan(paths_port_file, featurespecs, status_db); + auto action_plan = Dependencies::create_feature_install_plan(paths_port_file, fspecs, status_db); for (auto&& action : action_plan) { @@ -107,7 +226,10 @@ namespace vcpkg::Commands::CI else { auto summary = Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db); + for (auto&& result : summary.results) + split_specs.known.erase(result.spec); results.push_back({triplet, std::move(summary)}); + all_known_results.emplace_back(std::move(split_specs.known)); } } @@ -125,6 +247,14 @@ namespace vcpkg::Commands::CI for (auto&& result : results) xunit_doc += result.summary.xunit_results(); + for (auto&& known_result : all_known_results) + { + for (auto&& result : known_result) + { + xunit_doc += + Install::InstallSummary::xunit_result(result.first, Chrono::ElapsedTime{}, result.second); + } + } xunit_doc += "\n"; paths.get_filesystem().write_contents(fs::u8path(it_xunit->second), xunit_doc); diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 1d017a8d3..f6d81c973 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -144,12 +144,14 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const SourceControlFile& scf, const std::set& features, - const RequestType& request_type) + const RequestType& request_type, + std::vector&& dependencies) : spec(spec) , source_control_file(scf) , plan_type(InstallPlanType::BUILD_AND_INSTALL) , request_type(request_type) , feature_list(features) + , computed_dependencies(std::move(dependencies)) { } @@ -162,6 +164,7 @@ namespace vcpkg::Dependencies , plan_type(InstallPlanType::ALREADY_INSTALLED) , request_type(request_type) , feature_list(features) + , computed_dependencies(installed_package.get()->dependencies()) { } @@ -683,11 +686,17 @@ namespace vcpkg::Dependencies // If it will be transiently uninstalled, we need to issue a full installation command auto pscf = p_cluster->source_control_file.value_or_exit(VCPKG_LINE_INFO); Checks::check_exit(VCPKG_LINE_INFO, pscf != nullptr); + + auto dep_specs = Util::fmap(m_graph_plan->install_graph.adjacency_list(p_cluster), + [](ClusterPtr const& p) { return p->spec; }); + Util::sort_unique_erase(dep_specs); + plan.emplace_back(InstallPlanAction{ p_cluster->spec, *pscf, p_cluster->to_install_features, p_cluster->request_type, + std::move(dep_specs), }); } else diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 7d36fba82..e30a34c18 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -668,39 +668,42 @@ namespace vcpkg::Install return nullptr; } + std::string InstallSummary::xunit_result(const PackageSpec& spec, Chrono::ElapsedTime time, BuildResult code) + { + std::string inner_block; + const char* result_string = ""; + switch (code) + { + case BuildResult::POST_BUILD_CHECKS_FAILED: + case BuildResult::FILE_CONFLICTS: + case BuildResult::BUILD_FAILED: + result_string = "Fail"; + inner_block = Strings::format("", to_string(code)); + break; + case BuildResult::EXCLUDED: + case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: + result_string = "Skip"; + inner_block = Strings::format("", to_string(code)); + break; + case BuildResult::SUCCEEDED: result_string = "Pass"; break; + default: Checks::exit_fail(VCPKG_LINE_INFO); + } + + return Strings::format(R"(%s)" + "\n", + spec, + spec, + time.as().count(), + result_string, + inner_block); + } + std::string InstallSummary::xunit_results() const { std::string xunit_doc; for (auto&& result : results) { - std::string inner_block; - const char* result_string = ""; - switch (result.build_result.code) - { - case BuildResult::POST_BUILD_CHECKS_FAILED: - case BuildResult::FILE_CONFLICTS: - case BuildResult::BUILD_FAILED: - result_string = "Fail"; - inner_block = Strings::format("", - to_string(result.build_result.code)); - break; - case BuildResult::EXCLUDED: - case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: - result_string = "Skip"; - inner_block = - Strings::format("", to_string(result.build_result.code)); - break; - case BuildResult::SUCCEEDED: result_string = "Pass"; break; - default: Checks::exit_fail(VCPKG_LINE_INFO); - } - - xunit_doc += Strings::format(R"(%s)" - "\n", - result.spec, - result.spec, - result.timing.as().count(), - result_string, - inner_block); + xunit_doc += xunit_result(result.spec, result.timing, result.build_result.code); } return xunit_doc; } diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp index 0b4baf189..ed61cb42a 100644 --- a/toolsrc/src/vcpkg/sourceparagraph.cpp +++ b/toolsrc/src/vcpkg/sourceparagraph.cpp @@ -158,6 +158,16 @@ namespace vcpkg return std::move(control_file); } + Optional SourceControlFile::find_feature(const std::string& featurename) const + { + auto it = Util::find_if(feature_paragraphs, + [&](const std::unique_ptr& p) { return p->name == featurename; }); + if (it != feature_paragraphs.end()) + return **it; + else + return nullopt; + } + Dependency Dependency::parse_dependency(std::string name, std::string qualifier) { Dependency dep; -- cgit v1.2.3 From ab7985a34b8a4de59dc9a6e6c4c40fbb564797b8 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 16 Mar 2018 16:53:48 -0700 Subject: [vcpkg-hash] Use BCrypt on Windows --- toolsrc/src/vcpkg/base/strings.cpp | 13 +++- toolsrc/src/vcpkg/commands.hash.cpp | 124 ++++++++++++++++++++++++++++++++---- 2 files changed, 121 insertions(+), 16 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index a08512c9f..5fedf3e1f 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -7,10 +7,11 @@ namespace vcpkg::Strings::details { // To disambiguate between two overloads - static const auto isspace = [](const char c) { return std::isspace(c); }; + static bool IS_SPACE(const char c) { return std::isspace(c) != 0; }; // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower() static char tolower_char(const char c) { return static_cast(std::tolower(c)); } + static char toupper_char(const char c) { return static_cast(std::toupper(c)); } #if defined(_WIN32) static _locale_t& c_locale() @@ -114,6 +115,12 @@ namespace vcpkg::Strings return s; } + std::string ascii_to_uppercase(std::string s) + { + std::transform(s.begin(), s.end(), s.begin(), &details::toupper_char); + return s; + } + bool case_insensitive_ascii_starts_with(const std::string& s, const std::string& pattern) { #if defined(_WIN32) @@ -136,8 +143,8 @@ namespace vcpkg::Strings std::string trim(std::string&& s) { - s.erase(std::find_if_not(s.rbegin(), s.rend(), details::isspace).base(), s.end()); - s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), details::isspace)); + s.erase(std::find_if_not(s.rbegin(), s.rend(), details::IS_SPACE).base(), s.end()); + s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), details::IS_SPACE)); return std::move(s); } diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index cb0a8cc51..9e1b54390 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -1,13 +1,114 @@ #include "pch.h" +#include +#include #include #include #include #include +#if defined(_WIN32) +#include + +#ifndef NT_SUCCESS +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif + namespace vcpkg::Commands::Hash { - std::string get_file_hash(const VcpkgPaths& paths, fs::path const& path, std::string const& hash_type) + namespace + { + static std::string to_hex(const unsigned char* string, const size_t bytes) + { + static constexpr char HEX_MAP[] = "0123456789abcdef"; + + std::string output; + output.resize(2 * bytes); + + size_t current_char = 0; + for (size_t i = 0; i < bytes; i++) + { + // high + output[current_char] = HEX_MAP[(string[i] & 0xF0) >> 4]; + ++current_char; + // low + output[current_char] = HEX_MAP[(string[i] & 0x0F)]; + ++current_char; + } + + return output; + } + + struct BCryptAlgorithmHandle : Util::ResourceBase + { + BCRYPT_ALG_HANDLE handle = nullptr; + + ~BCryptAlgorithmHandle() + { + if (handle) BCryptCloseAlgorithmProvider(handle, 0); + } + }; + + struct BCryptHashHandle : Util::ResourceBase + { + BCRYPT_HASH_HANDLE handle = nullptr; + + ~BCryptHashHandle() + { + if (handle) BCryptDestroyHash(handle); + } + }; + } + + std::string get_file_hash(const VcpkgPaths&, const fs::path& path, const std::string& hash_type) + { + BCryptAlgorithmHandle algorithm_handle; + + NTSTATUS error_code = BCryptOpenAlgorithmProvider( + &algorithm_handle.handle, Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(), nullptr, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider"); + + DWORD hash_buffer_bytes; + DWORD cb_data; + error_code = BCryptGetProperty(algorithm_handle.handle, + BCRYPT_HASH_LENGTH, + reinterpret_cast(&hash_buffer_bytes), + sizeof(DWORD), + &cb_data, + 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length"); + const ULONG length_in_bytes = hash_buffer_bytes; + + BCryptHashHandle hash_handle; + + error_code = BCryptCreateHash(algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher"); + + FILE* file = nullptr; + const auto ec = _wfopen_s(&file, path.c_str(), L"rb"); + Checks::check_exit(VCPKG_LINE_INFO, ec == 0, "Failed to open file: %s", path.u8string()); + unsigned char buffer[4096]; + while (const auto actual_size = fread(buffer, 1, sizeof(buffer), file)) + { + error_code = BCryptHashData(hash_handle.handle, buffer, static_cast(actual_size), 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data"); + } + + fclose(file); + + std::unique_ptr hash_buffer = std::make_unique(length_in_bytes); + + error_code = BCryptFinishHash(hash_handle.handle, hash_buffer.get(), length_in_bytes, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash"); + + return to_hex(hash_buffer.get(), length_in_bytes); + } +} + +#else +namespace vcpkg::Commands::Hash +{ + std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type) { const std::string cmd_line = Strings::format( R"("%s" -E %ssum "%s")", @@ -32,7 +133,11 @@ namespace vcpkg::Commands::Hash Util::erase_remove_if(hash, isspace); return hash; } +} +#endif +namespace vcpkg::Commands::Hash +{ const CommandStructure COMMAND_STRUCTURE = { Strings::format("The argument should be a file path\n%s", Help::create_example_string("hash boost_1_62_0.tar.bz2")), @@ -44,19 +149,12 @@ namespace vcpkg::Commands::Hash void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - args.parse_arguments(COMMAND_STRUCTURE); - - if (args.command_arguments.size() == 1) - { - auto hash = get_file_hash(paths, args.command_arguments[0], "SHA512"); - System::println(hash); - } - if (args.command_arguments.size() == 2) - { - auto hash = get_file_hash(paths, args.command_arguments[0], args.command_arguments[1]); - System::println(hash); - } + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); + const fs::path file_to_hash = args.command_arguments[0]; + const std::string algorithm = args.command_arguments.size() == 2 ? args.command_arguments[1] : "SHA512"; + const std::string hash = get_file_hash(paths, file_to_hash, algorithm); + System::println(hash); Checks::exit_success(VCPKG_LINE_INFO); } } -- cgit v1.2.3 From d80dd5cbc777ce765c2d6b78d7c485fdf05f284b Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 19 Mar 2018 15:45:35 -0700 Subject: [vcpkg] Handle failure to store archive --- toolsrc/src/vcpkg/base/files.cpp | 4 ++++ toolsrc/src/vcpkg/build.cpp | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index b59104a59..4e61666b7 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -108,6 +108,10 @@ namespace vcpkg::Files output.close(); } + virtual void rename(const fs::path& oldpath, const fs::path& newpath, std::error_code& ec) override + { + fs::stdfs::rename(oldpath, newpath, ec); + } virtual void rename(const fs::path& oldpath, const fs::path& newpath) override { fs::stdfs::rename(oldpath, newpath); diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index bc9eca3ba..ebded2736 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -618,9 +618,12 @@ namespace vcpkg::Build compress_archive(paths, spec, tmp_archive_path); fs.create_directories(archive_path.parent_path(), ec); - fs.rename(tmp_archive_path, archive_path); - - System::println("Stored binary cache: %s", archive_path.u8string()); + fs.rename(tmp_archive_path, archive_path, ec); + if (ec) + System::println( + System::Color::warning, "Failed to store binary cache: %s", archive_path.u8string()); + else + System::println("Stored binary cache: %s", archive_path.u8string()); } else if (result.code == BuildResult::BUILD_FAILED || result.code == BuildResult::POST_BUILD_CHECKS_FAILED) { -- cgit v1.2.3 From 1baa7f16420a359328761b330cdaf58b82b6656c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 21 Mar 2018 16:19:06 -0700 Subject: Improve error message when PROGRAMFILES is not found --- toolsrc/src/vcpkg/base/system.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index a315c7880..60067759a 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -533,7 +533,15 @@ namespace vcpkg::System static const fs::path& get_program_files() { - static const fs::path PATH = System::get_environment_variable("PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO); + static const fs::path PATH = []() -> fs::path { + auto value = System::get_environment_variable("PROGRAMFILES"); + if (auto v = value.get()) + { + return *v; + } + Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find PROGRAMFILES environment variable"); + }(); + return PATH; } @@ -543,7 +551,7 @@ namespace vcpkg::System auto value = System::get_environment_variable("ProgramFiles(x86)"); if (auto v = value.get()) { - return std::move(*v); + return *v; } return get_program_files(); }(); @@ -556,7 +564,7 @@ namespace vcpkg::System auto value = System::get_environment_variable("ProgramW6432"); if (auto v = value.get()) { - return std::move(*v); + return *v; } return get_program_files(); }(); -- cgit v1.2.3 From d45954a96b625ba1856ac97b429163a1919a3299 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 21 Mar 2018 18:21:30 -0700 Subject: System::get_program_files() now returns Optional --- toolsrc/src/vcpkg/base/system.cpp | 35 ++++++++++++++++---------------- toolsrc/src/vcpkg/commands.edit.cpp | 20 +++++++++++++----- toolsrc/src/vcpkg/commands.integrate.cpp | 6 +++--- toolsrc/src/vcpkg/vcpkgpaths.cpp | 18 ++++++++-------- 4 files changed, 46 insertions(+), 33 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 60067759a..1094777af 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -224,21 +224,21 @@ namespace vcpkg::System env_cstr.push_back(L'\0'); } - if (extra_env.find("PATH") != extra_env.end()) - NEW_PATH += Strings::format(";%s", extra_env.find("PATH")->second); + if (extra_env.find("PATH") != extra_env.end()) + NEW_PATH += Strings::format(";%s", extra_env.find("PATH")->second); env_cstr.append(Strings::to_utf16(NEW_PATH)); env_cstr.push_back(L'\0'); env_cstr.append(L"VSLANG=1033"); env_cstr.push_back(L'\0'); - for (auto item : extra_env) - { - if (item.first == "PATH") continue; - env_cstr.append(Strings::to_utf16(item.first)); - env_cstr.push_back(L'='); - env_cstr.append(Strings::to_utf16(item.second)); - env_cstr.push_back(L'\0'); - } + for (auto item : extra_env) + { + if (item.first == "PATH") continue; + env_cstr.append(Strings::to_utf16(item.first)); + env_cstr.push_back(L'='); + env_cstr.append(Strings::to_utf16(item.second)); + env_cstr.push_back(L'\0'); + } STARTUPINFOW startup_info; memset(&startup_info, 0, sizeof(STARTUPINFOW)); @@ -531,23 +531,24 @@ namespace vcpkg::System } #endif - static const fs::path& get_program_files() + static const Optional& get_program_files() { - static const fs::path PATH = []() -> fs::path { + static const auto PATH = []() -> Optional { auto value = System::get_environment_variable("PROGRAMFILES"); if (auto v = value.get()) { return *v; } - Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find PROGRAMFILES environment variable"); + + return nullopt; }(); return PATH; } - const fs::path& get_program_files_32_bit() + const Optional& get_program_files_32_bit() { - static const fs::path PATH = []() -> fs::path { + static const auto PATH = []() -> Optional { auto value = System::get_environment_variable("ProgramFiles(x86)"); if (auto v = value.get()) { @@ -558,9 +559,9 @@ namespace vcpkg::System return PATH; } - const fs::path& get_program_files_platform_bitness() + const Optional& get_program_files_platform_bitness() { - static const fs::path PATH = []() -> fs::path { + static const auto PATH = []() -> Optional { auto value = System::get_environment_variable("ProgramW6432"); if (auto v = value.get()) { diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index 41f261a53..ac34a6720 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -69,14 +69,24 @@ namespace vcpkg::Commands::Edit std::vector candidate_paths; auto maybe_editor_path = System::get_environment_variable("EDITOR"); - if (auto editor_path = maybe_editor_path.get()) + if (const std::string* editor_path = maybe_editor_path.get()) { candidate_paths.emplace_back(*editor_path); } - candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE_INSIDERS); - candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE_INSIDERS); - candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE); - candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE); + + const auto& program_files = System::get_program_files_platform_bitness(); + if (const fs::path* pf = program_files.get()) + { + candidate_paths.push_back(*pf / VS_CODE_INSIDERS); + candidate_paths.push_back(*pf / VS_CODE); + } + + const auto& program_files_32_bit = System::get_program_files_32_bit(); + if (const fs::path* pf = program_files_32_bit.get()) + { + candidate_paths.push_back(*pf / VS_CODE_INSIDERS); + candidate_paths.push_back(*pf / VS_CODE); + } const std::vector from_registry = find_from_registry(); candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend()); diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 460e99b88..36e4e56e7 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -148,12 +148,12 @@ namespace vcpkg::Commands::Integrate static void integrate_install(const VcpkgPaths& paths) { static const std::array OLD_SYSTEM_TARGET_FILES = { - System::get_program_files_32_bit() / + System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", - System::get_program_files_32_bit() / + System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"}; static const fs::path SYSTEM_WIDE_TARGETS_FILE = - System::get_program_files_32_bit() / + System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; auto& fs = paths.get_filesystem(); diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 46e80c4a9..63a484a86 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -190,10 +190,11 @@ namespace vcpkg #endif const std::vector from_path = Files::find_from_PATH("cmake"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); -#if defined(_WIN32) - candidate_paths.push_back(System::get_program_files_platform_bitness() / "CMake" / "bin" / "cmake.exe"); - candidate_paths.push_back(System::get_program_files_32_bit() / "CMake" / "bin"); -#endif + + const auto& program_files = System::get_program_files_platform_bitness(); + if (const auto pf = program_files.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe"); + const auto& program_files_32_bit = System::get_program_files_32_bit(); + if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe"); const Optional path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); @@ -252,10 +253,11 @@ namespace vcpkg #endif const std::vector from_path = Files::find_from_PATH("git"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); -#if defined(_WIN32) - candidate_paths.push_back(System::get_program_files_platform_bitness() / "git" / "cmd" / "git.exe"); - candidate_paths.push_back(System::get_program_files_32_bit() / "git" / "cmd" / "git.exe"); -#endif + + const auto& program_files = System::get_program_files_platform_bitness(); + if (const auto pf = program_files.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe"); + const auto& program_files_32_bit = System::get_program_files_32_bit(); + if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe"); const Optional path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); -- cgit v1.2.3 From c3fb0b169751ec0f25ac3752a7e83e21173073a4 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 22 Mar 2018 03:08:25 -0700 Subject: [vcpkg] Download cmake on osx and linux --- toolsrc/src/vcpkg/base/system.cpp | 6 ++-- toolsrc/src/vcpkg/vcpkgpaths.cpp | 73 ++++++++++++++++++++++++++++++++------- 2 files changed, 63 insertions(+), 16 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 1094777af..171dd2bbf 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -285,14 +285,14 @@ namespace vcpkg::System fflush(nullptr); // Basically we are wrapping it in quotes - const std::string& actual_cmd_line = Strings::format(R"###("%s")###", cmd_line); #if defined(_WIN32) + const std::string& actual_cmd_line = Strings::format(R"###("%s")###", cmd_line); Debug::println("_wsystem(%s)", actual_cmd_line); const int exit_code = _wsystem(Strings::to_utf16(actual_cmd_line).c_str()); Debug::println("_wsystem() returned %d", exit_code); #else - Debug::println("_system(%s)", actual_cmd_line); - const int exit_code = system(actual_cmd_line.c_str()); + Debug::println("_system(%s)", cmd_line); + const int exit_code = system(cmd_line.c_str()); Debug::println("_system() returned %d", exit_code); #endif return exit_code; diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 63a484a86..c36def15d 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -19,6 +19,8 @@ namespace vcpkg { std::array required_version; fs::path downloaded_exe_path; + std::string url; + fs::path downloaded_path; }; static Optional> parse_version_string(const std::string& version_as_string) @@ -41,8 +43,24 @@ namespace vcpkg static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool) { +#if defined(_WIN32) + static constexpr StringLiteral OS_STRING = ""; +#elif defined(__APPLE__) + static constexpr StringLiteral OS_STRING = " os=\"osx\""; +#else // assume linux + static constexpr StringLiteral OS_STRING = " os=\"linux\""; +#endif + static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; + const auto maybe_get_string_inside_tags = [](const std::string& input, + const std::regex& regex) -> Optional { + std::smatch match; + const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); + if (!has_match) return nullopt; + return match[1]; + }; + const auto get_string_inside_tags = [](const std::string& input, const std::regex& regex, const std::string& tag_name) -> std::string { std::smatch match; @@ -57,7 +75,10 @@ namespace vcpkg static const std::regex VERSION_REGEX{ Strings::format(R"###(([\s\S]*?))###", tool)}; static const std::regex EXE_RELATIVE_PATH_REGEX{ - Strings::format(R"###(([\s\S]*?))###", tool)}; + Strings::format(R"###(([\s\S]*?))###", OS_STRING)}; + static const std::regex ARCHIVE_RELATIVE_PATH_REGEX{ + Strings::format(R"###(([\s\S]*?))###", OS_STRING)}; + static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###", OS_STRING)}; const std::regex tool_regex{Strings::format(R"###(([\s\S]*?))###", tool)}; @@ -74,9 +95,13 @@ namespace vcpkg const std::string required_version_as_string = get_string_inside_tags(tool_data_as_string, VERSION_REGEX, "requiredVersion"); + const std::string url = get_string_inside_tags(tool_data_as_string, URL_REGEX, "url"); + const std::string exe_relative_path = get_string_inside_tags(tool_data_as_string, EXE_RELATIVE_PATH_REGEX, "exeRelativePath"); + auto archive_relative_path = maybe_get_string_inside_tags(tool_data_as_string, ARCHIVE_RELATIVE_PATH_REGEX); + const Optional> required_version = parse_version_string(required_version_as_string); Checks::check_exit(VCPKG_LINE_INFO, required_version.has_value(), @@ -85,7 +110,10 @@ namespace vcpkg required_version_as_string); const fs::path exe_path = paths.downloads / exe_relative_path; - return ToolData{*required_version.get(), exe_path}; + return ToolData{*required_version.get(), + exe_path, + url, + paths.downloads / archive_relative_path.value_or(exe_relative_path)}; } static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, @@ -144,8 +172,10 @@ namespace vcpkg return data_lines; } - static fs::path fetch_tool(const fs::path& scripts_folder, const std::string& tool_name, const ToolData& tool_data) + static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data) { + const auto& fs = paths.get_filesystem(); + const fs::path& scripts_folder = paths.scripts; const std::array& version = tool_data.required_version; const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); @@ -154,6 +184,7 @@ namespace vcpkg version_as_string, tool_name, version_as_string); +#if defined(_WIN32) const fs::path script = scripts_folder / "fetchtool.ps1"; const std::string title = Strings::format( "Fetching %s version %s (No sufficient installed version was found)", tool_name, version_as_string); @@ -173,21 +204,37 @@ namespace vcpkg expected_downloaded_path.u8string(), actual_downloaded_path.u8string()); return actual_downloaded_path; +#else + if (!fs.exists(tool_data.downloaded_path)) + { + auto code = System::cmd_execute( + Strings::format(R"(curl '%s' --create-dirs --output '%s')", tool_data.url, tool_data.downloaded_path)); + Checks::check_exit(VCPKG_LINE_INFO, code == 0, "curl failed while downloading %s", tool_data.url); + } + auto code = System::cmd_execute( + Strings::format(R"(cd '%s' && tar xzf '%s')", paths.downloads, tool_data.downloaded_path)); + Checks::check_exit(VCPKG_LINE_INFO, code == 0, "tar failed while extracting %s", tool_data.downloaded_path); + + Checks::check_exit(VCPKG_LINE_INFO, + fs.exists(tool_data.downloaded_exe_path), + "Expected %s to exist after extracting", + tool_data.downloaded_exe_path); + + return tool_data.downloaded_exe_path; +#endif } static fs::path get_cmake_path(const VcpkgPaths& paths) { -#if defined(_WIN32) + std::vector candidate_paths; +#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__) static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "cmake"); + candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); #else static const ToolData TOOL_DATA = ToolData{{3, 5, 1}, ""}; #endif static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - std::vector candidate_paths; -#if defined(_WIN32) - candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); -#endif const std::vector from_path = Files::find_from_PATH("cmake"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); @@ -203,7 +250,7 @@ namespace vcpkg return *p; } - return fetch_tool(paths.scripts, "cmake", TOOL_DATA); + return fetch_tool(paths, "cmake", TOOL_DATA); } static fs::path get_7za_path(const VcpkgPaths& paths) @@ -212,7 +259,7 @@ namespace vcpkg static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "7zip"); if (!paths.get_filesystem().exists(TOOL_DATA.downloaded_exe_path)) { - return fetch_tool(paths.scripts, "7zip", TOOL_DATA); + return fetch_tool(paths, "7zip", TOOL_DATA); } return TOOL_DATA.downloaded_exe_path; #else @@ -235,7 +282,7 @@ namespace vcpkg return *p; } - return fetch_tool(paths.scripts, "nuget", TOOL_DATA); + return fetch_tool(paths, "nuget", TOOL_DATA); } static fs::path get_git_path(const VcpkgPaths& paths) @@ -266,7 +313,7 @@ namespace vcpkg return *p; } - return fetch_tool(paths.scripts, "git", TOOL_DATA); + return fetch_tool(paths, "git", TOOL_DATA); } static fs::path get_ifw_installerbase_path(const VcpkgPaths& paths) @@ -292,7 +339,7 @@ namespace vcpkg return *p; } - return fetch_tool(paths.scripts, "installerbase", TOOL_DATA); + return fetch_tool(paths, "installerbase", TOOL_DATA); } Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir, const std::string& default_vs_path) -- cgit v1.2.3 From 1f62b32641045fe377ee80ff1854a785344687d2 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 22 Mar 2018 10:01:12 -0700 Subject: [vcpkg] Sort abi tags to ensure stability --- toolsrc/src/vcpkg/build.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index ebded2736..953e77460 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -449,6 +449,8 @@ namespace vcpkg::Build if (config.build_package_options.use_head_version == UseHeadVersion::YES) abi_tag_entries.emplace_back(AbiEntry{"head", ""}); + Util::sort(abi_tag_entries); + std::string full_abi_info = Strings::join("", abi_tag_entries, [](const AbiEntry& p) { return p.key + " " + p.value + "\n"; }); -- cgit v1.2.3 From d5580dd330bac4d473f146e6efe3756e83a35066 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 24 Mar 2018 01:24:07 -0700 Subject: Join declaration and assignment --- toolsrc/src/vcpkg/install.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index e30a34c18..7a963c82f 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -558,16 +558,15 @@ namespace vcpkg::Install Build::CleanBuildtrees::NO, Build::CleanPackages::NO}; - // Note: action_plan will hold raw pointers to SourceControlFiles from this map - std::vector action_plan; - auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); std::unordered_map scf_map; for (auto&& port : all_ports) scf_map[port->core_paragraph->name] = std::move(*port); MapPortFileProvider provider(scf_map); - action_plan = create_feature_install_plan(provider, FullPackageSpec::to_feature_specs(specs), status_db); + // Note: action_plan will hold raw pointers to SourceControlFiles from this map + std::vector action_plan = + create_feature_install_plan(provider, FullPackageSpec::to_feature_specs(specs), status_db); if (!GlobalState::feature_packages) { -- cgit v1.2.3 From 7029daa36df7040e420b3722f345b6923ce93ef0 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 23 Mar 2018 09:59:42 -0700 Subject: [vcpkg] Handle non-sorted output from std::filesystem --- toolsrc/src/vcpkg/install.cpp | 4 ++-- toolsrc/src/vcpkg/paragraphs.cpp | 4 +++- toolsrc/src/vcpkg/vcpkglib.cpp | 1 + toolsrc/src/vcpkg/vcpkgpaths.cpp | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 7a963c82f..1fbf6d97e 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -70,8 +70,8 @@ namespace vcpkg::Install } const std::string filename = file.filename().u8string(); - if (fs::is_regular_file(status) && (Strings::case_insensitive_ascii_equals(filename.c_str(), "CONTROL") || - Strings::case_insensitive_ascii_equals(filename.c_str(), "BUILD_INFO"))) + if (fs::is_regular_file(status) && (Strings::case_insensitive_ascii_equals(filename, "CONTROL") || + Strings::case_insensitive_ascii_equals(filename, "BUILD_INFO"))) { // Do not copy the control file continue; diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp index d0b0c0abf..41ffceec7 100644 --- a/toolsrc/src/vcpkg/paragraphs.cpp +++ b/toolsrc/src/vcpkg/paragraphs.cpp @@ -251,7 +251,9 @@ namespace vcpkg::Paragraphs LoadResults try_load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) { LoadResults ret; - for (auto&& path : fs.get_files_non_recursive(ports_dir)) + auto port_dirs = fs.get_files_non_recursive(ports_dir); + Util::sort(port_dirs); + for (auto&& path : port_dirs) { auto maybe_spgh = try_load_port(fs, path); if (const auto spgh = maybe_spgh.get()) diff --git a/toolsrc/src/vcpkg/vcpkglib.cpp b/toolsrc/src/vcpkg/vcpkglib.cpp index 220c29720..7979fd9a5 100644 --- a/toolsrc/src/vcpkg/vcpkglib.cpp +++ b/toolsrc/src/vcpkg/vcpkglib.cpp @@ -54,6 +54,7 @@ namespace vcpkg StatusParagraphs current_status_db = load_current_database(fs, status_file, status_file_old); auto update_files = fs.get_files_non_recursive(updates_dir); + Util::sort(update_files); if (update_files.empty()) { // updates directory is empty, control file is up-to-date. diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index c36def15d..9b331d7fc 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -405,6 +405,7 @@ namespace vcpkg { output.push_back(path.stem().filename().string()); } + Util::sort(output); return output; }); -- cgit v1.2.3 From c814c9b8ac883aa42930e1f48660145fd4234fe6 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 27 Mar 2018 13:23:30 -0700 Subject: [vcpkgTools.xml] Restructre os-specific info --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 9b331d7fc..feacda026 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -46,9 +46,9 @@ namespace vcpkg #if defined(_WIN32) static constexpr StringLiteral OS_STRING = ""; #elif defined(__APPLE__) - static constexpr StringLiteral OS_STRING = " os=\"osx\""; + static constexpr StringLiteral OS_STRING = R"(os="osx")"; #else // assume linux - static constexpr StringLiteral OS_STRING = " os=\"linux\""; + static constexpr StringLiteral OS_STRING = R"(os="linux")"; #endif static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; @@ -72,15 +72,15 @@ namespace vcpkg }; static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO); - static const std::regex VERSION_REGEX{ - Strings::format(R"###(([\s\S]*?))###", tool)}; + static const std::regex VERSION_REGEX{R"###(([\s\S]*?))###"}; static const std::regex EXE_RELATIVE_PATH_REGEX{ - Strings::format(R"###(([\s\S]*?))###", OS_STRING)}; + Strings::format(R"###(([\s\S]*?))###")}; static const std::regex ARCHIVE_RELATIVE_PATH_REGEX{ - Strings::format(R"###(([\s\S]*?))###", OS_STRING)}; - static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###", OS_STRING)}; + Strings::format(R"###(([\s\S]*?))###")}; + static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###")}; - const std::regex tool_regex{Strings::format(R"###(([\s\S]*?))###", tool)}; + const std::regex tool_regex{ + Strings::format(R"###(([\s\S]*?))###", tool, OS_STRING)}; std::smatch match_tool; const bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); -- cgit v1.2.3 From ee1409f432711e59b58bd170f021949e8e12aedd Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 27 Mar 2018 21:39:23 -0700 Subject: Hotfix #3144 --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index feacda026..a17ffeb05 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -80,7 +80,7 @@ namespace vcpkg static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###")}; const std::regex tool_regex{ - Strings::format(R"###(([\s\S]*?))###", tool, OS_STRING)}; + Strings::format(R"###(([\s\S]*?))###", tool, OS_STRING)}; std::smatch match_tool; const bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); -- cgit v1.2.3 From 4a9feaa2403e59b3267f8bd02ef2fd687ea5661d Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 30 Mar 2018 18:44:13 -0700 Subject: Allow usage of os="windows" in vcpkgTools.xml from vcpkg.exe (use-cases in powershell still need to be modified) --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index a17ffeb05..7ab4c1c98 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -44,11 +44,11 @@ namespace vcpkg static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool) { #if defined(_WIN32) - static constexpr StringLiteral OS_STRING = ""; + static constexpr StringLiteral OS_STRING = "windows"; #elif defined(__APPLE__) - static constexpr StringLiteral OS_STRING = R"(os="osx")"; + static constexpr StringLiteral OS_STRING = "osx"; #else // assume linux - static constexpr StringLiteral OS_STRING = R"(os="linux")"; + static constexpr StringLiteral OS_STRING = "linux"; #endif static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; @@ -79,11 +79,16 @@ namespace vcpkg Strings::format(R"###(([\s\S]*?))###")}; static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###")}; - const std::regex tool_regex{ - Strings::format(R"###(([\s\S]*?))###", tool, OS_STRING)}; + std::regex tool_regex{ + Strings::format(R"###(([\s\S]*?)<\/tool>)###", tool, OS_STRING)}; std::smatch match_tool; - const bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); + bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); + if (!has_match_tool && OS_STRING == "windows") // Legacy support. Change introduced in vcpkg v0.0.107. + { + tool_regex = Strings::format(R"###(([\s\S]*?)<\/tool>)###", tool); + has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); + } Checks::check_exit(VCPKG_LINE_INFO, has_match_tool, "Could not find entry for tool [%s] in %s", -- cgit v1.2.3 From adccba04db25b3e3bd44c58a9d2cbc1366e53fde Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 2 Apr 2018 17:12:12 -0700 Subject: [vcpkg.exe] Look for vcpkgTools in downloads/tools/$toolname-$toolversion (only non-windows currently) --- toolsrc/src/vcpkg/build.cpp | 6 +++ toolsrc/src/vcpkg/vcpkgpaths.cpp | 94 +++++++++++++++++++++++++++++++++------- 2 files changed, 85 insertions(+), 15 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 953e77460..ab2e46aa7 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -322,6 +322,12 @@ namespace vcpkg::Build auto& fs = paths.get_filesystem(); const Triplet& triplet = spec.triplet(); +#if !defined(_WIN32) + // TODO: remove when vcpkg.exe is in charge for acquiring tools. Change introduced in vcpkg v0.0.107. + // bootstrap should have already downloaded ninja, but making sure it is present in case it was deleted. + vcpkg::Util::unused(paths.get_ninja_exe()); +#endif + const fs::path& cmake_exe_path = paths.get_cmake_exe(); const fs::path& git_exe_path = paths.get_git_exe(); diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 7ab4c1c98..d4bcea5af 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -18,9 +18,10 @@ namespace vcpkg struct ToolData { std::array required_version; - fs::path downloaded_exe_path; + fs::path exe_path; std::string url; fs::path downloaded_path; + fs::path tool_dir_path; }; static Optional> parse_version_string(const std::string& version_as_string) @@ -114,11 +115,20 @@ namespace vcpkg tool, required_version_as_string); +// Legacy support. Change introduced in vcpkg v0.0.107. +#if !defined(_WIN32) + const std::string tool_dir_name = Strings::format("%s-%s", tool, required_version_as_string); + const fs::path tool_dir_path = paths.downloads / "tools" / tool_dir_name; + const fs::path exe_path = tool_dir_path / exe_relative_path; +#else + const fs::path tool_dir_path; const fs::path exe_path = paths.downloads / exe_relative_path; +#endif return ToolData{*required_version.get(), exe_path, url, - paths.downloads / archive_relative_path.value_or(exe_relative_path)}; + paths.downloads / archive_relative_path.value_or(exe_relative_path), + tool_dir_path}; } static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, @@ -177,6 +187,36 @@ namespace vcpkg return data_lines; } + static void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path) + { + Files::Filesystem& fs = paths.get_filesystem(); + const fs::path to_path_partial = to_path.u8string() + ".partial"; + + std::error_code ec; + fs.remove_all(to_path_partial, ec); + fs.create_directories(to_path_partial, ec); + + const auto ext = archive.extension(); + if (ext == ".gz" && ext.extension() != ".tar") + { + const auto code = System::cmd_execute( + Strings::format(R"(cd '%s' && tar xzf '%s')", to_path_partial.u8string(), archive.u8string())); + Checks::check_exit(VCPKG_LINE_INFO, code == 0, "tar failed while extracting %s", archive.u8string()); + } + else if (ext == ".zip") + { + const auto code = System::cmd_execute( + Strings::format(R"(cd '%s' && unzip -qqo '%s')", to_path_partial.u8string(), archive.u8string())); + Checks::check_exit(VCPKG_LINE_INFO, code == 0, "unzip failed while extracting %s", archive.u8string()); + } + else + { + Checks::exit_with_message(VCPKG_LINE_INFO, "Unexpected archive extension: %s", ext.u8string()); + } + + fs.rename(to_path_partial, to_path); + } + static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data) { const auto& fs = paths.get_filesystem(); @@ -200,7 +240,7 @@ namespace vcpkg Checks::check_exit(VCPKG_LINE_INFO, tool_path.size() == 1, "Expected tool path, but got %s", output); const fs::path actual_downloaded_path = Strings::trim(std::string{tool_path.at(0)}); - const fs::path& expected_downloaded_path = tool_data.downloaded_exe_path; + const fs::path& expected_downloaded_path = tool_data.exe_path; std::error_code ec; const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); Checks::check_exit(VCPKG_LINE_INFO, @@ -216,16 +256,17 @@ namespace vcpkg Strings::format(R"(curl '%s' --create-dirs --output '%s')", tool_data.url, tool_data.downloaded_path)); Checks::check_exit(VCPKG_LINE_INFO, code == 0, "curl failed while downloading %s", tool_data.url); } - auto code = System::cmd_execute( - Strings::format(R"(cd '%s' && tar xzf '%s')", paths.downloads, tool_data.downloaded_path)); - Checks::check_exit(VCPKG_LINE_INFO, code == 0, "tar failed while extracting %s", tool_data.downloaded_path); + + System::println("Extracting %s...", tool_name); + extract_archive(paths, tool_data.downloaded_path, tool_data.tool_dir_path); + System::println("Extracting %s... done.", tool_name); Checks::check_exit(VCPKG_LINE_INFO, - fs.exists(tool_data.downloaded_exe_path), + fs.exists(tool_data.exe_path), "Expected %s to exist after extracting", - tool_data.downloaded_exe_path); + tool_data.exe_path); - return tool_data.downloaded_exe_path; + return tool_data.exe_path; #endif } @@ -234,7 +275,7 @@ namespace vcpkg std::vector candidate_paths; #if defined(_WIN32) || defined(__APPLE__) || defined(__linux__) static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "cmake"); - candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); + candidate_paths.push_back(TOOL_DATA.exe_path); #else static const ToolData TOOL_DATA = ToolData{{3, 5, 1}, ""}; #endif @@ -262,22 +303,40 @@ namespace vcpkg { #if defined(_WIN32) static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "7zip"); - if (!paths.get_filesystem().exists(TOOL_DATA.downloaded_exe_path)) + if (!paths.get_filesystem().exists(TOOL_DATA.exe_path)) { return fetch_tool(paths, "7zip", TOOL_DATA); } - return TOOL_DATA.downloaded_exe_path; + return TOOL_DATA.exe_path; #else Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot download 7zip for non-Windows platforms."); #endif } + static fs::path get_ninja_path(const VcpkgPaths& paths) + { + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "ninja"); + + std::vector candidate_paths; + candidate_paths.push_back(TOOL_DATA.exe_path); + const std::vector from_path = Files::find_from_PATH("ninja"); + candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + + auto path = find_if_has_equal_or_greater_version(candidate_paths, "--version", TOOL_DATA.required_version); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_tool(paths, "ninja", TOOL_DATA); + } + static fs::path get_nuget_path(const VcpkgPaths& paths) { static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "nuget"); std::vector candidate_paths; - candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); + candidate_paths.push_back(TOOL_DATA.exe_path); const std::vector from_path = Files::find_from_PATH("nuget"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); @@ -301,7 +360,7 @@ namespace vcpkg std::vector candidate_paths; #if defined(_WIN32) - candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); + candidate_paths.push_back(TOOL_DATA.exe_path); #endif const std::vector from_path = Files::find_from_PATH("git"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); @@ -328,7 +387,7 @@ namespace vcpkg static const std::string VERSION_CHECK_ARGUMENTS = "--framework-version"; std::vector candidate_paths; - candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); + candidate_paths.push_back(TOOL_DATA.exe_path); // TODO: Uncomment later // const std::vector from_path = Files::find_from_PATH("installerbase"); // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); @@ -438,6 +497,11 @@ namespace vcpkg return this->git_exe.get_lazy([this]() { return get_git_path(*this); }); } + const fs::path& VcpkgPaths::get_ninja_exe() const + { + return this->ninja_exe.get_lazy([this]() { return get_ninja_path(*this); }); + } + const fs::path& VcpkgPaths::get_nuget_exe() const { return this->nuget_exe.get_lazy([this]() { return get_nuget_path(*this); }); -- cgit v1.2.3 From 892f7052f943570eb5d8da991ace01725323c695 Mon Sep 17 00:00:00 2001 From: Jacob Zhong Date: Wed, 7 Mar 2018 17:57:16 +0800 Subject: [vcpkg] Add support of external downloader aria2 --- toolsrc/src/vcpkg/build.cpp | 19 +++++++++++++++++-- toolsrc/src/vcpkg/install.cpp | 12 ++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index ab2e46aa7..79a55bd36 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -165,6 +165,19 @@ namespace vcpkg::Build } } + static const std::string NAME_BUILD_IN_DOWNLOAD = "BUILT_IN"; + static const std::string NAME_ARIA2_DOWNLOAD = "ARIA2"; + + const std::string& to_string(DownloadTool tool) + { + switch (tool) + { + case DownloadTool::BUILT_IN: return NAME_BUILD_IN_DOWNLOAD; + case DownloadTool::ARIA2: return NAME_ARIA2_DOWNLOAD; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + } + Optional to_linkage_type(const std::string& str) { if (str == "dynamic") return LinkageType::DYNAMIC; @@ -348,8 +361,10 @@ namespace vcpkg::Build {"TARGET_TRIPLET", spec.triplet().canonical_name()}, {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, {"VCPKG_USE_HEAD_VERSION", - Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, - {"_VCPKG_NO_DOWNLOADS", !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, + Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, + {"_VCPKG_NO_DOWNLOADS", + !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, + {"_VCPKG_DOWNLOAD_TOOL", to_string(config.build_package_options.download_tool)}, {"GIT", git_exe_path}, {"FEATURES", Strings::join(";", config.feature_list)}, {"ALL_FEATURES", all_features}, diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 1fbf6d97e..b998d19ab 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -412,13 +412,15 @@ namespace vcpkg::Install static constexpr StringLiteral OPTION_RECURSE = "--recurse"; static constexpr StringLiteral OPTION_KEEP_GOING = "--keep-going"; static constexpr StringLiteral OPTION_XUNIT = "--x-xunit"; + static constexpr StringLiteral OPTION_USE_ARIA2 = "--use-aria2"; - static constexpr std::array INSTALL_SWITCHES = {{ + static constexpr std::array INSTALL_SWITCHES = {{ {OPTION_DRY_RUN, "Do not actually build or install"}, {OPTION_USE_HEAD_VERSION, "Install the libraries on the command line using the latest upstream sources"}, {OPTION_NO_DOWNLOADS, "Do not download new sources"}, {OPTION_RECURSE, "Allow removal of packages as part of installation"}, {OPTION_KEEP_GOING, "Continue installing packages on failure"}, + {OPTION_USE_ARIA2, "Use aria2 to perform download tasks"}, }}; static constexpr std::array INSTALL_SETTINGS = {{ {OPTION_XUNIT, "File to output results in XUnit format (Internal use)"}, @@ -547,16 +549,22 @@ namespace vcpkg::Install const bool use_head_version = Util::Sets::contains(options.switches, (OPTION_USE_HEAD_VERSION)); const bool no_downloads = Util::Sets::contains(options.switches, (OPTION_NO_DOWNLOADS)); const bool is_recursive = Util::Sets::contains(options.switches, (OPTION_RECURSE)); + const bool use_aria2 = Util::Sets::contains(options.switches, (OPTION_USE_ARIA2)); const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING)); // create the plan StatusParagraphs status_db = database_load_check(paths); + Build::DownloadTool download_tool = Build::DownloadTool::BUILT_IN; + if (use_aria2) + download_tool = Build::DownloadTool::ARIA2; + const Build::BuildPackageOptions install_plan_options = { Util::Enum::to_enum(use_head_version), Util::Enum::to_enum(!no_downloads), Build::CleanBuildtrees::NO, - Build::CleanPackages::NO}; + Build::CleanPackages::NO, + download_tool}; auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); std::unordered_map scf_map; -- cgit v1.2.3 From 7849f5da1e72977745f9fd69365f70df98eb028e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 2 Apr 2018 18:37:16 -0700 Subject: [aria2] Use --x-use-aria2 instead of --use-aria2 for now --- toolsrc/src/vcpkg/install.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index b998d19ab..fc336d6c7 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -412,7 +412,7 @@ namespace vcpkg::Install static constexpr StringLiteral OPTION_RECURSE = "--recurse"; static constexpr StringLiteral OPTION_KEEP_GOING = "--keep-going"; static constexpr StringLiteral OPTION_XUNIT = "--x-xunit"; - static constexpr StringLiteral OPTION_USE_ARIA2 = "--use-aria2"; + static constexpr StringLiteral OPTION_USE_ARIA2 = "--x-use-aria2"; static constexpr std::array INSTALL_SWITCHES = {{ {OPTION_DRY_RUN, "Do not actually build or install"}, @@ -556,8 +556,7 @@ namespace vcpkg::Install StatusParagraphs status_db = database_load_check(paths); Build::DownloadTool download_tool = Build::DownloadTool::BUILT_IN; - if (use_aria2) - download_tool = Build::DownloadTool::ARIA2; + if (use_aria2) download_tool = Build::DownloadTool::ARIA2; const Build::BuildPackageOptions install_plan_options = { Util::Enum::to_enum(use_head_version), -- cgit v1.2.3 From 410c547fa14ba6197833f19f2180ba2c532c1722 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 3 Apr 2018 15:19:16 -0700 Subject: Use -L on curl --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index d4bcea5af..bda2c4174 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -252,8 +252,8 @@ namespace vcpkg #else if (!fs.exists(tool_data.downloaded_path)) { - auto code = System::cmd_execute( - Strings::format(R"(curl '%s' --create-dirs --output '%s')", tool_data.url, tool_data.downloaded_path)); + auto code = System::cmd_execute(Strings::format( + R"(curl -L '%s' --create-dirs --output '%s')", tool_data.url, tool_data.downloaded_path)); Checks::check_exit(VCPKG_LINE_INFO, code == 0, "curl failed while downloading %s", tool_data.url); } -- cgit v1.2.3 From 385df0b02b204e01fbe49c8e3d24c093b22db4b2 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 3 Apr 2018 15:28:47 -0700 Subject: Add vcpkg edit --all --- toolsrc/src/vcpkg/commands.edit.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index ac34a6720..94df9f9af 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -34,6 +34,8 @@ namespace vcpkg::Commands::Edit static constexpr StringLiteral OPTION_BUILDTREES = "--buildtrees"; + static constexpr StringLiteral OPTION_ALL = "--all"; + static std::vector valid_arguments(const VcpkgPaths& paths) { auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); @@ -42,9 +44,9 @@ namespace vcpkg::Commands::Edit [](auto&& pgh) -> std::string { return pgh->core_paragraph->name; }); } - static constexpr std::array EDIT_SWITCHES = {{ - {OPTION_BUILDTREES, "Open editor into the port-specific buildtree subfolder"}, - }}; + static constexpr std::array EDIT_SWITCHES = { + {{OPTION_BUILDTREES, "Open editor into the port-specific buildtree subfolder"}, + {OPTION_ALL, "Open editor into the port as well as the port-specific buildtree subfolder"}}}; const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("edit zlib"), @@ -113,6 +115,15 @@ namespace vcpkg::Commands::Edit Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); } + if (Util::Sets::contains(options.switches, OPTION_ALL)) + { + const auto buildtrees_current_dir = paths.buildtrees / port_name; + + const auto cmd_line = Strings::format( + R"("%s" "%s" %s -n)", env_editor.u8string(), portpath.u8string(), buildtrees_current_dir.u8string()); + Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); + } + const auto cmd_line = Strings::format( R"("%s" "%s" "%s" -n)", env_editor.u8string(), -- cgit v1.2.3 From 599aea98c9a2ef587fd9deacdfcf64dfa2e3c4db Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 3 Apr 2018 15:30:24 -0700 Subject: Add missing quotes --- toolsrc/src/vcpkg/commands.edit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index 94df9f9af..6c696018e 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -120,7 +120,7 @@ namespace vcpkg::Commands::Edit const auto buildtrees_current_dir = paths.buildtrees / port_name; const auto cmd_line = Strings::format( - R"("%s" "%s" %s -n)", env_editor.u8string(), portpath.u8string(), buildtrees_current_dir.u8string()); + R"("%s" "%s" "%s" -n)", env_editor.u8string(), portpath.u8string(), buildtrees_current_dir.u8string()); Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); } -- cgit v1.2.3 From 31377dee20dad9b95357934732996e2448f2eaf5 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 3 Apr 2018 21:05:31 -0700 Subject: Use 7z for extracting. Extract tools in downloads/tools --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index bda2c4174..f2086257e 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -115,15 +115,9 @@ namespace vcpkg tool, required_version_as_string); -// Legacy support. Change introduced in vcpkg v0.0.107. -#if !defined(_WIN32) - const std::string tool_dir_name = Strings::format("%s-%s", tool, required_version_as_string); + const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, required_version_as_string, OS_STRING); const fs::path tool_dir_path = paths.downloads / "tools" / tool_dir_name; const fs::path exe_path = tool_dir_path / exe_relative_path; -#else - const fs::path tool_dir_path; - const fs::path exe_path = paths.downloads / exe_relative_path; -#endif return ToolData{*required_version.get(), exe_path, url, -- cgit v1.2.3 From 0c0f68939e0d8367e55793f80f0000f2a43a812a Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 4 Apr 2018 01:45:45 -0700 Subject: Introduce "vcpkg fetch" --- toolsrc/src/vcpkg/build.cpp | 15 +- toolsrc/src/vcpkg/commands.cpp | 9 +- toolsrc/src/vcpkg/commands.create.cpp | 2 +- toolsrc/src/vcpkg/commands.exportifw.cpp | 6 +- toolsrc/src/vcpkg/commands.fetch.cpp | 656 +++++++++++++++++++++++++++++++ toolsrc/src/vcpkg/commands.integrate.cpp | 2 +- toolsrc/src/vcpkg/commands.portsdiff.cpp | 4 +- toolsrc/src/vcpkg/export.cpp | 4 +- toolsrc/src/vcpkg/vcpkgpaths.cpp | 654 +----------------------------- 9 files changed, 687 insertions(+), 665 deletions(-) create mode 100644 toolsrc/src/vcpkg/commands.fetch.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 79a55bd36..86d171534 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -341,8 +341,8 @@ namespace vcpkg::Build vcpkg::Util::unused(paths.get_ninja_exe()); #endif - const fs::path& cmake_exe_path = paths.get_cmake_exe(); - const fs::path& git_exe_path = paths.get_git_exe(); + const fs::path& cmake_exe_path = paths.get_tool_exe(Tools::CMAKE); + const fs::path& git_exe_path = paths.get_tool_exe(Tools::GIT); std::string all_features; for (auto& feature : config.scf.feature_paragraphs) @@ -361,9 +361,8 @@ namespace vcpkg::Build {"TARGET_TRIPLET", spec.triplet().canonical_name()}, {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, {"VCPKG_USE_HEAD_VERSION", - Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, - {"_VCPKG_NO_DOWNLOADS", - !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, + Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, + {"_VCPKG_NO_DOWNLOADS", !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, {"_VCPKG_DOWNLOAD_TOOL", to_string(config.build_package_options.download_tool)}, {"GIT", git_exe_path}, {"FEATURES", Strings::join(";", config.feature_list)}, @@ -519,7 +518,7 @@ namespace vcpkg::Build Checks::check_exit(VCPKG_LINE_INFO, files.empty(), "unable to clear path: %s", pkg_path.u8string()); #if defined(_WIN32) - auto&& _7za = paths.get_7za_exe(); + auto&& _7za = paths.get_tool_exe(Tools::SEVEN_ZIP); System::cmd_execute_clean(Strings::format( R"("%s" x "%s" -o"%s" -y >nul)", _7za.u8string(), archive_path.u8string(), pkg_path.u8string())); @@ -539,7 +538,7 @@ namespace vcpkg::Build Checks::check_exit( VCPKG_LINE_INFO, !fs.exists(tmp_archive_path), "Could not remove file: %s", tmp_archive_path.u8string()); #if defined(_WIN32) - auto&& _7za = paths.get_7za_exe(); + auto&& _7za = paths.get_tool_exe(Tools::SEVEN_ZIP); System::cmd_execute_clean(Strings::format( R"("%s" a "%s" "%s\*" >nul)", @@ -771,7 +770,7 @@ namespace vcpkg::Build { static constexpr CStringView FLAG_GUID = "c35112b6-d1ba-415b-aa5d-81de856ef8eb"; - const fs::path& cmake_exe_path = paths.get_cmake_exe(); + const fs::path& cmake_exe_path = paths.get_tool_exe(Tools::CMAKE); const fs::path ports_cmake_script_path = paths.scripts / "get_triplet_environment.cmake"; const fs::path triplet_file_path = paths.triplets / (triplet.canonical_name() + ".cmake"); diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index d9c0e54cd..e98ff711a 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -43,16 +43,15 @@ namespace vcpkg::Commands {"portsdiff", &PortsDiff::perform_and_exit}, {"autocomplete", &Autocomplete::perform_and_exit}, {"hash", &Hash::perform_and_exit}, - }; + {"fetch", &Fetch::perform_and_exit}, + }; return t; } Span> get_available_commands_type_c() { - static std::vector> t = { - {"version", &Version::perform_and_exit}, - {"contact", &Contact::perform_and_exit} - }; + static std::vector> t = {{"version", &Version::perform_and_exit}, + {"contact", &Contact::perform_and_exit}}; return t; } } diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp index 25c34cf09..60769c9ef 100644 --- a/toolsrc/src/vcpkg/commands.create.cpp +++ b/toolsrc/src/vcpkg/commands.create.cpp @@ -22,7 +22,7 @@ namespace vcpkg::Commands::Create const std::string port_name = args.command_arguments.at(0); const std::string url = args.command_arguments.at(1); - const fs::path& cmake_exe = paths.get_cmake_exe(); + const fs::path& cmake_exe = paths.get_tool_exe(Tools::CMAKE); std::vector cmake_args{{"CMD", "CREATE"}, {"PORT", port_name}, {"URL", url}}; diff --git a/toolsrc/src/vcpkg/commands.exportifw.cpp b/toolsrc/src/vcpkg/commands.exportifw.cpp index 58d9aa0be..ae106196a 100644 --- a/toolsrc/src/vcpkg/commands.exportifw.cpp +++ b/toolsrc/src/vcpkg/commands.exportifw.cpp @@ -291,7 +291,7 @@ namespace vcpkg::Export::IFW std::error_code ec; Files::Filesystem& fs = paths.get_filesystem(); - const fs::path& installerbase_exe = paths.get_ifw_installerbase_exe(); + const fs::path& installerbase_exe = paths.get_tool_exe(Tools::IFW_INSTALLER_BASE); fs::path tempmaintenancetool = ifw_packages_dir_path / "maintenance" / "data" / "tempmaintenancetool.exe"; fs.create_directories(tempmaintenancetool.parent_path(), ec); Checks::check_exit(VCPKG_LINE_INFO, @@ -335,7 +335,7 @@ namespace vcpkg::Export::IFW void do_repository(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) { - const fs::path& repogen_exe = paths.get_ifw_repogen_exe(); + const fs::path& repogen_exe = paths.get_tool_exe(Tools::IFW_REPOGEN); const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); @@ -361,7 +361,7 @@ namespace vcpkg::Export::IFW void do_installer(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) { - const fs::path& binarycreator_exe = paths.get_ifw_binarycreator_exe(); + const fs::path& binarycreator_exe = paths.get_tool_exe(Tools::IFW_BINARYCREATOR); const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp new file mode 100644 index 000000000..95c47e2db --- /dev/null +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -0,0 +1,656 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include + +namespace vcpkg::Commands::Fetch +{ + static constexpr CStringView V_120 = "v120"; + static constexpr CStringView V_140 = "v140"; + static constexpr CStringView V_141 = "v141"; + + struct ToolData + { + std::array required_version; + fs::path exe_path; + std::string url; + fs::path downloaded_path; + fs::path tool_dir_path; + }; + + static Optional> parse_version_string(const std::string& version_as_string) + { + static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###"); + + std::match_results match; + const auto found = std::regex_search(version_as_string, match, RE); + if (!found) + { + return {}; + } + + const int d1 = atoi(match[1].str().c_str()); + const int d2 = atoi(match[2].str().c_str()); + const int d3 = atoi(match[3].str().c_str()); + const std::array result = {d1, d2, d3}; + return result; + } + + static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool) + { +#if defined(_WIN32) + static constexpr StringLiteral OS_STRING = "windows"; +#elif defined(__APPLE__) + static constexpr StringLiteral OS_STRING = "osx"; +#else // assume linux + static constexpr StringLiteral OS_STRING = "linux"; +#endif + + static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; + + const auto maybe_get_string_inside_tags = [](const std::string& input, + const std::regex& regex) -> Optional { + std::smatch match; + const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); + if (!has_match) return nullopt; + return match[1]; + }; + + const auto get_string_inside_tags = + [](const std::string& input, const std::regex& regex, const std::string& tag_name) -> std::string { + std::smatch match; + const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); + Checks::check_exit( + VCPKG_LINE_INFO, has_match, "Could not find tag <%s> in %s", tag_name, XML_PATH.generic_string()); + + return match[1]; + }; + + static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO); + static const std::regex VERSION_REGEX{R"###(([\s\S]*?))###"}; + static const std::regex EXE_RELATIVE_PATH_REGEX{ + Strings::format(R"###(([\s\S]*?))###")}; + static const std::regex ARCHIVE_RELATIVE_PATH_REGEX{ + Strings::format(R"###(([\s\S]*?))###")}; + static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###")}; + + std::regex tool_regex{ + Strings::format(R"###(([\s\S]*?)<\/tool>)###", tool, OS_STRING)}; + + std::smatch match_tool; + bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); + if (!has_match_tool && OS_STRING == "windows") // Legacy support. Change introduced in vcpkg v0.0.107. + { + tool_regex = Strings::format(R"###(([\s\S]*?)<\/tool>)###", tool); + has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); + } + Checks::check_exit(VCPKG_LINE_INFO, + has_match_tool, + "Could not find entry for tool [%s] in %s", + tool, + XML_PATH.generic_string()); + + const std::string tool_data_as_string = get_string_inside_tags(XML, tool_regex, tool); + + const std::string required_version_as_string = + get_string_inside_tags(tool_data_as_string, VERSION_REGEX, "requiredVersion"); + + const std::string url = get_string_inside_tags(tool_data_as_string, URL_REGEX, "url"); + + const std::string exe_relative_path = + get_string_inside_tags(tool_data_as_string, EXE_RELATIVE_PATH_REGEX, "exeRelativePath"); + + auto archive_relative_path = maybe_get_string_inside_tags(tool_data_as_string, ARCHIVE_RELATIVE_PATH_REGEX); + + const Optional> required_version = parse_version_string(required_version_as_string); + Checks::check_exit(VCPKG_LINE_INFO, + required_version.has_value(), + "Could not parse version for tool %s. Version string was: %s", + tool, + required_version_as_string); + + const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, required_version_as_string, OS_STRING); + const fs::path tool_dir_path = paths.downloads / "tools" / tool_dir_name; + const fs::path exe_path = tool_dir_path / exe_relative_path; + return ToolData{*required_version.get(), + exe_path, + url, + paths.downloads / archive_relative_path.value_or(exe_relative_path), + tool_dir_path}; + } + + static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, + const std::array& expected_version) + { + const auto rc = System::cmd_execute_and_capture_output(Strings::format(R"(%s)", version_cmd)); + if (rc.exit_code != 0) + { + return false; + } + + const Optional> v = parse_version_string(rc.output); + if (!v.has_value()) + { + return false; + } + + const std::array actual_version = *v.get(); + return (actual_version[0] > expected_version[0] || + (actual_version[0] == expected_version[0] && actual_version[1] > expected_version[1]) || + (actual_version[0] == expected_version[0] && actual_version[1] == expected_version[1] && + actual_version[2] >= expected_version[2])); + } + + static Optional find_if_has_equal_or_greater_version(const std::vector& candidate_paths, + const std::string& version_check_arguments, + const std::array& expected_version) + { + auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { + const std::string cmd = Strings::format(R"("%s" %s)", p.u8string(), version_check_arguments); + return exists_and_has_equal_or_greater_version(cmd, expected_version); + }); + + if (it != candidate_paths.cend()) + { + return std::move(*it); + } + + return nullopt; + } + + static std::vector keep_data_lines(const std::string& data_blob) + { + static const std::regex DATA_LINE_REGEX(R"(::(.+?)(?=::))"); + + std::vector data_lines; + + const std::sregex_iterator it(data_blob.cbegin(), data_blob.cend(), DATA_LINE_REGEX); + const std::sregex_iterator end; + for (std::sregex_iterator i = it; i != end; ++i) + { + const std::smatch match = *i; + data_lines.push_back(match[1].str()); + } + + return data_lines; + } + + static void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path) + { + Files::Filesystem& fs = paths.get_filesystem(); + const fs::path to_path_partial = to_path.u8string() + ".partial"; + + std::error_code ec; + fs.remove_all(to_path_partial, ec); + fs.create_directories(to_path_partial, ec); + + const auto ext = archive.extension(); + if (ext == ".gz" && ext.extension() != ".tar") + { + const auto code = System::cmd_execute( + Strings::format(R"(cd '%s' && tar xzf '%s')", to_path_partial.u8string(), archive.u8string())); + Checks::check_exit(VCPKG_LINE_INFO, code == 0, "tar failed while extracting %s", archive.u8string()); + } + else if (ext == ".zip") + { + const auto code = System::cmd_execute( + Strings::format(R"(cd '%s' && unzip -qqo '%s')", to_path_partial.u8string(), archive.u8string())); + Checks::check_exit(VCPKG_LINE_INFO, code == 0, "unzip failed while extracting %s", archive.u8string()); + } + else + { + Checks::exit_with_message(VCPKG_LINE_INFO, "Unexpected archive extension: %s", ext.u8string()); + } + + fs.rename(to_path_partial, to_path); + } + + static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data) + { + const auto& fs = paths.get_filesystem(); + const fs::path& scripts_folder = paths.scripts; + const std::array& version = tool_data.required_version; + + const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); + System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", + tool_name, + version_as_string, + tool_name, + version_as_string); +#if defined(_WIN32) + const fs::path script = scripts_folder / "fetchtool.ps1"; + const std::string title = Strings::format( + "Fetching %s version %s (No sufficient installed version was found)", tool_name, version_as_string); + const System::PowershellParameter tool_param("tool", tool_name); + const std::string output = System::powershell_execute_and_capture_output(title, script, {tool_param}); + + const std::vector tool_path = keep_data_lines(output); + Checks::check_exit(VCPKG_LINE_INFO, tool_path.size() == 1, "Expected tool path, but got %s", output); + + const fs::path actual_downloaded_path = Strings::trim(std::string{tool_path.at(0)}); + const fs::path& expected_downloaded_path = tool_data.exe_path; + std::error_code ec; + const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + eq && !ec, + "Expected tool downloaded path to be %s, but was %s", + expected_downloaded_path.u8string(), + actual_downloaded_path.u8string()); + return actual_downloaded_path; +#else + if (!fs.exists(tool_data.downloaded_path)) + { + auto code = System::cmd_execute(Strings::format( + R"(curl -L '%s' --create-dirs --output '%s')", tool_data.url, tool_data.downloaded_path)); + Checks::check_exit(VCPKG_LINE_INFO, code == 0, "curl failed while downloading %s", tool_data.url); + } + + System::println("Extracting %s...", tool_name); + extract_archive(paths, tool_data.downloaded_path, tool_data.tool_dir_path); + System::println("Extracting %s... done.", tool_name); + + Checks::check_exit(VCPKG_LINE_INFO, + fs.exists(tool_data.exe_path), + "Expected %s to exist after extracting", + tool_data.exe_path); + + return tool_data.exe_path; +#endif + } + + static fs::path get_cmake_path(const VcpkgPaths& paths) + { + std::vector candidate_paths; +#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__) + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "cmake"); + candidate_paths.push_back(TOOL_DATA.exe_path); +#else + static const ToolData TOOL_DATA = ToolData{{3, 5, 1}, ""}; +#endif + static const std::string VERSION_CHECK_ARGUMENTS = "--version"; + + const std::vector from_path = Files::find_from_PATH("cmake"); + candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + + const auto& program_files = System::get_program_files_platform_bitness(); + if (const auto pf = program_files.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe"); + const auto& program_files_32_bit = System::get_program_files_32_bit(); + if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe"); + + const Optional path = + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_tool(paths, "cmake", TOOL_DATA); + } + + static fs::path get_7za_path(const VcpkgPaths& paths) + { +#if defined(_WIN32) + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "7zip"); + if (!paths.get_filesystem().exists(TOOL_DATA.exe_path)) + { + return fetch_tool(paths, "7zip", TOOL_DATA); + } + return TOOL_DATA.exe_path; +#else + Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot download 7zip for non-Windows platforms."); +#endif + } + + static fs::path get_ninja_path(const VcpkgPaths& paths) + { + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "ninja"); + + std::vector candidate_paths; + candidate_paths.push_back(TOOL_DATA.exe_path); + const std::vector from_path = Files::find_from_PATH("ninja"); + candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + + auto path = find_if_has_equal_or_greater_version(candidate_paths, "--version", TOOL_DATA.required_version); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_tool(paths, "ninja", TOOL_DATA); + } + + static fs::path get_nuget_path(const VcpkgPaths& paths) + { + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "nuget"); + + std::vector candidate_paths; + candidate_paths.push_back(TOOL_DATA.exe_path); + const std::vector from_path = Files::find_from_PATH("nuget"); + candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + + auto path = find_if_has_equal_or_greater_version(candidate_paths, "", TOOL_DATA.required_version); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_tool(paths, "nuget", TOOL_DATA); + } + + static fs::path get_git_path(const VcpkgPaths& paths) + { +#if defined(_WIN32) + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "git"); +#else + static const ToolData TOOL_DATA = ToolData{{2, 7, 4}, ""}; +#endif + static const std::string VERSION_CHECK_ARGUMENTS = "--version"; + + std::vector candidate_paths; +#if defined(_WIN32) + candidate_paths.push_back(TOOL_DATA.exe_path); +#endif + const std::vector from_path = Files::find_from_PATH("git"); + candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + + const auto& program_files = System::get_program_files_platform_bitness(); + if (const auto pf = program_files.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe"); + const auto& program_files_32_bit = System::get_program_files_32_bit(); + if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe"); + + const Optional path = + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_tool(paths, "git", TOOL_DATA); + } + + static fs::path get_ifw_installerbase_path(const VcpkgPaths& paths) + { + static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "installerbase"); + + static const std::string VERSION_CHECK_ARGUMENTS = "--framework-version"; + + std::vector candidate_paths; + candidate_paths.push_back(TOOL_DATA.exe_path); + // TODO: Uncomment later + // const std::vector from_path = Files::find_from_PATH("installerbase"); + // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + // candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" / + // "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe"); + // candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" / + // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); + + const Optional path = + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_tool(paths, "installerbase", TOOL_DATA); + } + + struct VisualStudioInstance + { + fs::path root_path; + std::string version; + std::string release_type; + std::string preference_weight; // Mostly unused, just for verification that order is as intended + + std::string major_version() const { return version.substr(0, 2); } + }; + + static std::vector get_visual_studio_instances(const VcpkgPaths& paths) + { + const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; + const std::string output = + System::powershell_execute_and_capture_output("Detecting Visual Studio instances", script); + + const std::vector instances_as_strings = keep_data_lines(output); + Checks::check_exit(VCPKG_LINE_INFO, + !instances_as_strings.empty(), + "Could not detect any Visual Studio instances.\n" + "Powershell script:\n" + " %s\n" + "returned:\n" + "%s", + script.generic_string(), + output); + + std::vector instances; + for (const std::string& instance_as_string : instances_as_strings) + { + const std::vector split = Strings::split(instance_as_string, "::"); + Checks::check_exit(VCPKG_LINE_INFO, + split.size() == 4, + "Invalid Visual Studio instance format.\n" + "Expected: PreferenceWeight::ReleaseType::Version::PathToVisualStudio\n" + "Actual : %s\n", + instance_as_string); + instances.push_back({split.at(3), split.at(2), split.at(1), split.at(0)}); + } + + return instances; + } + + std::vector find_toolset_instances(const VcpkgPaths& paths) + { + using CPU = System::CPUArchitecture; + + const auto& fs = paths.get_filesystem(); + + // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. + std::vector paths_examined; + + std::vector found_toolsets; + std::vector excluded_toolsets; + + const std::vector vs_instances = get_visual_studio_instances(paths); + const bool v140_is_available = Util::find_if(vs_instances, [&](const VisualStudioInstance& vs_instance) { + return vs_instance.major_version() == "14"; + }) != vs_instances.cend(); + + for (const VisualStudioInstance& vs_instance : vs_instances) + { + const std::string major_version = vs_instance.major_version(); + if (major_version == "15") + { + const fs::path vc_dir = vs_instance.root_path / "VC"; + + // Skip any instances that do not have vcvarsall. + const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build"; + const fs::path vcvarsall_bat = vcvarsall_dir / "vcvarsall.bat"; + paths_examined.push_back(vcvarsall_bat); + if (!fs.exists(vcvarsall_bat)) continue; + + // Get all supported architectures + std::vector supported_architectures; + if (fs.exists(vcvarsall_dir / "vcvars32.bat")) + supported_architectures.push_back({"x86", CPU::X86, CPU::X86}); + if (fs.exists(vcvarsall_dir / "vcvars64.bat")) + supported_architectures.push_back({"amd64", CPU::X64, CPU::X64}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) + supported_architectures.push_back({"x86_amd64", CPU::X86, CPU::X64}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) + supported_architectures.push_back({"x86_arm", CPU::X86, CPU::ARM}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_arm64.bat")) + supported_architectures.push_back({"x86_arm64", CPU::X86, CPU::ARM64}); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) + supported_architectures.push_back({"amd64_x86", CPU::X64, CPU::X86}); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) + supported_architectures.push_back({"amd64_arm", CPU::X64, CPU::ARM}); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm64.bat")) + supported_architectures.push_back({"amd64_arm64", CPU::X64, CPU::ARM64}); + + // Locate the "best" MSVC toolchain version + const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; + std::vector msvc_subdirectories = fs.get_files_non_recursive(msvc_path); + Util::unstable_keep_if(msvc_subdirectories, + [&fs](const fs::path& path) { return fs.is_directory(path); }); + + // Sort them so that latest comes first + std::sort( + msvc_subdirectories.begin(), + msvc_subdirectories.end(), + [](const fs::path& left, const fs::path& right) { return left.filename() > right.filename(); }); + + for (const fs::path& subdir : msvc_subdirectories) + { + const fs::path dumpbin_path = subdir / "bin" / "HostX86" / "x86" / "dumpbin.exe"; + paths_examined.push_back(dumpbin_path); + if (fs.exists(dumpbin_path)) + { + const Toolset v141toolset = Toolset{ + vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}; + + auto english_language_pack = dumpbin_path.parent_path() / "1033"; + + if (!fs.exists(english_language_pack)) + { + excluded_toolsets.push_back(v141toolset); + break; + } + + found_toolsets.push_back(v141toolset); + + if (v140_is_available) + { + const Toolset v140toolset = Toolset{vs_instance.root_path, + dumpbin_path, + vcvarsall_bat, + {"-vcvars_ver=14.0"}, + V_140, + supported_architectures}; + found_toolsets.push_back(v140toolset); + } + + break; + } + } + + continue; + } + + if (major_version == "14" || major_version == "12") + { + const fs::path vcvarsall_bat = vs_instance.root_path / "VC" / "vcvarsall.bat"; + + paths_examined.push_back(vcvarsall_bat); + if (fs.exists(vcvarsall_bat)) + { + const fs::path vs_dumpbin_exe = vs_instance.root_path / "VC" / "bin" / "dumpbin.exe"; + paths_examined.push_back(vs_dumpbin_exe); + + const fs::path vs_bin_dir = vcvarsall_bat.parent_path() / "bin"; + std::vector supported_architectures; + if (fs.exists(vs_bin_dir / "vcvars32.bat")) + supported_architectures.push_back({"x86", CPU::X86, CPU::X86}); + if (fs.exists(vs_bin_dir / "amd64\\vcvars64.bat")) + supported_architectures.push_back({"x64", CPU::X64, CPU::X64}); + if (fs.exists(vs_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) + supported_architectures.push_back({"x86_amd64", CPU::X86, CPU::X64}); + if (fs.exists(vs_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) + supported_architectures.push_back({"x86_arm", CPU::X86, CPU::ARM}); + if (fs.exists(vs_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) + supported_architectures.push_back({"amd64_x86", CPU::X64, CPU::X86}); + if (fs.exists(vs_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) + supported_architectures.push_back({"amd64_arm", CPU::X64, CPU::ARM}); + + if (fs.exists(vs_dumpbin_exe)) + { + const Toolset toolset = {vs_instance.root_path, + vs_dumpbin_exe, + vcvarsall_bat, + {}, + major_version == "14" ? V_140 : V_120, + supported_architectures}; + + auto english_language_pack = vs_dumpbin_exe.parent_path() / "1033"; + + if (!fs.exists(english_language_pack)) + { + excluded_toolsets.push_back(toolset); + break; + } + + found_toolsets.push_back(toolset); + } + } + } + } + + if (!excluded_toolsets.empty()) + { + System::println( + System::Color::warning, + "Warning: The following VS instances are excluded because the English language pack is unavailable."); + for (const Toolset& toolset : excluded_toolsets) + { + System::println(" %s", toolset.visual_studio_root_path.u8string()); + } + System::println(System::Color::warning, "Please install the English language pack."); + } + + if (found_toolsets.empty()) + { + System::println(System::Color::error, "Could not locate a complete toolset."); + System::println("The following paths were examined:"); + for (const fs::path& path : paths_examined) + { + System::println(" %s", path.u8string()); + } + Checks::exit_fail(VCPKG_LINE_INFO); + } + + return found_toolsets; + } + + fs::path get_tool_path(const VcpkgPaths& paths, const std::string& tool) + { + // First deal with specially handled tools. + // For these we may look in locations like Program Files, the PATH etc as well as the auto-downloaded location. + if (tool == Tools::SEVEN_ZIP) return get_7za_path(paths); + if (tool == Tools::CMAKE) return get_cmake_path(paths); + if (tool == Tools::GIT) return get_git_path(paths); + if (tool == Tools::NINJA) return get_ninja_path(paths); + if (tool == Tools::NUGET) return get_nuget_path(paths); + if (tool == Tools::IFW_INSTALLER_BASE) return get_ifw_installerbase_path(paths); + if (tool == Tools::IFW_BINARYCREATOR) + return get_ifw_installerbase_path(paths).parent_path() / "binarycreator.exe"; + if (tool == Tools::IFW_REPOGEN) return get_ifw_installerbase_path(paths).parent_path() / "repogen.exe"; + + // For other tools, we simply always auto-download them. + const ToolData tool_data = parse_tool_data_from_xml(paths, tool); + if (paths.get_filesystem().exists(tool_data.exe_path)) + { + return tool_data.exe_path; + } + return fetch_tool(paths, tool, tool_data); + } + + const CommandStructure COMMAND_STRUCTURE = { + Strings::format("The argument should be tool name\n%s", Help::create_example_string("fetch cmake")), + 1, + 1, + {}, + nullptr, + }; + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); + + const std::string tool = args.command_arguments[0]; + const fs::path tool_path = get_tool_path(paths, tool); + System::println(tool_path.u8string()); + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 36e4e56e7..d6ae27181 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -276,7 +276,7 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")", { auto& fs = paths.get_filesystem(); - const fs::path& nuget_exe = paths.get_nuget_exe(); + const fs::path& nuget_exe = paths.get_tool_exe(Tools::NUGET); const fs::path& buildsystems_dir = paths.buildsystems; const fs::path tmp_dir = buildsystems_dir / "tmp"; diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp index dba04ce5b..c6b02582f 100644 --- a/toolsrc/src/vcpkg/commands.portsdiff.cpp +++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp @@ -79,7 +79,7 @@ namespace vcpkg::Commands::PortsDiff { std::error_code ec; auto& fs = paths.get_filesystem(); - const fs::path& git_exe = paths.get_git_exe(); + const fs::path& git_exe = paths.get_tool_exe(Tools::GIT); const fs::path dot_git_dir = paths.root / ".git"; const std::string ports_dir_name_as_string = paths.ports.filename().u8string(); const fs::path temp_checkout_path = @@ -130,7 +130,7 @@ namespace vcpkg::Commands::PortsDiff { args.parse_arguments(COMMAND_STRUCTURE); - const fs::path& git_exe = paths.get_git_exe(); + const fs::path& git_exe = paths.get_tool_exe(Tools::GIT); const std::string git_commit_id_for_previous_snapshot = args.command_arguments.at(0); const std::string git_commit_id_for_current_snapshot = diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 16c84f99d..32151c791 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -123,7 +123,7 @@ namespace vcpkg::Export const fs::path& output_dir) { Files::Filesystem& fs = paths.get_filesystem(); - const fs::path& nuget_exe = paths.get_nuget_exe(); + const fs::path& nuget_exe = paths.get_tool_exe(Tools::NUGET); // This file will be placed in "build\native" in the nuget package. Therefore, go up two dirs. const std::string targets_redirect_content = @@ -189,7 +189,7 @@ namespace vcpkg::Export const fs::path& output_dir, const ArchiveFormat& format) { - const fs::path& cmake_exe = paths.get_cmake_exe(); + const fs::path& cmake_exe = paths.get_tool_exe(Tools::CMAKE); const std::string exported_dir_filename = raw_exported_dir.filename().u8string(); const std::string exported_archive_filename = diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index f2086257e..4f998d579 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -5,401 +5,13 @@ #include #include #include +#include #include #include #include namespace vcpkg { - static constexpr CStringView V_120 = "v120"; - static constexpr CStringView V_140 = "v140"; - static constexpr CStringView V_141 = "v141"; - - struct ToolData - { - std::array required_version; - fs::path exe_path; - std::string url; - fs::path downloaded_path; - fs::path tool_dir_path; - }; - - static Optional> parse_version_string(const std::string& version_as_string) - { - static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###"); - - std::match_results match; - const auto found = std::regex_search(version_as_string, match, RE); - if (!found) - { - return {}; - } - - const int d1 = atoi(match[1].str().c_str()); - const int d2 = atoi(match[2].str().c_str()); - const int d3 = atoi(match[3].str().c_str()); - const std::array result = {d1, d2, d3}; - return result; - } - - static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool) - { -#if defined(_WIN32) - static constexpr StringLiteral OS_STRING = "windows"; -#elif defined(__APPLE__) - static constexpr StringLiteral OS_STRING = "osx"; -#else // assume linux - static constexpr StringLiteral OS_STRING = "linux"; -#endif - - static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; - - const auto maybe_get_string_inside_tags = [](const std::string& input, - const std::regex& regex) -> Optional { - std::smatch match; - const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); - if (!has_match) return nullopt; - return match[1]; - }; - - const auto get_string_inside_tags = - [](const std::string& input, const std::regex& regex, const std::string& tag_name) -> std::string { - std::smatch match; - const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); - Checks::check_exit( - VCPKG_LINE_INFO, has_match, "Could not find tag <%s> in %s", tag_name, XML_PATH.generic_string()); - - return match[1]; - }; - - static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO); - static const std::regex VERSION_REGEX{R"###(([\s\S]*?))###"}; - static const std::regex EXE_RELATIVE_PATH_REGEX{ - Strings::format(R"###(([\s\S]*?))###")}; - static const std::regex ARCHIVE_RELATIVE_PATH_REGEX{ - Strings::format(R"###(([\s\S]*?))###")}; - static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###")}; - - std::regex tool_regex{ - Strings::format(R"###(([\s\S]*?)<\/tool>)###", tool, OS_STRING)}; - - std::smatch match_tool; - bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); - if (!has_match_tool && OS_STRING == "windows") // Legacy support. Change introduced in vcpkg v0.0.107. - { - tool_regex = Strings::format(R"###(([\s\S]*?)<\/tool>)###", tool); - has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); - } - Checks::check_exit(VCPKG_LINE_INFO, - has_match_tool, - "Could not find entry for tool [%s] in %s", - tool, - XML_PATH.generic_string()); - - const std::string tool_data_as_string = get_string_inside_tags(XML, tool_regex, tool); - - const std::string required_version_as_string = - get_string_inside_tags(tool_data_as_string, VERSION_REGEX, "requiredVersion"); - - const std::string url = get_string_inside_tags(tool_data_as_string, URL_REGEX, "url"); - - const std::string exe_relative_path = - get_string_inside_tags(tool_data_as_string, EXE_RELATIVE_PATH_REGEX, "exeRelativePath"); - - auto archive_relative_path = maybe_get_string_inside_tags(tool_data_as_string, ARCHIVE_RELATIVE_PATH_REGEX); - - const Optional> required_version = parse_version_string(required_version_as_string); - Checks::check_exit(VCPKG_LINE_INFO, - required_version.has_value(), - "Could not parse version for tool %s. Version string was: %s", - tool, - required_version_as_string); - - const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, required_version_as_string, OS_STRING); - const fs::path tool_dir_path = paths.downloads / "tools" / tool_dir_name; - const fs::path exe_path = tool_dir_path / exe_relative_path; - return ToolData{*required_version.get(), - exe_path, - url, - paths.downloads / archive_relative_path.value_or(exe_relative_path), - tool_dir_path}; - } - - static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, - const std::array& expected_version) - { - const auto rc = System::cmd_execute_and_capture_output(Strings::format(R"(%s)", version_cmd)); - if (rc.exit_code != 0) - { - return false; - } - - const Optional> v = parse_version_string(rc.output); - if (!v.has_value()) - { - return false; - } - - const std::array actual_version = *v.get(); - return (actual_version[0] > expected_version[0] || - (actual_version[0] == expected_version[0] && actual_version[1] > expected_version[1]) || - (actual_version[0] == expected_version[0] && actual_version[1] == expected_version[1] && - actual_version[2] >= expected_version[2])); - } - - static Optional find_if_has_equal_or_greater_version(const std::vector& candidate_paths, - const std::string& version_check_arguments, - const std::array& expected_version) - { - auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { - const std::string cmd = Strings::format(R"("%s" %s)", p.u8string(), version_check_arguments); - return exists_and_has_equal_or_greater_version(cmd, expected_version); - }); - - if (it != candidate_paths.cend()) - { - return std::move(*it); - } - - return nullopt; - } - - static std::vector keep_data_lines(const std::string& data_blob) - { - static const std::regex DATA_LINE_REGEX(R"(::(.+?)(?=::))"); - - std::vector data_lines; - - const std::sregex_iterator it(data_blob.cbegin(), data_blob.cend(), DATA_LINE_REGEX); - const std::sregex_iterator end; - for (std::sregex_iterator i = it; i != end; ++i) - { - const std::smatch match = *i; - data_lines.push_back(match[1].str()); - } - - return data_lines; - } - - static void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path) - { - Files::Filesystem& fs = paths.get_filesystem(); - const fs::path to_path_partial = to_path.u8string() + ".partial"; - - std::error_code ec; - fs.remove_all(to_path_partial, ec); - fs.create_directories(to_path_partial, ec); - - const auto ext = archive.extension(); - if (ext == ".gz" && ext.extension() != ".tar") - { - const auto code = System::cmd_execute( - Strings::format(R"(cd '%s' && tar xzf '%s')", to_path_partial.u8string(), archive.u8string())); - Checks::check_exit(VCPKG_LINE_INFO, code == 0, "tar failed while extracting %s", archive.u8string()); - } - else if (ext == ".zip") - { - const auto code = System::cmd_execute( - Strings::format(R"(cd '%s' && unzip -qqo '%s')", to_path_partial.u8string(), archive.u8string())); - Checks::check_exit(VCPKG_LINE_INFO, code == 0, "unzip failed while extracting %s", archive.u8string()); - } - else - { - Checks::exit_with_message(VCPKG_LINE_INFO, "Unexpected archive extension: %s", ext.u8string()); - } - - fs.rename(to_path_partial, to_path); - } - - static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data) - { - const auto& fs = paths.get_filesystem(); - const fs::path& scripts_folder = paths.scripts; - const std::array& version = tool_data.required_version; - - const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); - System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", - tool_name, - version_as_string, - tool_name, - version_as_string); -#if defined(_WIN32) - const fs::path script = scripts_folder / "fetchtool.ps1"; - const std::string title = Strings::format( - "Fetching %s version %s (No sufficient installed version was found)", tool_name, version_as_string); - const System::PowershellParameter tool_param("tool", tool_name); - const std::string output = System::powershell_execute_and_capture_output(title, script, {tool_param}); - - const std::vector tool_path = keep_data_lines(output); - Checks::check_exit(VCPKG_LINE_INFO, tool_path.size() == 1, "Expected tool path, but got %s", output); - - const fs::path actual_downloaded_path = Strings::trim(std::string{tool_path.at(0)}); - const fs::path& expected_downloaded_path = tool_data.exe_path; - std::error_code ec; - const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - eq && !ec, - "Expected tool downloaded path to be %s, but was %s", - expected_downloaded_path.u8string(), - actual_downloaded_path.u8string()); - return actual_downloaded_path; -#else - if (!fs.exists(tool_data.downloaded_path)) - { - auto code = System::cmd_execute(Strings::format( - R"(curl -L '%s' --create-dirs --output '%s')", tool_data.url, tool_data.downloaded_path)); - Checks::check_exit(VCPKG_LINE_INFO, code == 0, "curl failed while downloading %s", tool_data.url); - } - - System::println("Extracting %s...", tool_name); - extract_archive(paths, tool_data.downloaded_path, tool_data.tool_dir_path); - System::println("Extracting %s... done.", tool_name); - - Checks::check_exit(VCPKG_LINE_INFO, - fs.exists(tool_data.exe_path), - "Expected %s to exist after extracting", - tool_data.exe_path); - - return tool_data.exe_path; -#endif - } - - static fs::path get_cmake_path(const VcpkgPaths& paths) - { - std::vector candidate_paths; -#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__) - static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "cmake"); - candidate_paths.push_back(TOOL_DATA.exe_path); -#else - static const ToolData TOOL_DATA = ToolData{{3, 5, 1}, ""}; -#endif - static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - - const std::vector from_path = Files::find_from_PATH("cmake"); - candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - - const auto& program_files = System::get_program_files_platform_bitness(); - if (const auto pf = program_files.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe"); - const auto& program_files_32_bit = System::get_program_files_32_bit(); - if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe"); - - const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); - if (const auto p = path.get()) - { - return *p; - } - - return fetch_tool(paths, "cmake", TOOL_DATA); - } - - static fs::path get_7za_path(const VcpkgPaths& paths) - { -#if defined(_WIN32) - static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "7zip"); - if (!paths.get_filesystem().exists(TOOL_DATA.exe_path)) - { - return fetch_tool(paths, "7zip", TOOL_DATA); - } - return TOOL_DATA.exe_path; -#else - Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot download 7zip for non-Windows platforms."); -#endif - } - - static fs::path get_ninja_path(const VcpkgPaths& paths) - { - static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "ninja"); - - std::vector candidate_paths; - candidate_paths.push_back(TOOL_DATA.exe_path); - const std::vector from_path = Files::find_from_PATH("ninja"); - candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - - auto path = find_if_has_equal_or_greater_version(candidate_paths, "--version", TOOL_DATA.required_version); - if (const auto p = path.get()) - { - return *p; - } - - return fetch_tool(paths, "ninja", TOOL_DATA); - } - - static fs::path get_nuget_path(const VcpkgPaths& paths) - { - static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "nuget"); - - std::vector candidate_paths; - candidate_paths.push_back(TOOL_DATA.exe_path); - const std::vector from_path = Files::find_from_PATH("nuget"); - candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - - auto path = find_if_has_equal_or_greater_version(candidate_paths, "", TOOL_DATA.required_version); - if (const auto p = path.get()) - { - return *p; - } - - return fetch_tool(paths, "nuget", TOOL_DATA); - } - - static fs::path get_git_path(const VcpkgPaths& paths) - { -#if defined(_WIN32) - static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "git"); -#else - static const ToolData TOOL_DATA = ToolData{{2, 7, 4}, ""}; -#endif - static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - - std::vector candidate_paths; -#if defined(_WIN32) - candidate_paths.push_back(TOOL_DATA.exe_path); -#endif - const std::vector from_path = Files::find_from_PATH("git"); - candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - - const auto& program_files = System::get_program_files_platform_bitness(); - if (const auto pf = program_files.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe"); - const auto& program_files_32_bit = System::get_program_files_32_bit(); - if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe"); - - const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); - if (const auto p = path.get()) - { - return *p; - } - - return fetch_tool(paths, "git", TOOL_DATA); - } - - static fs::path get_ifw_installerbase_path(const VcpkgPaths& paths) - { - static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "installerbase"); - - static const std::string VERSION_CHECK_ARGUMENTS = "--framework-version"; - - std::vector candidate_paths; - candidate_paths.push_back(TOOL_DATA.exe_path); - // TODO: Uncomment later - // const std::vector from_path = Files::find_from_PATH("installerbase"); - // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - // candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" / - // "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe"); - // candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" / - // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); - - const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); - if (const auto p = path.get()) - { - return *p; - } - - return fetch_tool(paths, "installerbase", TOOL_DATA); - } - Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir, const std::string& default_vs_path) { std::error_code ec; @@ -471,266 +83,22 @@ namespace vcpkg bool VcpkgPaths::is_valid_triplet(const Triplet& t) const { - auto it = Util::find_if(this->get_available_triplets(), - [&](auto&& available_triplet) { return t.canonical_name() == available_triplet; }); + const auto it = Util::find_if(this->get_available_triplets(), [&](auto&& available_triplet) { + return t.canonical_name() == available_triplet; + }); return it != this->get_available_triplets().cend(); } - const fs::path& VcpkgPaths::get_7za_exe() const + const fs::path& VcpkgPaths::get_tool_exe(const std::string& tool) const { - return this->_7za_exe.get_lazy([this]() { return get_7za_path(*this); }); - } - - const fs::path& VcpkgPaths::get_cmake_exe() const - { - return this->cmake_exe.get_lazy([this]() { return get_cmake_path(*this); }); - } - - const fs::path& VcpkgPaths::get_git_exe() const - { - return this->git_exe.get_lazy([this]() { return get_git_path(*this); }); - } - - const fs::path& VcpkgPaths::get_ninja_exe() const - { - return this->ninja_exe.get_lazy([this]() { return get_ninja_path(*this); }); - } - - const fs::path& VcpkgPaths::get_nuget_exe() const - { - return this->nuget_exe.get_lazy([this]() { return get_nuget_path(*this); }); - } - - const fs::path& VcpkgPaths::get_ifw_installerbase_exe() const - { - return this->ifw_installerbase_exe.get_lazy([this]() { return get_ifw_installerbase_path(*this); }); - } - - const fs::path& VcpkgPaths::get_ifw_binarycreator_exe() const - { - return this->ifw_binarycreator_exe.get_lazy( - [this]() { return get_ifw_installerbase_exe().parent_path() / "binarycreator.exe"; }); - } - - const fs::path& VcpkgPaths::get_ifw_repogen_exe() const - { - return this->ifw_repogen_exe.get_lazy( - [this]() { return get_ifw_installerbase_exe().parent_path() / "repogen.exe"; }); - } - - struct VisualStudioInstance - { - fs::path root_path; - std::string version; - std::string release_type; - std::string preference_weight; // Mostly unused, just for verification that order is as intended - - std::string major_version() const { return version.substr(0, 2); } - }; - - static std::vector get_visual_studio_instances(const VcpkgPaths& paths) - { - const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; - const std::string output = - System::powershell_execute_and_capture_output("Detecting Visual Studio instances", script); - - const std::vector instances_as_strings = keep_data_lines(output); - Checks::check_exit(VCPKG_LINE_INFO, - !instances_as_strings.empty(), - "Could not detect any Visual Studio instances.\n" - "Powershell script:\n" - " %s\n" - "returned:\n" - "%s", - script.generic_string(), - output); - - std::vector instances; - for (const std::string& instance_as_string : instances_as_strings) - { - const std::vector split = Strings::split(instance_as_string, "::"); - Checks::check_exit(VCPKG_LINE_INFO, - split.size() == 4, - "Invalid Visual Studio instance format.\n" - "Expected: PreferenceWeight::ReleaseType::Version::PathToVisualStudio\n" - "Actual : %s\n", - instance_as_string); - instances.push_back({split.at(3), split.at(2), split.at(1), split.at(0)}); - } - - return instances; - } - - static std::vector find_toolset_instances(const VcpkgPaths& paths) - { - using CPU = System::CPUArchitecture; - - const auto& fs = paths.get_filesystem(); - - // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. - std::vector paths_examined; - - std::vector found_toolsets; - std::vector excluded_toolsets; - - const std::vector vs_instances = get_visual_studio_instances(paths); - const bool v140_is_available = Util::find_if(vs_instances, [&](const VisualStudioInstance& vs_instance) { - return vs_instance.major_version() == "14"; - }) != vs_instances.cend(); - - for (const VisualStudioInstance& vs_instance : vs_instances) - { - const std::string major_version = vs_instance.major_version(); - if (major_version == "15") - { - const fs::path vc_dir = vs_instance.root_path / "VC"; - - // Skip any instances that do not have vcvarsall. - const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build"; - const fs::path vcvarsall_bat = vcvarsall_dir / "vcvarsall.bat"; - paths_examined.push_back(vcvarsall_bat); - if (!fs.exists(vcvarsall_bat)) continue; - - // Get all supported architectures - std::vector supported_architectures; - if (fs.exists(vcvarsall_dir / "vcvars32.bat")) - supported_architectures.push_back({"x86", CPU::X86, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvars64.bat")) - supported_architectures.push_back({"amd64", CPU::X64, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) - supported_architectures.push_back({"x86_amd64", CPU::X86, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) - supported_architectures.push_back({"x86_arm", CPU::X86, CPU::ARM}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_arm64.bat")) - supported_architectures.push_back({"x86_arm64", CPU::X86, CPU::ARM64}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) - supported_architectures.push_back({"amd64_x86", CPU::X64, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) - supported_architectures.push_back({"amd64_arm", CPU::X64, CPU::ARM}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm64.bat")) - supported_architectures.push_back({"amd64_arm64", CPU::X64, CPU::ARM64}); - - // Locate the "best" MSVC toolchain version - const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; - std::vector msvc_subdirectories = fs.get_files_non_recursive(msvc_path); - Util::unstable_keep_if(msvc_subdirectories, - [&fs](const fs::path& path) { return fs.is_directory(path); }); - - // Sort them so that latest comes first - std::sort( - msvc_subdirectories.begin(), - msvc_subdirectories.end(), - [](const fs::path& left, const fs::path& right) { return left.filename() > right.filename(); }); - - for (const fs::path& subdir : msvc_subdirectories) - { - const fs::path dumpbin_path = subdir / "bin" / "HostX86" / "x86" / "dumpbin.exe"; - paths_examined.push_back(dumpbin_path); - if (fs.exists(dumpbin_path)) - { - const Toolset v141toolset = Toolset{ - vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}; - - auto english_language_pack = dumpbin_path.parent_path() / "1033"; - - if (!fs.exists(english_language_pack)) - { - excluded_toolsets.push_back(v141toolset); - break; - } - - found_toolsets.push_back(v141toolset); - - if (v140_is_available) - { - const Toolset v140toolset = Toolset{vs_instance.root_path, - dumpbin_path, - vcvarsall_bat, - {"-vcvars_ver=14.0"}, - V_140, - supported_architectures}; - found_toolsets.push_back(v140toolset); - } - - break; - } - } - - continue; - } - - if (major_version == "14" || major_version == "12") - { - const fs::path vcvarsall_bat = vs_instance.root_path / "VC" / "vcvarsall.bat"; - - paths_examined.push_back(vcvarsall_bat); - if (fs.exists(vcvarsall_bat)) - { - const fs::path vs_dumpbin_exe = vs_instance.root_path / "VC" / "bin" / "dumpbin.exe"; - paths_examined.push_back(vs_dumpbin_exe); - - const fs::path vs_bin_dir = vcvarsall_bat.parent_path() / "bin"; - std::vector supported_architectures; - if (fs.exists(vs_bin_dir / "vcvars32.bat")) - supported_architectures.push_back({"x86", CPU::X86, CPU::X86}); - if (fs.exists(vs_bin_dir / "amd64\\vcvars64.bat")) - supported_architectures.push_back({"x64", CPU::X64, CPU::X64}); - if (fs.exists(vs_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) - supported_architectures.push_back({"x86_amd64", CPU::X86, CPU::X64}); - if (fs.exists(vs_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) - supported_architectures.push_back({"x86_arm", CPU::X86, CPU::ARM}); - if (fs.exists(vs_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) - supported_architectures.push_back({"amd64_x86", CPU::X64, CPU::X86}); - if (fs.exists(vs_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) - supported_architectures.push_back({"amd64_arm", CPU::X64, CPU::ARM}); - - if (fs.exists(vs_dumpbin_exe)) - { - const Toolset toolset = {vs_instance.root_path, - vs_dumpbin_exe, - vcvarsall_bat, - {}, - major_version == "14" ? V_140 : V_120, - supported_architectures}; - - auto english_language_pack = vs_dumpbin_exe.parent_path() / "1033"; - - if (!fs.exists(english_language_pack)) - { - excluded_toolsets.push_back(toolset); - break; - } - - found_toolsets.push_back(toolset); - } - } - } - } - - if (!excluded_toolsets.empty()) - { - System::println( - System::Color::warning, - "Warning: The following VS instances are excluded because the English language pack is unavailable."); - for (const Toolset& toolset : excluded_toolsets) - { - System::println(" %s", toolset.visual_studio_root_path.u8string()); - } - System::println(System::Color::warning, "Please install the English language pack."); - } - - if (found_toolsets.empty()) + const auto it = this->tool_paths.find(tool); + if (it != this->tool_paths.cend()) { - System::println(System::Color::error, "Could not locate a complete toolset."); - System::println("The following paths were examined:"); - for (const fs::path& path : paths_examined) - { - System::println(" %s", path.u8string()); - } - Checks::exit_fail(VCPKG_LINE_INFO); + return it->second; } - return found_toolsets; + this->tool_paths[tool] = Commands::Fetch::get_tool_path(*this, tool); + return this->tool_paths[tool]; } const Toolset& VcpkgPaths::get_toolset(const Build::PreBuildInfo& prebuildinfo) const @@ -754,7 +122,7 @@ namespace vcpkg // Invariant: toolsets are non-empty and sorted with newest at back() const std::vector& vs_toolsets = - this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); + this->toolsets.get_lazy([this]() { return Commands::Fetch::find_toolset_instances(*this); }); std::vector candidates = Util::element_pointers(vs_toolsets); const auto tsv = prebuildinfo.platform_toolset.get(); -- cgit v1.2.3 From 23c2b82535d24a8ef343ce2ca36e5a63d111dcd8 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 4 Apr 2018 19:28:10 -0700 Subject: [vcpkgTools.xml] Add os="windows" to relevant entries --- toolsrc/src/vcpkg/commands.fetch.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 95c47e2db..cfb1b6c2a 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -78,16 +78,11 @@ namespace vcpkg::Commands::Fetch Strings::format(R"###(([\s\S]*?))###")}; static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###")}; - std::regex tool_regex{ + const std::regex tool_regex{ Strings::format(R"###(([\s\S]*?)<\/tool>)###", tool, OS_STRING)}; std::smatch match_tool; - bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); - if (!has_match_tool && OS_STRING == "windows") // Legacy support. Change introduced in vcpkg v0.0.107. - { - tool_regex = Strings::format(R"###(([\s\S]*?)<\/tool>)###", tool); - has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); - } + const bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); Checks::check_exit(VCPKG_LINE_INFO, has_match_tool, "Could not find entry for tool [%s] in %s", -- cgit v1.2.3 From 863a8f3329356d260c02c0d6f855e81fd1e2cea9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 4 Apr 2018 19:37:31 -0700 Subject: [vcpkgTools.xml] Rename archiveRelativePath to archiveName --- toolsrc/src/vcpkg/commands.fetch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index cfb1b6c2a..10153293c 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -75,7 +75,7 @@ namespace vcpkg::Commands::Fetch static const std::regex EXE_RELATIVE_PATH_REGEX{ Strings::format(R"###(([\s\S]*?))###")}; static const std::regex ARCHIVE_RELATIVE_PATH_REGEX{ - Strings::format(R"###(([\s\S]*?))###")}; + Strings::format(R"###(([\s\S]*?))###")}; static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###")}; const std::regex tool_regex{ -- cgit v1.2.3 From 32404eee694266a23a5d8a2c2f004d68c1d79195 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 4 Apr 2018 19:52:14 -0700 Subject: [vcpkgTools.xml] Verify the version field --- toolsrc/src/vcpkg/commands.fetch.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 10153293c..d2634a5f0 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -50,6 +50,7 @@ namespace vcpkg::Commands::Fetch static constexpr StringLiteral OS_STRING = "linux"; #endif + static const std::string XML_VERSION = "1"; static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; const auto maybe_get_string_inside_tags = [](const std::string& input, @@ -70,6 +71,7 @@ namespace vcpkg::Commands::Fetch return match[1]; }; + static const std::regex XML_VERSION_REGEX{R"###()###"}; static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO); static const std::regex VERSION_REGEX{R"###(([\s\S]*?))###"}; static const std::regex EXE_RELATIVE_PATH_REGEX{ @@ -78,6 +80,17 @@ namespace vcpkg::Commands::Fetch Strings::format(R"###(([\s\S]*?))###")}; static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###")}; + std::smatch match_xml_version; + const bool has_xml_version = std::regex_search(XML.cbegin(), XML.cend(), match_xml_version, XML_VERSION_REGEX); + Checks::check_exit( + VCPKG_LINE_INFO, has_xml_version, "Could not find in %s", XML_PATH.generic_string()); + Checks::check_exit(VCPKG_LINE_INFO, + XML_VERSION == match_xml_version[1], + "Expected %s version: [%s], but was [%s]. Please re-run bootstrap-vcpkg.", + XML_PATH.generic_string(), + XML_VERSION, + match_xml_version[1]); + const std::regex tool_regex{ Strings::format(R"###(([\s\S]*?)<\/tool>)###", tool, OS_STRING)}; -- cgit v1.2.3 From da9d1c46750bf78db65383e3a48d71905b8f91ef Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 4 Apr 2018 19:53:56 -0700 Subject: Misc archiveRelativePath->archiveName renames --- toolsrc/src/vcpkg/commands.fetch.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index d2634a5f0..90b408cc0 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -76,8 +76,7 @@ namespace vcpkg::Commands::Fetch static const std::regex VERSION_REGEX{R"###(([\s\S]*?))###"}; static const std::regex EXE_RELATIVE_PATH_REGEX{ Strings::format(R"###(([\s\S]*?))###")}; - static const std::regex ARCHIVE_RELATIVE_PATH_REGEX{ - Strings::format(R"###(([\s\S]*?))###")}; + static const std::regex ARCHIVE_NAME_REGEX{Strings::format(R"###(([\s\S]*?))###")}; static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###")}; std::smatch match_xml_version; @@ -112,7 +111,7 @@ namespace vcpkg::Commands::Fetch const std::string exe_relative_path = get_string_inside_tags(tool_data_as_string, EXE_RELATIVE_PATH_REGEX, "exeRelativePath"); - auto archive_relative_path = maybe_get_string_inside_tags(tool_data_as_string, ARCHIVE_RELATIVE_PATH_REGEX); + auto archive_name = maybe_get_string_inside_tags(tool_data_as_string, ARCHIVE_NAME_REGEX); const Optional> required_version = parse_version_string(required_version_as_string); Checks::check_exit(VCPKG_LINE_INFO, @@ -127,7 +126,7 @@ namespace vcpkg::Commands::Fetch return ToolData{*required_version.get(), exe_path, url, - paths.downloads / archive_relative_path.value_or(exe_relative_path), + paths.downloads / archive_name.value_or(exe_relative_path), tool_dir_path}; } -- cgit v1.2.3 From 408cd5ccb8d8260efd9a8f2ff956414587d42e28 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 4 Apr 2018 20:33:45 -0700 Subject: [vcpkgTools.xml] requiredVersion -> version --- toolsrc/src/vcpkg/commands.fetch.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 90b408cc0..a82f31724 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -15,7 +15,7 @@ namespace vcpkg::Commands::Fetch struct ToolData { - std::array required_version; + std::array version; fs::path exe_path; std::string url; fs::path downloaded_path; @@ -73,7 +73,7 @@ namespace vcpkg::Commands::Fetch static const std::regex XML_VERSION_REGEX{R"###()###"}; static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO); - static const std::regex VERSION_REGEX{R"###(([\s\S]*?))###"}; + static const std::regex VERSION_REGEX{R"###(([\s\S]*?))###"}; static const std::regex EXE_RELATIVE_PATH_REGEX{ Strings::format(R"###(([\s\S]*?))###")}; static const std::regex ARCHIVE_NAME_REGEX{Strings::format(R"###(([\s\S]*?))###")}; @@ -104,7 +104,7 @@ namespace vcpkg::Commands::Fetch const std::string tool_data_as_string = get_string_inside_tags(XML, tool_regex, tool); const std::string required_version_as_string = - get_string_inside_tags(tool_data_as_string, VERSION_REGEX, "requiredVersion"); + get_string_inside_tags(tool_data_as_string, VERSION_REGEX, "version"); const std::string url = get_string_inside_tags(tool_data_as_string, URL_REGEX, "url"); @@ -220,7 +220,7 @@ namespace vcpkg::Commands::Fetch { const auto& fs = paths.get_filesystem(); const fs::path& scripts_folder = paths.scripts; - const std::array& version = tool_data.required_version; + const std::array& version = tool_data.version; const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", @@ -289,7 +289,7 @@ namespace vcpkg::Commands::Fetch if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe"); const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version); if (const auto p = path.get()) { return *p; @@ -321,7 +321,7 @@ namespace vcpkg::Commands::Fetch const std::vector from_path = Files::find_from_PATH("ninja"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - auto path = find_if_has_equal_or_greater_version(candidate_paths, "--version", TOOL_DATA.required_version); + auto path = find_if_has_equal_or_greater_version(candidate_paths, "--version", TOOL_DATA.version); if (const auto p = path.get()) { return *p; @@ -339,7 +339,7 @@ namespace vcpkg::Commands::Fetch const std::vector from_path = Files::find_from_PATH("nuget"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - auto path = find_if_has_equal_or_greater_version(candidate_paths, "", TOOL_DATA.required_version); + auto path = find_if_has_equal_or_greater_version(candidate_paths, "", TOOL_DATA.version); if (const auto p = path.get()) { return *p; @@ -370,7 +370,7 @@ namespace vcpkg::Commands::Fetch if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe"); const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version); if (const auto p = path.get()) { return *p; @@ -396,7 +396,7 @@ namespace vcpkg::Commands::Fetch // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version); if (const auto p = path.get()) { return *p; -- cgit v1.2.3 From 540ab527894f96a57682dc4bca2a08548221b762 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 4 Apr 2018 20:47:58 -0700 Subject: Fix #ifdef'ed references to get_tool_exe() --- toolsrc/src/vcpkg/build.cpp | 2 +- toolsrc/src/vcpkg/commands.hash.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 86d171534..b7055100b 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -338,7 +338,7 @@ namespace vcpkg::Build #if !defined(_WIN32) // TODO: remove when vcpkg.exe is in charge for acquiring tools. Change introduced in vcpkg v0.0.107. // bootstrap should have already downloaded ninja, but making sure it is present in case it was deleted. - vcpkg::Util::unused(paths.get_ninja_exe()); + vcpkg::Util::unused(paths.get_tool_exe(Tools::NINJA)); #endif const fs::path& cmake_exe_path = paths.get_tool_exe(Tools::CMAKE); diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 9e1b54390..517970b2c 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -112,7 +112,7 @@ namespace vcpkg::Commands::Hash { const std::string cmd_line = Strings::format( R"("%s" -E %ssum "%s")", - paths.get_cmake_exe().u8string(), + paths.get_tool_exe(Tools::CMAKE).u8string(), Strings::ascii_to_lowercase(hash_type), path.u8string()); -- cgit v1.2.3 From 0108d6ea2808adea5fe7ce97f6871b59a0fadb1d Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 4 Apr 2018 21:47:50 -0700 Subject: Disable vcpkg fetch for now --- toolsrc/src/vcpkg/commands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index e98ff711a..c6b700aae 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -43,7 +43,7 @@ namespace vcpkg::Commands {"portsdiff", &PortsDiff::perform_and_exit}, {"autocomplete", &Autocomplete::perform_and_exit}, {"hash", &Hash::perform_and_exit}, - {"fetch", &Fetch::perform_and_exit}, + // {"fetch", &Fetch::perform_and_exit}, }; return t; } -- cgit v1.2.3 From b217246f70fd6ac8f8d093b4457ae9035a2dd954 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 4 Apr 2018 22:01:08 -0700 Subject: [vcpkg.exe] Hash check after downloading a tool --- toolsrc/src/vcpkg/commands.fetch.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index a82f31724..33fa74c62 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -20,6 +20,7 @@ namespace vcpkg::Commands::Fetch std::string url; fs::path downloaded_path; fs::path tool_dir_path; + std::string sha512; }; static Optional> parse_version_string(const std::string& version_as_string) @@ -78,6 +79,7 @@ namespace vcpkg::Commands::Fetch Strings::format(R"###(([\s\S]*?))###")}; static const std::regex ARCHIVE_NAME_REGEX{Strings::format(R"###(([\s\S]*?))###")}; static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###")}; + static const std::regex SHA512_REGEX{Strings::format(R"###(([\s\S]*?))###")}; std::smatch match_xml_version; const bool has_xml_version = std::regex_search(XML.cbegin(), XML.cend(), match_xml_version, XML_VERSION_REGEX); @@ -123,11 +125,15 @@ namespace vcpkg::Commands::Fetch const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, required_version_as_string, OS_STRING); const fs::path tool_dir_path = paths.downloads / "tools" / tool_dir_name; const fs::path exe_path = tool_dir_path / exe_relative_path; + + const std::string sha512 = get_string_inside_tags(tool_data_as_string, SHA512_REGEX, "sha512"); + return ToolData{*required_version.get(), exe_path, url, paths.downloads / archive_name.value_or(exe_relative_path), - tool_dir_path}; + tool_dir_path, + sha512}; } static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, @@ -256,6 +262,17 @@ namespace vcpkg::Commands::Fetch Checks::check_exit(VCPKG_LINE_INFO, code == 0, "curl failed while downloading %s", tool_data.url); } + const std::string actual_hash = Hash::get_file_hash(paths, tool_data.downloaded_path, "SHA512"); + Checks::check_exit(VCPKG_LINE_INFO, + tool_data.sha512 == actual_hash, + "File does not have the expected hash:\n" + " File path : [ %s ]\n" + " Expected hash: [ %s ]\n" + " Actual hash: [ %s ] \n", + tool_data.downloaded_path.u8string(), + tool_data.sha512, + actual_hash); + System::println("Extracting %s...", tool_name); extract_archive(paths, tool_data.downloaded_path, tool_data.tool_dir_path); System::println("Extracting %s... done.", tool_name); -- cgit v1.2.3 From 7cfc53a45e53476ff93406644c82c4f15563f67b Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Apr 2018 03:37:04 -0700 Subject: [vcpkg.exe] Move downloaded file in place after hash check --- toolsrc/src/vcpkg/commands.fetch.cpp | 59 +++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 18 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 33fa74c62..e369f44d2 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -18,7 +18,7 @@ namespace vcpkg::Commands::Fetch std::array version; fs::path exe_path; std::string url; - fs::path downloaded_path; + fs::path download_path; fs::path tool_dir_path; std::string sha512; }; @@ -219,7 +219,41 @@ namespace vcpkg::Commands::Fetch Checks::exit_with_message(VCPKG_LINE_INFO, "Unexpected archive extension: %s", ext.u8string()); } - fs.rename(to_path_partial, to_path); + fs.rename(to_path_partial, to_path, ec); + } + + static void download_file(const VcpkgPaths& paths, + const std::string& url, + const fs::path& download_path, + const std::string& sha512) + { + Files::Filesystem& fs = paths.get_filesystem(); + if (fs.exists(download_path)) + { + return; + } + + const std::string download_path_part = download_path.u8string() + ".part"; + std::error_code ec; + fs.remove(download_path_part, ec); + const auto code = System::cmd_execute(Strings::format( + R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part)); + Checks::check_exit(VCPKG_LINE_INFO, code == 0, "Could not download %s", url); + + const std::string actual_hash = Hash::get_file_hash(paths, download_path_part, "SHA512"); + Checks::check_exit(VCPKG_LINE_INFO, + sha512 == actual_hash, + "File does not have the expected hash:\n" + " url : [ %s ]\n" + " File path : [ %s ]\n" + " Expected hash: [ %s ]\n" + " Actual hash: [ %s ] \n", + url, + download_path.u8string(), + sha512, + actual_hash); + + fs.rename(download_path_part, download_path, ec); } static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data) @@ -255,26 +289,15 @@ namespace vcpkg::Commands::Fetch actual_downloaded_path.u8string()); return actual_downloaded_path; #else - if (!fs.exists(tool_data.downloaded_path)) + if (!fs.exists(tool_data.download_path)) { - auto code = System::cmd_execute(Strings::format( - R"(curl -L '%s' --create-dirs --output '%s')", tool_data.url, tool_data.downloaded_path)); - Checks::check_exit(VCPKG_LINE_INFO, code == 0, "curl failed while downloading %s", tool_data.url); + System::println("Downloading %s...", tool_name); + download_file(paths, tool_data.url, tool_data.download_path, tool_data.sha512); + System::println("Downloading %s... done.", tool_name); } - const std::string actual_hash = Hash::get_file_hash(paths, tool_data.downloaded_path, "SHA512"); - Checks::check_exit(VCPKG_LINE_INFO, - tool_data.sha512 == actual_hash, - "File does not have the expected hash:\n" - " File path : [ %s ]\n" - " Expected hash: [ %s ]\n" - " Actual hash: [ %s ] \n", - tool_data.downloaded_path.u8string(), - tool_data.sha512, - actual_hash); - System::println("Extracting %s...", tool_name); - extract_archive(paths, tool_data.downloaded_path, tool_data.tool_dir_path); + extract_archive(paths, tool_data.download_path, tool_data.tool_dir_path); System::println("Extracting %s... done.", tool_name); Checks::check_exit(VCPKG_LINE_INFO, -- cgit v1.2.3 From 870fa61e0132028f43c292b7fd7a7d7c6525a8d7 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Apr 2018 04:29:43 -0700 Subject: [vcpkg hash] Don't use cmake for non-windows hashes. Use shasum instead --- toolsrc/src/vcpkg/build.cpp | 8 +++---- toolsrc/src/vcpkg/commands.cpp | 8 ++++--- toolsrc/src/vcpkg/commands.fetch.cpp | 2 +- toolsrc/src/vcpkg/commands.hash.cpp | 43 ++++++++++++++++-------------------- 4 files changed, 29 insertions(+), 32 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index b7055100b..16a85db52 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -457,9 +457,9 @@ namespace vcpkg::Build abi_tag_entries.insert(abi_tag_entries.end(), dependency_abis.begin(), dependency_abis.end()); abi_tag_entries.emplace_back( - AbiEntry{"portfile", Commands::Hash::get_file_hash(paths, config.port_dir / "portfile.cmake", "SHA1")}); + AbiEntry{"portfile", Commands::Hash::get_file_hash(config.port_dir / "portfile.cmake", "SHA1")}); abi_tag_entries.emplace_back( - AbiEntry{"control", Commands::Hash::get_file_hash(paths, config.port_dir / "CONTROL", "SHA1")}); + AbiEntry{"control", Commands::Hash::get_file_hash(config.port_dir / "CONTROL", "SHA1")}); abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag}); @@ -494,7 +494,7 @@ namespace vcpkg::Build auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt"); fs.write_contents(abi_file_path, full_abi_info); - return AbiTagAndFile{Commands::Hash::get_file_hash(paths, abi_file_path, "SHA1"), abi_file_path}; + return AbiTagAndFile{Commands::Hash::get_file_hash(abi_file_path, "SHA1"), abi_file_path}; } else { @@ -784,7 +784,7 @@ namespace vcpkg::Build { return it_hash->second; } - auto hash = Commands::Hash::get_file_hash(paths, triplet_file_path, "SHA1"); + auto hash = Commands::Hash::get_file_hash(triplet_file_path, "SHA1"); s_hash_cache.emplace(triplet_file_path, hash); return hash; } diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index c6b700aae..9041b37ff 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -42,7 +42,6 @@ namespace vcpkg::Commands {"cache", &Cache::perform_and_exit}, {"portsdiff", &PortsDiff::perform_and_exit}, {"autocomplete", &Autocomplete::perform_and_exit}, - {"hash", &Hash::perform_and_exit}, // {"fetch", &Fetch::perform_and_exit}, }; return t; @@ -50,8 +49,11 @@ namespace vcpkg::Commands Span> get_available_commands_type_c() { - static std::vector> t = {{"version", &Version::perform_and_exit}, - {"contact", &Contact::perform_and_exit}}; + static std::vector> t = { + {"version", &Version::perform_and_exit}, + {"contact", &Contact::perform_and_exit}, + {"hash", &Hash::perform_and_exit}, + }; return t; } } diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index e369f44d2..1ba043728 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -240,7 +240,7 @@ namespace vcpkg::Commands::Fetch R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part)); Checks::check_exit(VCPKG_LINE_INFO, code == 0, "Could not download %s", url); - const std::string actual_hash = Hash::get_file_hash(paths, download_path_part, "SHA512"); + const std::string actual_hash = Hash::get_file_hash(download_path_part, "SHA512"); Checks::check_exit(VCPKG_LINE_INFO, sha512 == actual_hash, "File does not have the expected hash:\n" diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 517970b2c..087f3e682 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -60,7 +60,7 @@ namespace vcpkg::Commands::Hash }; } - std::string get_file_hash(const VcpkgPaths&, const fs::path& path, const std::string& hash_type) + std::string get_file_hash(const fs::path& path, const std::string& hash_type) { BCryptAlgorithmHandle algorithm_handle; @@ -108,30 +108,25 @@ namespace vcpkg::Commands::Hash #else namespace vcpkg::Commands::Hash { - std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type) + std::string get_file_hash(const fs::path& path, const std::string& hash_type) { - const std::string cmd_line = Strings::format( - R"("%s" -E %ssum "%s")", - paths.get_tool_exe(Tools::CMAKE).u8string(), - Strings::ascii_to_lowercase(hash_type), - path.u8string()); - - const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line); - - std::string const& output = ec_data.output; - - const auto start = output.find_first_of(' '); - Checks::check_exit( - VCPKG_LINE_INFO, start != std::string::npos, "Unexpected output format from command: %s", cmd_line); + if (!Strings::case_insensitive_ascii_starts_with(hash_type, "SHA")) + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "shasum only supports SHA hashes, but %s was provided", hash_type); + } - const auto end = output.find_first_of("\r\n", start + 1); - Checks::check_exit( - VCPKG_LINE_INFO, end != std::string::npos, "Unexpected output format from command: %s", cmd_line); + const std::string digest_size = hash_type.substr(3, hash_type.length() - 3); - auto hash = output.substr(0, start); - Util::erase_remove_if(hash, isspace); - return hash; + const std::string cmd_line = Strings::format( + R"(shasum -a %s "%s" | awk '{ print $1 }')", digest_size, path.u8string()); + const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, + ec_data.exit_code == 0, + "Failed to run:\n" + " %s", + cmd_line); + return Strings::trim(std::string{ec_data.output}); } } #endif @@ -147,13 +142,13 @@ namespace vcpkg::Commands::Hash nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + void perform_and_exit(const VcpkgCmdArguments& args) { Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); const fs::path file_to_hash = args.command_arguments[0]; const std::string algorithm = args.command_arguments.size() == 2 ? args.command_arguments[1] : "SHA512"; - const std::string hash = get_file_hash(paths, file_to_hash, algorithm); + const std::string hash = get_file_hash(file_to_hash, algorithm); System::println(hash); Checks::exit_success(VCPKG_LINE_INFO); } -- cgit v1.2.3 From e71230855443a0b87c38e011531cfc6b9d6ffce5 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Apr 2018 16:41:52 -0700 Subject: [vcpkg hash] Add string hashing (as opposed to file hashing) --- toolsrc/src/vcpkg/commands.hash.cpp | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 087f3e682..856b0e283 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -103,6 +103,42 @@ namespace vcpkg::Commands::Hash return to_hex(hash_buffer.get(), length_in_bytes); } + + std::string get_string_hash(const std::string& s, const std::string& hash_type) + { + BCryptAlgorithmHandle algorithm_handle; + + NTSTATUS error_code = BCryptOpenAlgorithmProvider( + &algorithm_handle.handle, Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(), nullptr, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider"); + + DWORD hash_buffer_bytes; + DWORD cb_data; + error_code = BCryptGetProperty(algorithm_handle.handle, + BCRYPT_HASH_LENGTH, + reinterpret_cast(&hash_buffer_bytes), + sizeof(DWORD), + &cb_data, + 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length"); + const ULONG length_in_bytes = hash_buffer_bytes; + + BCryptHashHandle hash_handle; + + error_code = BCryptCreateHash(algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher"); + + auto* const buffer = reinterpret_cast(const_cast(s.c_str())); + error_code = BCryptHashData(hash_handle.handle, buffer, static_cast(s.size()), 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data"); + + std::unique_ptr hash_buffer = std::make_unique(length_in_bytes); + + error_code = BCryptFinishHash(hash_handle.handle, hash_buffer.get(), length_in_bytes, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash"); + + return to_hex(hash_buffer.get(), length_in_bytes); + } } #else @@ -128,6 +164,27 @@ namespace vcpkg::Commands::Hash cmd_line); return Strings::trim(std::string{ec_data.output}); } + + std::string get_string_hash(const std::string& s, const std::string& hash_type) + { + if (!Strings::case_insensitive_ascii_starts_with(hash_type, "SHA")) + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "shasum only supports SHA hashes, but %s was provided", hash_type); + } + + const std::string digest_size = hash_type.substr(3, hash_type.length() - 3); + + const std::string cmd_line = Strings::format( + R"(echo -n "%s" | shasum -a %s | awk '{ print $1 }')", s, digest_size); + const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, + ec_data.exit_code == 0, + "Failed to run:\n" + " %s", + cmd_line); + return Strings::trim(std::string{ec_data.output}); + } } #endif -- cgit v1.2.3 From c1257f988a49b167cd9d94a0931806c6e465700a Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Apr 2018 17:03:45 -0700 Subject: [vcpkg hash] Refactor to reduce code duplication --- toolsrc/src/vcpkg/commands.hash.cpp | 149 +++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 71 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 856b0e283..c0130f12f 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -18,7 +18,7 @@ namespace vcpkg::Commands::Hash { namespace { - static std::string to_hex(const unsigned char* string, const size_t bytes) + std::string to_hex(const unsigned char* string, const size_t bytes) { static constexpr char HEX_MAP[] = "0123456789abcdef"; @@ -58,86 +58,93 @@ namespace vcpkg::Commands::Hash if (handle) BCryptDestroyHash(handle); } }; - } - std::string get_file_hash(const fs::path& path, const std::string& hash_type) - { - BCryptAlgorithmHandle algorithm_handle; - - NTSTATUS error_code = BCryptOpenAlgorithmProvider( - &algorithm_handle.handle, Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(), nullptr, 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider"); - - DWORD hash_buffer_bytes; - DWORD cb_data; - error_code = BCryptGetProperty(algorithm_handle.handle, - BCRYPT_HASH_LENGTH, - reinterpret_cast(&hash_buffer_bytes), - sizeof(DWORD), - &cb_data, - 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length"); - const ULONG length_in_bytes = hash_buffer_bytes; - - BCryptHashHandle hash_handle; - - error_code = BCryptCreateHash(algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher"); - - FILE* file = nullptr; - const auto ec = _wfopen_s(&file, path.c_str(), L"rb"); - Checks::check_exit(VCPKG_LINE_INFO, ec == 0, "Failed to open file: %s", path.u8string()); - unsigned char buffer[4096]; - while (const auto actual_size = fread(buffer, 1, sizeof(buffer), file)) + struct BCryptHasher { - error_code = BCryptHashData(hash_handle.handle, buffer, static_cast(actual_size), 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data"); - } - - fclose(file); - - std::unique_ptr hash_buffer = std::make_unique(length_in_bytes); - - error_code = BCryptFinishHash(hash_handle.handle, hash_buffer.get(), length_in_bytes, 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash"); - - return to_hex(hash_buffer.get(), length_in_bytes); - } - - std::string get_string_hash(const std::string& s, const std::string& hash_type) - { - BCryptAlgorithmHandle algorithm_handle; + explicit BCryptHasher(const std::string& hash_type) + { + NTSTATUS error_code = + BCryptOpenAlgorithmProvider(&this->algorithm_handle.handle, + Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(), + nullptr, + 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider"); + + DWORD hash_buffer_bytes; + DWORD cb_data; + error_code = BCryptGetProperty(this->algorithm_handle.handle, + BCRYPT_HASH_LENGTH, + reinterpret_cast(&hash_buffer_bytes), + sizeof(DWORD), + &cb_data, + 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length"); + this->length_in_bytes = hash_buffer_bytes; + } - NTSTATUS error_code = BCryptOpenAlgorithmProvider( - &algorithm_handle.handle, Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(), nullptr, 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider"); + std::string hash_file(const fs::path& path) const + { + BCryptHashHandle hash_handle; + this->initialize_hash_handle(hash_handle); + + FILE* file = nullptr; + const auto ec = _wfopen_s(&file, path.c_str(), L"rb"); + Checks::check_exit(VCPKG_LINE_INFO, ec == 0, "Failed to open file: %s", path.u8string()); + unsigned char buffer[4096]; + while (const auto actual_size = fread(buffer, 1, sizeof(buffer), file)) + { + hash_data(hash_handle, buffer, actual_size); + } + fclose(file); + + return this->finalize_hash_handle(hash_handle); + } - DWORD hash_buffer_bytes; - DWORD cb_data; - error_code = BCryptGetProperty(algorithm_handle.handle, - BCRYPT_HASH_LENGTH, - reinterpret_cast(&hash_buffer_bytes), - sizeof(DWORD), - &cb_data, - 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length"); - const ULONG length_in_bytes = hash_buffer_bytes; + std::string hash_string(const std::string& s) const + { + BCryptHashHandle hash_handle; + this->initialize_hash_handle(hash_handle); + hash_data(hash_handle, reinterpret_cast(const_cast(s.c_str())), s.size()); + return this->finalize_hash_handle(hash_handle); + } - BCryptHashHandle hash_handle; + private: + void initialize_hash_handle(BCryptHashHandle& hash_handle) const + { + const NTSTATUS error_code = + BCryptCreateHash(this->algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher"); + } - error_code = BCryptCreateHash(algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher"); + void hash_data(BCryptHashHandle& hash_handle, unsigned char* buffer, const size_t& data_size) const + { + const NTSTATUS error_code = + BCryptHashData(hash_handle.handle, buffer, static_cast(data_size), 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data"); + } - auto* const buffer = reinterpret_cast(const_cast(s.c_str())); - error_code = BCryptHashData(hash_handle.handle, buffer, static_cast(s.size()), 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data"); + std::string finalize_hash_handle(const BCryptHashHandle& hash_handle) const + { + std::unique_ptr hash_buffer = std::make_unique(this->length_in_bytes); + const NTSTATUS error_code = + BCryptFinishHash(hash_handle.handle, hash_buffer.get(), this->length_in_bytes, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash"); + return to_hex(hash_buffer.get(), this->length_in_bytes); + } - std::unique_ptr hash_buffer = std::make_unique(length_in_bytes); + BCryptAlgorithmHandle algorithm_handle; + ULONG length_in_bytes; + }; + } - error_code = BCryptFinishHash(hash_handle.handle, hash_buffer.get(), length_in_bytes, 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash"); + std::string get_file_hash(const fs::path& path, const std::string& hash_type) + { + return BCryptHasher{hash_type}.hash_file(path); + } - return to_hex(hash_buffer.get(), length_in_bytes); + std::string get_string_hash(const std::string& s, const std::string& hash_type) + { + return BCryptHasher{hash_type}.hash_string(s); } } -- cgit v1.2.3 From 3f6f9f3f4d48ef0115f3095f7d8d2c6d3b0c63e1 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Apr 2018 17:12:59 -0700 Subject: [metrics] Use new string-hash functions instead of ps1 script --- toolsrc/src/vcpkg/metrics.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 9e17b237d..4067efc95 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -264,17 +264,10 @@ namespace vcpkg::Metrics while (next != last) { - auto match = *next; + const auto match = *next; if (match[0] != "00-00-00-00-00-00") { - const std::string matchstr = match[0]; - const System::PowershellParameter value("Value", matchstr); - auto hash_result = System::powershell_execute_and_capture_output( - "SHA256Hash", get_vcpkg_root() / "scripts" / "SHA256Hash.ps1", {value}); - Util::erase_remove_if(hash_result, - [](char ch) { return !(ch >= 'A' && ch <= 'F') && !(ch >= '0' && ch <= '9'); }); - hash_result = Strings::ascii_to_lowercase(hash_result); - return hash_result; + return vcpkg::Commands::Hash::get_string_hash(match[0], "SHA256"); } ++next; } -- cgit v1.2.3 From ca9503b9d7f9bca6e2f9881a7f4ec9ce9d600928 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Apr 2018 21:28:02 -0700 Subject: [vcpkg hash] Refactor and tweaks in BCryptHasher. --- toolsrc/src/vcpkg/commands.hash.cpp | 83 +++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 41 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index c0130f12f..19f73b463 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -39,28 +39,52 @@ namespace vcpkg::Commands::Hash return output; } - struct BCryptAlgorithmHandle : Util::ResourceBase + class BCryptHasher { - BCRYPT_ALG_HANDLE handle = nullptr; + struct BCryptAlgorithmHandle : Util::ResourceBase + { + BCRYPT_ALG_HANDLE handle = nullptr; + + ~BCryptAlgorithmHandle() + { + if (handle) BCryptCloseAlgorithmProvider(handle, 0); + } + }; + + struct BCryptHashHandle : Util::ResourceBase + { + BCRYPT_HASH_HANDLE handle = nullptr; + + ~BCryptHashHandle() + { + if (handle) BCryptDestroyHash(handle); + } + }; - ~BCryptAlgorithmHandle() + static void initialize_hash_handle(BCryptHashHandle& hash_handle, + const BCryptAlgorithmHandle& algorithm_handle) { - if (handle) BCryptCloseAlgorithmProvider(handle, 0); + const NTSTATUS error_code = + BCryptCreateHash(algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher"); } - }; - struct BCryptHashHandle : Util::ResourceBase - { - BCRYPT_HASH_HANDLE handle = nullptr; + static void hash_data(BCryptHashHandle& hash_handle, const unsigned char* buffer, const size_t& data_size) + { + const NTSTATUS error_code = BCryptHashData( + hash_handle.handle, const_cast(buffer), static_cast(data_size), 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data"); + } - ~BCryptHashHandle() + static std::string finalize_hash_handle(const BCryptHashHandle& hash_handle, const ULONG length_in_bytes) { - if (handle) BCryptDestroyHash(handle); + std::unique_ptr hash_buffer = std::make_unique(length_in_bytes); + const NTSTATUS error_code = BCryptFinishHash(hash_handle.handle, hash_buffer.get(), length_in_bytes, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash"); + return to_hex(hash_buffer.get(), length_in_bytes); } - }; - struct BCryptHasher - { + public: explicit BCryptHasher(const std::string& hash_type) { NTSTATUS error_code = @@ -85,7 +109,7 @@ namespace vcpkg::Commands::Hash std::string hash_file(const fs::path& path) const { BCryptHashHandle hash_handle; - this->initialize_hash_handle(hash_handle); + initialize_hash_handle(hash_handle, this->algorithm_handle); FILE* file = nullptr; const auto ec = _wfopen_s(&file, path.c_str(), L"rb"); @@ -97,41 +121,18 @@ namespace vcpkg::Commands::Hash } fclose(file); - return this->finalize_hash_handle(hash_handle); + return finalize_hash_handle(hash_handle, length_in_bytes); } std::string hash_string(const std::string& s) const { BCryptHashHandle hash_handle; - this->initialize_hash_handle(hash_handle); - hash_data(hash_handle, reinterpret_cast(const_cast(s.c_str())), s.size()); - return this->finalize_hash_handle(hash_handle); + initialize_hash_handle(hash_handle, this->algorithm_handle); + hash_data(hash_handle, reinterpret_cast(s.c_str()), s.size()); + return finalize_hash_handle(hash_handle, length_in_bytes); } private: - void initialize_hash_handle(BCryptHashHandle& hash_handle) const - { - const NTSTATUS error_code = - BCryptCreateHash(this->algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher"); - } - - void hash_data(BCryptHashHandle& hash_handle, unsigned char* buffer, const size_t& data_size) const - { - const NTSTATUS error_code = - BCryptHashData(hash_handle.handle, buffer, static_cast(data_size), 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data"); - } - - std::string finalize_hash_handle(const BCryptHashHandle& hash_handle) const - { - std::unique_ptr hash_buffer = std::make_unique(this->length_in_bytes); - const NTSTATUS error_code = - BCryptFinishHash(hash_handle.handle, hash_buffer.get(), this->length_in_bytes, 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash"); - return to_hex(hash_buffer.get(), this->length_in_bytes); - } - BCryptAlgorithmHandle algorithm_handle; ULONG length_in_bytes; }; -- cgit v1.2.3 From ec790eb1716fca367dccc2b5f7e96a8719ca74fa Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Apr 2018 22:01:11 -0700 Subject: [vcpkg hash] Refactor to reduce repetition. Allow simple chars in get_string_hash() for now. --- toolsrc/src/vcpkg/commands.hash.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 19f73b463..a3ac2cbbb 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -152,7 +152,7 @@ namespace vcpkg::Commands::Hash #else namespace vcpkg::Commands::Hash { - std::string get_file_hash(const fs::path& path, const std::string& hash_type) + static std::string get_digest_size(const std::string& hash_type) { if (!Strings::case_insensitive_ascii_starts_with(hash_type, "SHA")) { @@ -160,10 +160,11 @@ namespace vcpkg::Commands::Hash VCPKG_LINE_INFO, "shasum only supports SHA hashes, but %s was provided", hash_type); } - const std::string digest_size = hash_type.substr(3, hash_type.length() - 3); + return hash_type.substr(3, hash_type.length() - 3); + } - const std::string cmd_line = Strings::format( - R"(shasum -a %s "%s" | awk '{ print $1 }')", digest_size, path.u8string()); + static std::string run_shasum_and_post_process(const std::string& cmd_line) + { const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, @@ -173,25 +174,27 @@ namespace vcpkg::Commands::Hash return Strings::trim(std::string{ec_data.output}); } + std::string get_file_hash(const fs::path& path, const std::string& hash_type) + { + const std::string digest_size = get_digest_size(hash_type); + const std::string cmd_line = Strings::format( + R"(shasum -a %s "%s" | awk '{ print $1 }')", digest_size, path.u8string()); + return run_shasum_and_post_process(cmd_line); + } + std::string get_string_hash(const std::string& s, const std::string& hash_type) { - if (!Strings::case_insensitive_ascii_starts_with(hash_type, "SHA")) - { - Checks::exit_with_message( - VCPKG_LINE_INFO, "shasum only supports SHA hashes, but %s was provided", hash_type); - } + const std::string digest_size = get_digest_size(hash_type); - const std::string digest_size = hash_type.substr(3, hash_type.length() - 3); + static const std::regex ALLOWED_CHARS{"^[a-zA-Z0-9:]*$"}; + + Checks::check_exit(VCPKG_LINE_INFO, + std::regex_match(s, ALLOWED_CHARS), + "Only alphanumeric chars and colons are currently allowed"); const std::string cmd_line = Strings::format( R"(echo -n "%s" | shasum -a %s | awk '{ print $1 }')", s, digest_size); - const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); - Checks::check_exit(VCPKG_LINE_INFO, - ec_data.exit_code == 0, - "Failed to run:\n" - " %s", - cmd_line); - return Strings::trim(std::string{ec_data.output}); + return run_shasum_and_post_process(cmd_line); } } #endif -- cgit v1.2.3 From 1bfb01cfeeffc8c8161f64b1bd2986557b6ba207 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 5 Apr 2018 22:05:55 -0700 Subject: [vcpkg hash] Add sanity checking --- toolsrc/src/vcpkg/build.cpp | 8 ++++---- toolsrc/src/vcpkg/commands.cpp | 2 +- toolsrc/src/vcpkg/commands.fetch.cpp | 2 +- toolsrc/src/vcpkg/commands.hash.cpp | 33 +++++++++++++++++++++++---------- 4 files changed, 29 insertions(+), 16 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 16a85db52..b7055100b 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -457,9 +457,9 @@ namespace vcpkg::Build abi_tag_entries.insert(abi_tag_entries.end(), dependency_abis.begin(), dependency_abis.end()); abi_tag_entries.emplace_back( - AbiEntry{"portfile", Commands::Hash::get_file_hash(config.port_dir / "portfile.cmake", "SHA1")}); + AbiEntry{"portfile", Commands::Hash::get_file_hash(paths, config.port_dir / "portfile.cmake", "SHA1")}); abi_tag_entries.emplace_back( - AbiEntry{"control", Commands::Hash::get_file_hash(config.port_dir / "CONTROL", "SHA1")}); + AbiEntry{"control", Commands::Hash::get_file_hash(paths, config.port_dir / "CONTROL", "SHA1")}); abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag}); @@ -494,7 +494,7 @@ namespace vcpkg::Build auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt"); fs.write_contents(abi_file_path, full_abi_info); - return AbiTagAndFile{Commands::Hash::get_file_hash(abi_file_path, "SHA1"), abi_file_path}; + return AbiTagAndFile{Commands::Hash::get_file_hash(paths, abi_file_path, "SHA1"), abi_file_path}; } else { @@ -784,7 +784,7 @@ namespace vcpkg::Build { return it_hash->second; } - auto hash = Commands::Hash::get_file_hash(triplet_file_path, "SHA1"); + auto hash = Commands::Hash::get_file_hash(paths, triplet_file_path, "SHA1"); s_hash_cache.emplace(triplet_file_path, hash); return hash; } diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index 9041b37ff..8b6ffb3d7 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -42,6 +42,7 @@ namespace vcpkg::Commands {"cache", &Cache::perform_and_exit}, {"portsdiff", &PortsDiff::perform_and_exit}, {"autocomplete", &Autocomplete::perform_and_exit}, + {"hash", &Hash::perform_and_exit}, // {"fetch", &Fetch::perform_and_exit}, }; return t; @@ -52,7 +53,6 @@ namespace vcpkg::Commands static std::vector> t = { {"version", &Version::perform_and_exit}, {"contact", &Contact::perform_and_exit}, - {"hash", &Hash::perform_and_exit}, }; return t; } diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 1ba043728..e369f44d2 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -240,7 +240,7 @@ namespace vcpkg::Commands::Fetch R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part)); Checks::check_exit(VCPKG_LINE_INFO, code == 0, "Could not download %s", url); - const std::string actual_hash = Hash::get_file_hash(download_path_part, "SHA512"); + const std::string actual_hash = Hash::get_file_hash(paths, download_path_part, "SHA512"); Checks::check_exit(VCPKG_LINE_INFO, sha512 == actual_hash, "File does not have the expected hash:\n" diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index a3ac2cbbb..3f90eeaca 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -7,6 +7,19 @@ #include #include +namespace vcpkg::Commands::Hash +{ + static void verify_has_only_allowed_chars(const std::string& s) + { + static const std::regex ALLOWED_CHARS{"^[a-zA-Z0-9-]*$"}; + Checks::check_exit(VCPKG_LINE_INFO, + std::regex_match(s, ALLOWED_CHARS), + "Only alphanumeric chars and dashes are currently allowed. String was:\n" + " % s", + s); + } +} + #if defined(_WIN32) #include @@ -138,13 +151,16 @@ namespace vcpkg::Commands::Hash }; } - std::string get_file_hash(const fs::path& path, const std::string& hash_type) + std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type) { + Checks::check_exit( + VCPKG_LINE_INFO, paths.get_filesystem().exists(path), "File %s does not exist", path.u8string()); return BCryptHasher{hash_type}.hash_file(path); } std::string get_string_hash(const std::string& s, const std::string& hash_type) { + verify_has_only_allowed_chars(s); return BCryptHasher{hash_type}.hash_string(s); } } @@ -174,9 +190,11 @@ namespace vcpkg::Commands::Hash return Strings::trim(std::string{ec_data.output}); } - std::string get_file_hash(const fs::path& path, const std::string& hash_type) + std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type) { const std::string digest_size = get_digest_size(hash_type); + Checks::check_exit( + VCPKG_LINE_INFO, paths.get_filesystem().exists(path), "File %s does not exist", path.u8string()); const std::string cmd_line = Strings::format( R"(shasum -a %s "%s" | awk '{ print $1 }')", digest_size, path.u8string()); return run_shasum_and_post_process(cmd_line); @@ -185,12 +203,7 @@ namespace vcpkg::Commands::Hash std::string get_string_hash(const std::string& s, const std::string& hash_type) { const std::string digest_size = get_digest_size(hash_type); - - static const std::regex ALLOWED_CHARS{"^[a-zA-Z0-9:]*$"}; - - Checks::check_exit(VCPKG_LINE_INFO, - std::regex_match(s, ALLOWED_CHARS), - "Only alphanumeric chars and colons are currently allowed"); + verify_has_only_allowed_chars(s); const std::string cmd_line = Strings::format( R"(echo -n "%s" | shasum -a %s | awk '{ print $1 }')", s, digest_size); @@ -210,13 +223,13 @@ namespace vcpkg::Commands::Hash nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); const fs::path file_to_hash = args.command_arguments[0]; const std::string algorithm = args.command_arguments.size() == 2 ? args.command_arguments[1] : "SHA512"; - const std::string hash = get_file_hash(file_to_hash, algorithm); + const std::string hash = get_file_hash(paths, file_to_hash, algorithm); System::println(hash); Checks::exit_success(VCPKG_LINE_INFO); } -- cgit v1.2.3 From 7d5c33cf1b9483c94894e5f1831c8411b36f37cf Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 6 Apr 2018 14:36:48 -0700 Subject: [vcpkgTools.xml] Bump version to "2" --- toolsrc/src/vcpkg/commands.fetch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index e369f44d2..d085fb0f7 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -51,7 +51,7 @@ namespace vcpkg::Commands::Fetch static constexpr StringLiteral OS_STRING = "linux"; #endif - static const std::string XML_VERSION = "1"; + static const std::string XML_VERSION = "2"; static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; const auto maybe_get_string_inside_tags = [](const std::string& input, -- cgit v1.2.3 From ee75dd08d3ea93eb2cc2f309a1f49abe2b470448 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 6 Apr 2018 14:45:50 -0700 Subject: Improve error message --- toolsrc/src/vcpkg/commands.fetch.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index d085fb0f7..0be097bc9 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -83,8 +83,11 @@ namespace vcpkg::Commands::Fetch std::smatch match_xml_version; const bool has_xml_version = std::regex_search(XML.cbegin(), XML.cend(), match_xml_version, XML_VERSION_REGEX); - Checks::check_exit( - VCPKG_LINE_INFO, has_xml_version, "Could not find in %s", XML_PATH.generic_string()); + Checks::check_exit(VCPKG_LINE_INFO, + has_xml_version, + R"(Could not find in %s)", + XML_VERSION, + XML_PATH.generic_string()); Checks::check_exit(VCPKG_LINE_INFO, XML_VERSION == match_xml_version[1], "Expected %s version: [%s], but was [%s]. Please re-run bootstrap-vcpkg.", -- cgit v1.2.3 From d11014e2ae97c8f7b38f72d23d942a4f107afd26 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 6 Apr 2018 14:46:40 -0700 Subject: Don't ignore fs.rename() errors --- toolsrc/src/vcpkg/commands.fetch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 0be097bc9..85ec6b289 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -222,7 +222,7 @@ namespace vcpkg::Commands::Fetch Checks::exit_with_message(VCPKG_LINE_INFO, "Unexpected archive extension: %s", ext.u8string()); } - fs.rename(to_path_partial, to_path, ec); + fs.rename(to_path_partial, to_path); } static void download_file(const VcpkgPaths& paths, @@ -256,7 +256,7 @@ namespace vcpkg::Commands::Fetch sha512, actual_hash); - fs.rename(download_path_part, download_path, ec); + fs.rename(download_path_part, download_path); } static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data) -- cgit v1.2.3 From ba432c23bccb3e0eb716765984cc9e9e91845822 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 6 Apr 2018 14:47:15 -0700 Subject: Fix spacing in error message --- toolsrc/src/vcpkg/commands.fetch.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 85ec6b289..7cce312dd 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -247,10 +247,10 @@ namespace vcpkg::Commands::Fetch Checks::check_exit(VCPKG_LINE_INFO, sha512 == actual_hash, "File does not have the expected hash:\n" - " url : [ %s ]\n" - " File path : [ %s ]\n" - " Expected hash: [ %s ]\n" - " Actual hash: [ %s ] \n", + " url : [ %s ]\n" + " File path : [ %s ]\n" + " Expected hash : [ %s ]\n" + " Actual hash : [ %s ]\n", url, download_path.u8string(), sha512, -- cgit v1.2.3 From 80f16f769e981b4a52ae841dd71f73009866133c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 6 Apr 2018 14:51:53 -0700 Subject: Use Cache class --- toolsrc/src/vcpkg/vcpkgpaths.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 4f998d579..0903c2d76 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -91,14 +91,7 @@ namespace vcpkg const fs::path& VcpkgPaths::get_tool_exe(const std::string& tool) const { - const auto it = this->tool_paths.find(tool); - if (it != this->tool_paths.cend()) - { - return it->second; - } - - this->tool_paths[tool] = Commands::Fetch::get_tool_path(*this, tool); - return this->tool_paths[tool]; + return this->tool_paths.get_lazy(tool, [&]() { return Commands::Fetch::get_tool_path(*this, tool); }); } const Toolset& VcpkgPaths::get_toolset(const Build::PreBuildInfo& prebuildinfo) const -- cgit v1.2.3 From 5d96ff1229d3e93f901215f054225d2859b07f5f Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 6 Apr 2018 15:12:26 -0700 Subject: [fetch] Don't attempt to download on unknown OSes --- toolsrc/src/vcpkg/commands.fetch.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 7cce312dd..1d2c67d67 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -47,10 +47,13 @@ namespace vcpkg::Commands::Fetch static constexpr StringLiteral OS_STRING = "windows"; #elif defined(__APPLE__) static constexpr StringLiteral OS_STRING = "osx"; -#else // assume linux +#elif defined(__linux__) static constexpr StringLiteral OS_STRING = "linux"; +#else + return ToolData{}; #endif +#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__) static const std::string XML_VERSION = "2"; static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; @@ -137,6 +140,7 @@ namespace vcpkg::Commands::Fetch paths.downloads / archive_name.value_or(exe_relative_path), tool_dir_path, sha512}; +#endif } static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, -- cgit v1.2.3 From b87aeb77deb7b6cdc7e78d0b006243a15993e78c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 6 Apr 2018 15:17:16 -0700 Subject: [vcpkg.exe] Verify hash for already present files. Dont check for path twice --- toolsrc/src/vcpkg/commands.fetch.cpp | 42 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 1d2c67d67..cf19b4384 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -229,17 +229,31 @@ namespace vcpkg::Commands::Fetch fs.rename(to_path_partial, to_path); } + static void verify_hash(const VcpkgPaths& paths, + const std::string& url, + const fs::path& path, + const std::string& sha512) + { + const std::string actual_hash = Hash::get_file_hash(paths, path, "SHA512"); + Checks::check_exit(VCPKG_LINE_INFO, + sha512 == actual_hash, + "File does not have the expected hash:\n" + " url : [ %s ]\n" + " File path : [ %s ]\n" + " Expected hash : [ %s ]\n" + " Actual hash : [ %s ]\n", + url, + path.u8string(), + sha512, + actual_hash); + } + static void download_file(const VcpkgPaths& paths, const std::string& url, const fs::path& download_path, const std::string& sha512) { Files::Filesystem& fs = paths.get_filesystem(); - if (fs.exists(download_path)) - { - return; - } - const std::string download_path_part = download_path.u8string() + ".part"; std::error_code ec; fs.remove(download_path_part, ec); @@ -247,19 +261,7 @@ namespace vcpkg::Commands::Fetch R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part)); Checks::check_exit(VCPKG_LINE_INFO, code == 0, "Could not download %s", url); - const std::string actual_hash = Hash::get_file_hash(paths, download_path_part, "SHA512"); - Checks::check_exit(VCPKG_LINE_INFO, - sha512 == actual_hash, - "File does not have the expected hash:\n" - " url : [ %s ]\n" - " File path : [ %s ]\n" - " Expected hash : [ %s ]\n" - " Actual hash : [ %s ]\n", - url, - download_path.u8string(), - sha512, - actual_hash); - + verify_hash(paths, url, download_path_part, sha512); fs.rename(download_path_part, download_path); } @@ -302,6 +304,10 @@ namespace vcpkg::Commands::Fetch download_file(paths, tool_data.url, tool_data.download_path, tool_data.sha512); System::println("Downloading %s... done.", tool_name); } + else + { + verify_hash(paths, tool_data.url, tool_data.download_path, tool_data.sha512); + } System::println("Extracting %s...", tool_name); extract_archive(paths, tool_data.download_path, tool_data.tool_dir_path); -- cgit v1.2.3 From be2ea0373fbbb17ec792155ebaec0d2dd3d95242 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 6 Apr 2018 15:47:58 -0700 Subject: #ifdef linux-specific code --- toolsrc/src/vcpkg/commands.fetch.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index cf19b4384..9652d0b9e 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -199,6 +199,7 @@ namespace vcpkg::Commands::Fetch return data_lines; } +#if !defined(_WIN32) static void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path) { Files::Filesystem& fs = paths.get_filesystem(); @@ -265,6 +266,7 @@ namespace vcpkg::Commands::Fetch fs.rename(download_path_part, download_path); } +#endif static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data) { const auto& fs = paths.get_filesystem(); -- cgit v1.2.3 From bab554a8b3df8bf451e846022b310204b8843640 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 6 Apr 2018 22:52:35 -0700 Subject: [vcpkg hash] Process in C++ instead of calling awk --- toolsrc/src/vcpkg/commands.hash.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 3f90eeaca..801b8d323 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -187,7 +187,16 @@ namespace vcpkg::Commands::Hash "Failed to run:\n" " %s", cmd_line); - return Strings::trim(std::string{ec_data.output}); + + std::vector split = Strings::split(ec_data.output, " "); + Checks::check_exit(VCPKG_LINE_INFO, + split.size() == 3, + "Expected output of the form [hash filename\n] (3 tokens), but got\n" + "[%s] (%s tokens)", + ec_data.output, + std::to_string(split.size())); + + return split[0]; } std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type) @@ -196,7 +205,7 @@ namespace vcpkg::Commands::Hash Checks::check_exit( VCPKG_LINE_INFO, paths.get_filesystem().exists(path), "File %s does not exist", path.u8string()); const std::string cmd_line = Strings::format( - R"(shasum -a %s "%s" | awk '{ print $1 }')", digest_size, path.u8string()); + R"(shasum -a %s "%s")", digest_size, path.u8string()); return run_shasum_and_post_process(cmd_line); } @@ -206,7 +215,7 @@ namespace vcpkg::Commands::Hash verify_has_only_allowed_chars(s); const std::string cmd_line = Strings::format( - R"(echo -n "%s" | shasum -a %s | awk '{ print $1 }')", s, digest_size); + R"(echo -n "%s" | shasum -a %s)", s, digest_size); return run_shasum_and_post_process(cmd_line); } } -- cgit v1.2.3 From 479ed417d91122f68bf5806622a78be04b391166 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 6 Apr 2018 22:54:27 -0700 Subject: [vcpkg hash] formatting --- toolsrc/src/vcpkg/commands.hash.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 801b8d323..c23a63e1e 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -204,8 +204,7 @@ namespace vcpkg::Commands::Hash const std::string digest_size = get_digest_size(hash_type); Checks::check_exit( VCPKG_LINE_INFO, paths.get_filesystem().exists(path), "File %s does not exist", path.u8string()); - const std::string cmd_line = Strings::format( - R"(shasum -a %s "%s")", digest_size, path.u8string()); + const std::string cmd_line = Strings::format(R"(shasum -a %s "%s")", digest_size, path.u8string()); return run_shasum_and_post_process(cmd_line); } @@ -214,8 +213,7 @@ namespace vcpkg::Commands::Hash const std::string digest_size = get_digest_size(hash_type); verify_has_only_allowed_chars(s); - const std::string cmd_line = Strings::format( - R"(echo -n "%s" | shasum -a %s)", s, digest_size); + const std::string cmd_line = Strings::format(R"(echo -n "%s" | shasum -a %s)", s, digest_size); return run_shasum_and_post_process(cmd_line); } } -- cgit v1.2.3 From 7a19c72ca9e9ae8215be63e957ba11cc156b87b9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:03:59 -0700 Subject: Rename. Remove stray semicolon --- toolsrc/src/vcpkg/base/strings.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index 5fedf3e1f..541b1f2d9 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -7,7 +7,7 @@ namespace vcpkg::Strings::details { // To disambiguate between two overloads - static bool IS_SPACE(const char c) { return std::isspace(c) != 0; }; + static bool is_space(const char c) { return std::isspace(c) != 0; } // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower() static char tolower_char(const char c) { return static_cast(std::tolower(c)); } @@ -143,8 +143,8 @@ namespace vcpkg::Strings std::string trim(std::string&& s) { - s.erase(std::find_if_not(s.rbegin(), s.rend(), details::IS_SPACE).base(), s.end()); - s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), details::IS_SPACE)); + s.erase(std::find_if_not(s.rbegin(), s.rend(), details::is_space).base(), s.end()); + s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), details::is_space)); return std::move(s); } -- cgit v1.2.3 From fcdf4637ed9c645cc3719358a292c4571806e0bd Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:07:40 -0700 Subject: Default construct std::array() --- toolsrc/src/vcpkg/base/chrono.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/chrono.cpp b/toolsrc/src/vcpkg/base/chrono.cpp index 00f8ba3f1..eff84ee4e 100644 --- a/toolsrc/src/vcpkg/base/chrono.cpp +++ b/toolsrc/src/vcpkg/base/chrono.cpp @@ -117,9 +117,7 @@ namespace vcpkg::Chrono std::string CTime::to_string() const { - std::array date; - date.fill(0); - + std::array date{}; strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S.0Z", &m_tm); return &date[0]; } -- cgit v1.2.3 From 87f7f23d07ad6af428793a3acb45626d1228c802 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:10:03 -0700 Subject: const/auto --- toolsrc/src/vcpkg/base/chrono.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/chrono.cpp b/toolsrc/src/vcpkg/base/chrono.cpp index eff84ee4e..2a76f5df0 100644 --- a/toolsrc/src/vcpkg/base/chrono.cpp +++ b/toolsrc/src/vcpkg/base/chrono.cpp @@ -15,7 +15,7 @@ namespace vcpkg::Chrono using std::chrono::nanoseconds; using std::chrono::seconds; - const double nanos_as_double = static_cast(nanos.count()); + const auto nanos_as_double = static_cast(nanos.count()); if (duration_cast(nanos) > hours()) { @@ -92,7 +92,7 @@ namespace vcpkg::Chrono Optional CTime::parse(CStringView str) { CTime ret; - auto assigned = + const auto assigned = #if defined(_WIN32) sscanf_s #else @@ -123,7 +123,7 @@ namespace vcpkg::Chrono } std::chrono::system_clock::time_point CTime::to_time_point() const { - auto t = mktime(&m_tm); + const time_t t = mktime(&m_tm); return std::chrono::system_clock::from_time_t(t); } } -- cgit v1.2.3 From a64b160c67bfe8de754f41004f5c7cdbfea0a0ee Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:13:41 -0700 Subject: Use auto on left side when casting on right side --- toolsrc/src/vcpkg/base/cofffilereader.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp index 96d280108..bc418f42a 100644 --- a/toolsrc/src/vcpkg/base/cofffilereader.cpp +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -87,7 +87,7 @@ namespace vcpkg::CoffFileReader static const size_t MACHINE_TYPE_SIZE = 2; std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE); - const uint16_t machine = reinterpret_bytes(machine_field_as_string.c_str()); + const auto machine = reinterpret_bytes(machine_field_as_string.c_str()); return to_machine_type(machine); } @@ -158,7 +158,7 @@ namespace vcpkg::CoffFileReader for (uint32_t i = 0; i < offset_count; ++i) { const std::string value_as_string = raw_offsets.substr(OFFSET_WIDTH * i, OFFSET_WIDTH * (i + 1)); - const uint32_t value = reinterpret_bytes(value_as_string.c_str()); + const auto value = reinterpret_bytes(value_as_string.c_str()); // Ignore offsets that point to offset 0. See vcpkg github #223 #288 #292 if (value != 0) @@ -182,7 +182,7 @@ namespace vcpkg::CoffFileReader static ImportHeader read(fstream& fs) { static const size_t SIG1_OFFSET = 0; - static const uint16_t SIG1 = static_cast(MachineType::UNKNOWN); + static const auto SIG1 = static_cast(MachineType::UNKNOWN); static const size_t SIG1_SIZE = 2; static const size_t SIG2_OFFSET = 2; @@ -194,11 +194,11 @@ namespace vcpkg::CoffFileReader fs.read(&ret.data[0], HEADER_SIZE); const std::string sig1_as_string = ret.data.substr(SIG1_OFFSET, SIG1_SIZE); - const uint16_t sig1 = reinterpret_bytes(sig1_as_string.c_str()); + const auto sig1 = reinterpret_bytes(sig1_as_string.c_str()); Checks::check_exit(VCPKG_LINE_INFO, sig1 == SIG1, "Sig1 was incorrect. Expected %s but got %s", SIG1, sig1); const std::string sig2_as_string = ret.data.substr(SIG2_OFFSET, SIG2_SIZE); - const uint16_t sig2 = reinterpret_bytes(sig2_as_string.c_str()); + const auto sig2 = reinterpret_bytes(sig2_as_string.c_str()); Checks::check_exit(VCPKG_LINE_INFO, sig2 == SIG2, "Sig2 was incorrect. Expected %s but got %s", SIG2, sig2); return ret; @@ -210,7 +210,7 @@ namespace vcpkg::CoffFileReader static const size_t MACHINE_TYPE_SIZE = 2; std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE); - const uint16_t machine = reinterpret_bytes(machine_field_as_string.c_str()); + const auto machine = reinterpret_bytes(machine_field_as_string.c_str()); return to_machine_type(machine); } @@ -278,7 +278,7 @@ namespace vcpkg::CoffFileReader second_linker_member_header.name().substr(0, 2) == "/ ", "Could not find proper second linker member"); // The first 4 bytes contains the number of archive members - const uint32_t archive_member_count = read_value_from_stream(fs); + const auto archive_member_count = read_value_from_stream(fs); const OffsetsArray offsets = OffsetsArray::read(fs, archive_member_count); marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + second_linker_member_header.member_size()); marker.seek_to_marker(fs); @@ -297,7 +297,7 @@ namespace vcpkg::CoffFileReader { marker.set_to_offset(offset + ArchiveMemberHeader::HEADER_SIZE); // Skip the header, no need to read it. marker.seek_to_marker(fs); - const uint16_t first_two_bytes = peek_value_from_stream(fs); + const auto first_two_bytes = peek_value_from_stream(fs); const bool isImportHeader = to_machine_type(first_two_bytes) == MachineType::UNKNOWN; const MachineType machine = isImportHeader ? ImportHeader::read(fs).machine_type() : CoffFileHeader::read(fs).machine_type(); -- cgit v1.2.3 From 2076dfe376d21d3f89e342903edb0a95e96a51e5 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:14:20 -0700 Subject: Naming convention --- toolsrc/src/vcpkg/base/cofffilereader.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp index bc418f42a..fdab307eb 100644 --- a/toolsrc/src/vcpkg/base/cofffilereader.cpp +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -43,7 +43,7 @@ namespace vcpkg::CoffFileReader actual); } - static void read_and_verify_PE_signature(fstream& fs) + static void read_and_verify_pe_signature(fstream& fs) { static const size_t OFFSET_TO_PE_SIGNATURE_OFFSET = 0x3c; @@ -51,13 +51,13 @@ namespace vcpkg::CoffFileReader static const size_t PE_SIGNATURE_SIZE = 4; fs.seekg(OFFSET_TO_PE_SIGNATURE_OFFSET, ios_base::beg); - const int32_t offset_to_PE_signature = read_value_from_stream(fs); + const auto offset_to_pe_signature = read_value_from_stream(fs); - fs.seekg(offset_to_PE_signature); + fs.seekg(offset_to_pe_signature); char signature[PE_SIGNATURE_SIZE]; fs.read(signature, PE_SIGNATURE_SIZE); verify_equal_strings(VCPKG_LINE_INFO, PE_SIGNATURE, signature, PE_SIGNATURE_SIZE, "PE_SIGNATURE"); - fs.seekg(offset_to_PE_signature + PE_SIGNATURE_SIZE, ios_base::beg); + fs.seekg(offset_to_pe_signature + PE_SIGNATURE_SIZE, ios_base::beg); } static fpos_t align_to_size(const uint64_t unaligned, const uint64_t alignment_size) @@ -235,7 +235,7 @@ namespace vcpkg::CoffFileReader std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate); Checks::check_exit(VCPKG_LINE_INFO, fs.is_open(), "Could not open file %s for reading", path.generic_string()); - read_and_verify_PE_signature(fs); + read_and_verify_pe_signature(fs); CoffFileHeader header = CoffFileHeader::read(fs); const MachineType machine = header.machine_type(); return {machine}; @@ -283,8 +283,8 @@ namespace vcpkg::CoffFileReader marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + second_linker_member_header.member_size()); marker.seek_to_marker(fs); - const bool hasLongnameMemberHeader = peek_value_from_stream(fs) == 0x2F2F; - if (hasLongnameMemberHeader) + const bool has_longname_member_header = peek_value_from_stream(fs) == 0x2F2F; + if (has_longname_member_header) { const ArchiveMemberHeader longnames_member_header = ArchiveMemberHeader::read(fs); marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + longnames_member_header.member_size()); @@ -298,9 +298,9 @@ namespace vcpkg::CoffFileReader marker.set_to_offset(offset + ArchiveMemberHeader::HEADER_SIZE); // Skip the header, no need to read it. marker.seek_to_marker(fs); const auto first_two_bytes = peek_value_from_stream(fs); - const bool isImportHeader = to_machine_type(first_two_bytes) == MachineType::UNKNOWN; + const bool is_import_header = to_machine_type(first_two_bytes) == MachineType::UNKNOWN; const MachineType machine = - isImportHeader ? ImportHeader::read(fs).machine_type() : CoffFileHeader::read(fs).machine_type(); + is_import_header ? ImportHeader::read(fs).machine_type() : CoffFileHeader::read(fs).machine_type(); machine_types.insert(machine); } -- cgit v1.2.3 From fc27c9dd5c2559fb604cc2ce73cfb8e79ef0e406 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:18:07 -0700 Subject: [cofffilereader] Use StringLiteral --- toolsrc/src/vcpkg/base/cofffilereader.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp index fdab307eb..fec26a441 100644 --- a/toolsrc/src/vcpkg/base/cofffilereader.cpp +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -2,6 +2,7 @@ #include #include +#include using namespace std; @@ -47,7 +48,7 @@ namespace vcpkg::CoffFileReader { static const size_t OFFSET_TO_PE_SIGNATURE_OFFSET = 0x3c; - static const char* PE_SIGNATURE = "PE\0\0"; + static const StringLiteral PE_SIGNATURE = "PE\0\0"; static const size_t PE_SIGNATURE_SIZE = 4; fs.seekg(OFFSET_TO_PE_SIGNATURE_OFFSET, ios_base::beg); @@ -56,7 +57,7 @@ namespace vcpkg::CoffFileReader fs.seekg(offset_to_pe_signature); char signature[PE_SIGNATURE_SIZE]; fs.read(signature, PE_SIGNATURE_SIZE); - verify_equal_strings(VCPKG_LINE_INFO, PE_SIGNATURE, signature, PE_SIGNATURE_SIZE, "PE_SIGNATURE"); + verify_equal_strings(VCPKG_LINE_INFO, PE_SIGNATURE.c_str(), signature, PE_SIGNATURE_SIZE, "PE_SIGNATURE"); fs.seekg(offset_to_pe_signature + PE_SIGNATURE_SIZE, ios_base::beg); } @@ -102,7 +103,7 @@ namespace vcpkg::CoffFileReader static ArchiveMemberHeader read(fstream& fs) { static const size_t HEADER_END_OFFSET = 58; - static const char* HEADER_END = "`\n"; + static const StringLiteral HEADER_END = "`\n"; static const size_t HEADER_END_SIZE = 2; ArchiveMemberHeader ret; @@ -113,7 +114,7 @@ namespace vcpkg::CoffFileReader { const std::string header_end = ret.data.substr(HEADER_END_OFFSET, HEADER_END_SIZE); verify_equal_strings( - VCPKG_LINE_INFO, HEADER_END, header_end.c_str(), HEADER_END_SIZE, "LIB HEADER_END"); + VCPKG_LINE_INFO, HEADER_END.c_str(), header_end.c_str(), HEADER_END_SIZE, "LIB HEADER_END"); } return ret; @@ -220,14 +221,14 @@ namespace vcpkg::CoffFileReader static void read_and_verify_archive_file_signature(fstream& fs) { - static const char* FILE_START = "!\n"; + static const StringLiteral FILE_START = "!\n"; static const size_t FILE_START_SIZE = 8; fs.seekg(fs.beg); char file_start[FILE_START_SIZE]; fs.read(file_start, FILE_START_SIZE); - verify_equal_strings(VCPKG_LINE_INFO, FILE_START, file_start, FILE_START_SIZE, "LIB FILE_START"); + verify_equal_strings(VCPKG_LINE_INFO, FILE_START.c_str(), file_start, FILE_START_SIZE, "LIB FILE_START"); } DllInfo read_dll(const fs::path& path) -- cgit v1.2.3 From d1420efa9faf9b18ba49f3990d8c0cebf7889641 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:18:46 -0700 Subject: fs.beg -> std::festream::beg --- toolsrc/src/vcpkg/base/cofffilereader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp index fec26a441..7538808c2 100644 --- a/toolsrc/src/vcpkg/base/cofffilereader.cpp +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -224,7 +224,7 @@ namespace vcpkg::CoffFileReader static const StringLiteral FILE_START = "!\n"; static const size_t FILE_START_SIZE = 8; - fs.seekg(fs.beg); + fs.seekg(std::fstream::beg); char file_start[FILE_START_SIZE]; fs.read(file_start, FILE_START_SIZE); -- cgit v1.2.3 From 84a0eaa0f2ead797cc78d74e3f35239430447383 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:20:25 -0700 Subject: [cofffilereader.cpp] static const -> static constexpr --- toolsrc/src/vcpkg/base/cofffilereader.cpp | 54 +++++++++++++++---------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp index 7538808c2..5b06a885c 100644 --- a/toolsrc/src/vcpkg/base/cofffilereader.cpp +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -46,10 +46,10 @@ namespace vcpkg::CoffFileReader static void read_and_verify_pe_signature(fstream& fs) { - static const size_t OFFSET_TO_PE_SIGNATURE_OFFSET = 0x3c; + static constexpr size_t OFFSET_TO_PE_SIGNATURE_OFFSET = 0x3c; - static const StringLiteral PE_SIGNATURE = "PE\0\0"; - static const size_t PE_SIGNATURE_SIZE = 4; + static constexpr StringLiteral PE_SIGNATURE = "PE\0\0"; + static constexpr size_t PE_SIGNATURE_SIZE = 4; fs.seekg(OFFSET_TO_PE_SIGNATURE_OFFSET, ios_base::beg); const auto offset_to_pe_signature = read_value_from_stream(fs); @@ -72,7 +72,7 @@ namespace vcpkg::CoffFileReader struct CoffFileHeader { - static const size_t HEADER_SIZE = 20; + static constexpr size_t HEADER_SIZE = 20; static CoffFileHeader read(fstream& fs) { @@ -84,8 +84,8 @@ namespace vcpkg::CoffFileReader MachineType machine_type() const { - static const size_t MACHINE_TYPE_OFFSET = 0; - static const size_t MACHINE_TYPE_SIZE = 2; + static constexpr size_t MACHINE_TYPE_OFFSET = 0; + static constexpr size_t MACHINE_TYPE_SIZE = 2; std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE); const auto machine = reinterpret_bytes(machine_field_as_string.c_str()); @@ -98,13 +98,13 @@ namespace vcpkg::CoffFileReader struct ArchiveMemberHeader { - static const size_t HEADER_SIZE = 60; + static constexpr size_t HEADER_SIZE = 60; static ArchiveMemberHeader read(fstream& fs) { - static const size_t HEADER_END_OFFSET = 58; - static const StringLiteral HEADER_END = "`\n"; - static const size_t HEADER_END_SIZE = 2; + static constexpr size_t HEADER_END_OFFSET = 58; + static constexpr StringLiteral HEADER_END = "`\n"; + static constexpr size_t HEADER_END_SIZE = 2; ArchiveMemberHeader ret; ret.data.resize(HEADER_SIZE); @@ -122,17 +122,17 @@ namespace vcpkg::CoffFileReader std::string name() const { - static const size_t HEADER_NAME_OFFSET = 0; - static const size_t HEADER_NAME_SIZE = 16; + static constexpr size_t HEADER_NAME_OFFSET = 0; + static constexpr size_t HEADER_NAME_SIZE = 16; return data.substr(HEADER_NAME_OFFSET, HEADER_NAME_SIZE); } uint64_t member_size() const { - static const size_t ALIGNMENT_SIZE = 2; + static constexpr size_t ALIGNMENT_SIZE = 2; - static const size_t HEADER_SIZE_OFFSET = 48; - static const size_t HEADER_SIZE_FIELD_SIZE = 10; + static constexpr size_t HEADER_SIZE_OFFSET = 48; + static constexpr size_t HEADER_SIZE_FIELD_SIZE = 10; const std::string as_string = data.substr(HEADER_SIZE_OFFSET, HEADER_SIZE_FIELD_SIZE); // This is in ASCII decimal representation const uint64_t value = std::strtoull(as_string.c_str(), nullptr, 10); @@ -148,7 +148,7 @@ namespace vcpkg::CoffFileReader { static OffsetsArray read(fstream& fs, const uint32_t offset_count) { - static const size_t OFFSET_WIDTH = 4; + static constexpr size_t OFFSET_WIDTH = 4; std::string raw_offsets; const size_t raw_offset_size = offset_count * OFFSET_WIDTH; @@ -178,17 +178,17 @@ namespace vcpkg::CoffFileReader struct ImportHeader { - static const size_t HEADER_SIZE = 20; + static constexpr size_t HEADER_SIZE = 20; static ImportHeader read(fstream& fs) { - static const size_t SIG1_OFFSET = 0; - static const auto SIG1 = static_cast(MachineType::UNKNOWN); - static const size_t SIG1_SIZE = 2; + static constexpr size_t SIG1_OFFSET = 0; + static constexpr auto SIG1 = static_cast(MachineType::UNKNOWN); + static constexpr size_t SIG1_SIZE = 2; - static const size_t SIG2_OFFSET = 2; - static const uint16_t SIG2 = 0xFFFF; - static const size_t SIG2_SIZE = 2; + static constexpr size_t SIG2_OFFSET = 2; + static constexpr uint16_t SIG2 = 0xFFFF; + static constexpr size_t SIG2_SIZE = 2; ImportHeader ret; ret.data.resize(HEADER_SIZE); @@ -207,8 +207,8 @@ namespace vcpkg::CoffFileReader MachineType machine_type() const { - static const size_t MACHINE_TYPE_OFFSET = 6; - static const size_t MACHINE_TYPE_SIZE = 2; + static constexpr size_t MACHINE_TYPE_OFFSET = 6; + static constexpr size_t MACHINE_TYPE_SIZE = 2; std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE); const auto machine = reinterpret_bytes(machine_field_as_string.c_str()); @@ -221,8 +221,8 @@ namespace vcpkg::CoffFileReader static void read_and_verify_archive_file_signature(fstream& fs) { - static const StringLiteral FILE_START = "!\n"; - static const size_t FILE_START_SIZE = 8; + static constexpr StringLiteral FILE_START = "!\n"; + static constexpr size_t FILE_START_SIZE = 8; fs.seekg(std::fstream::beg); -- cgit v1.2.3 From 4f1c5e0b9ad516b1b506154fe4bf88d96e8664c8 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:32:40 -0700 Subject: Use instead of . Default construct. --- toolsrc/src/vcpkg/base/system.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 171dd2bbf..ea74f872e 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #if defined(__APPLE__) #include @@ -23,7 +23,7 @@ namespace vcpkg::System { using std::chrono::system_clock; std::time_t now_time = system_clock::to_time_t(system_clock::now()); - tm parts; + tm parts{}; #if defined(_WIN32) localtime_s(&parts, &now_time); #else -- cgit v1.2.3 From 9725e59b997e1db31db9b9dfcb96725cbe0f474d Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:37:02 -0700 Subject: [system.cpp] Naming convention, const, auto& --- toolsrc/src/vcpkg/base/system.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index ea74f872e..3f2f47d72 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -158,7 +158,7 @@ namespace vcpkg::System #if defined(_WIN32) static const std::string SYSTEM_ROOT = get_environment_variable("SystemRoot").value_or_exit(VCPKG_LINE_INFO); static const std::string SYSTEM_32 = SYSTEM_ROOT + R"(\system32)"; - std::string NEW_PATH = Strings::format( + std::string new_path = Strings::format( R"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32); std::vector env_wstrings = { @@ -225,13 +225,13 @@ namespace vcpkg::System } if (extra_env.find("PATH") != extra_env.end()) - NEW_PATH += Strings::format(";%s", extra_env.find("PATH")->second); - env_cstr.append(Strings::to_utf16(NEW_PATH)); + new_path += Strings::format(";%s", extra_env.find("PATH")->second); + env_cstr.append(Strings::to_utf16(new_path)); env_cstr.push_back(L'\0'); env_cstr.append(L"VSLANG=1033"); env_cstr.push_back(L'\0'); - for (auto item : extra_env) + for (const auto& item : extra_env) { if (item.first == "PATH") continue; env_cstr.append(Strings::to_utf16(item.first)); @@ -339,7 +339,7 @@ namespace vcpkg::System const auto ec = _pclose(pipe); remove_byte_order_marks(&output); - Debug::println("_pclose() returned %d after %8d us", ec, (int)timer.microseconds()); + Debug::println("_pclose() returned %d after %8d us", ec, static_cast(timer.microseconds())); return {ec, Strings::to_utf8(output)}; #else -- cgit v1.2.3 From 30e516cd6163fb06d517669497b1aa7ad6db666f Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:39:23 -0700 Subject: constructor order of init --- toolsrc/src/vcpkg/binaryparagraph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp index 7a8b0d577..73ca23df1 100644 --- a/toolsrc/src/vcpkg/binaryparagraph.cpp +++ b/toolsrc/src/vcpkg/binaryparagraph.cpp @@ -79,7 +79,7 @@ namespace vcpkg } BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, const Triplet& triplet) - : version(), feature(fpgh.name), description(fpgh.description), maintainer() + : version(), description(fpgh.description), maintainer(), feature(fpgh.name) { this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); this->depends = filter_dependencies(fpgh.depends, triplet); -- cgit v1.2.3 From 4e4afa29bfc053d852544a24c2ecaeff165521fd Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:47:31 -0700 Subject: [build.cpp] Clang tidy fixes --- toolsrc/src/vcpkg/build.cpp | 73 ++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 38 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index b7055100b..76381f862 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -64,7 +64,8 @@ namespace vcpkg::Build::Command const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES, Build::CleanBuildtrees::NO, - Build::CleanPackages::NO}; + Build::CleanPackages::NO, + Build::DownloadTool::BUILT_IN}; std::set features_as_set(full_spec.features.begin(), full_spec.features.end()); features_as_set.emplace("core"); @@ -210,7 +211,7 @@ namespace vcpkg::Build for (auto&& host : host_architectures) { - auto it = Util::find_if(toolset.supported_architectures, [&](const ToolsetArchOption& opt) { + const auto it = Util::find_if(toolset.supported_architectures, [&](const ToolsetArchOption& opt) { return host == opt.host_arch && target_arch == opt.target_arch; }); if (it != toolset.supported_architectures.end()) return it->name; @@ -279,7 +280,7 @@ namespace vcpkg::Build { const Triplet& triplet = config.triplet; - auto dep_strings = + const std::vector dep_strings = Util::fmap_flatten(config.feature_list, [&](std::string const& feature) -> std::vector { if (feature == "core") { @@ -302,7 +303,7 @@ namespace vcpkg::Build if (fspec.feature().empty()) { // reference to default features - auto it = status_db.find_installed(fspec.spec()); + const auto it = status_db.find_installed(fspec.spec()); if (it == status_db.end()) { // not currently installed, so just leave the default reference so it will fail later @@ -310,9 +311,9 @@ namespace vcpkg::Build } else { - ret.push_back(FeatureSpec{fspec.spec(), "core"}); + ret.emplace_back(fspec.spec(), "core"); for (auto&& default_feature : it->get()->package.default_features) - ret.push_back(FeatureSpec{fspec.spec(), default_feature}); + ret.emplace_back(fspec.spec(), default_feature); } } else @@ -463,7 +464,7 @@ namespace vcpkg::Build abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag}); - std::string features = Strings::join(";", config.feature_list); + const std::string features = Strings::join(";", config.feature_list); abi_tag_entries.emplace_back(AbiEntry{"features", features}); if (config.build_package_options.use_head_version == UseHeadVersion::YES) @@ -471,7 +472,7 @@ namespace vcpkg::Build Util::sort(abi_tag_entries); - std::string full_abi_info = + const std::string full_abi_info = Strings::join("", abi_tag_entries, [](const AbiEntry& p) { return p.key + " " + p.value + "\n"; }); if (GlobalState::debugging) @@ -491,19 +492,17 @@ namespace vcpkg::Build { std::error_code ec; fs.create_directories(paths.buildtrees / name, ec); - auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt"); + const auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt"); fs.write_contents(abi_file_path, full_abi_info); return AbiTagAndFile{Commands::Hash::get_file_hash(paths, abi_file_path, "SHA1"), abi_file_path}; } - else - { - System::println( - "Warning: binary caching disabled because abi keys are missing values:\n%s", - Strings::join("", abi_tag_entries_missing, [](const AbiEntry& e) { return " " + e.key + "\n"; })); - return nullopt; - } + System::println( + "Warning: binary caching disabled because abi keys are missing values:\n%s", + Strings::join("", abi_tag_entries_missing, [](const AbiEntry& e) { return " " + e.key + "\n"; })); + + return nullopt; } static void decompress_archive(const VcpkgPaths& paths, const PackageSpec& spec, const fs::path& archive_path) @@ -518,10 +517,10 @@ namespace vcpkg::Build Checks::check_exit(VCPKG_LINE_INFO, files.empty(), "unable to clear path: %s", pkg_path.u8string()); #if defined(_WIN32) - auto&& _7za = paths.get_tool_exe(Tools::SEVEN_ZIP); + auto&& seven_zip_exe = paths.get_tool_exe(Tools::SEVEN_ZIP); System::cmd_execute_clean(Strings::format( - R"("%s" x "%s" -o"%s" -y >nul)", _7za.u8string(), archive_path.u8string(), pkg_path.u8string())); + R"("%s" x "%s" -o"%s" -y >nul)", seven_zip_exe.u8string(), archive_path.u8string(), pkg_path.u8string())); #else System::cmd_execute_clean(Strings::format( R"(unzip -qq "%s" "-d%s")", archive_path.u8string(), pkg_path.u8string())); @@ -538,11 +537,11 @@ namespace vcpkg::Build Checks::check_exit( VCPKG_LINE_INFO, !fs.exists(tmp_archive_path), "Could not remove file: %s", tmp_archive_path.u8string()); #if defined(_WIN32) - auto&& _7za = paths.get_tool_exe(Tools::SEVEN_ZIP); + auto&& seven_zip_exe = paths.get_tool_exe(Tools::SEVEN_ZIP); System::cmd_execute_clean(Strings::format( R"("%s" a "%s" "%s\*" >nul)", - _7za.u8string(), + seven_zip_exe.u8string(), tmp_archive_path.u8string(), paths.package_dir(spec).u8string())); #else @@ -584,7 +583,7 @@ namespace vcpkg::Build for (auto&& pspec : dep_pspecs) { if (pspec == spec) continue; - auto status_it = status_db.find_installed(pspec); + const auto status_it = status_db.find_installed(pspec); Checks::check_exit(VCPKG_LINE_INFO, status_it != status_db.end()); dependency_abis.emplace_back( AbiEntry{status_it->get()->package.spec.name(), status_it->get()->package.abi}); @@ -594,17 +593,15 @@ namespace vcpkg::Build auto maybe_abi_tag_and_file = compute_abi_tag(paths, config, pre_build_info, dependency_abis); - std::unique_ptr bcf; - - auto abi_tag_and_file = maybe_abi_tag_and_file.get(); + const auto abi_tag_and_file = maybe_abi_tag_and_file.get(); if (GlobalState::g_binary_caching && abi_tag_and_file) { - auto archives_root_dir = paths.root / "archives"; - auto archive_name = abi_tag_and_file->tag + ".zip"; - auto archive_subpath = fs::u8path(abi_tag_and_file->tag.substr(0, 2)) / archive_name; - auto archive_path = archives_root_dir / archive_subpath; - auto archive_tombstone_path = archives_root_dir / "fail" / archive_subpath; + const fs::path archives_root_dir = paths.root / "archives"; + const std::string archive_name = abi_tag_and_file->tag + ".zip"; + const fs::path archive_subpath = fs::u8path(abi_tag_and_file->tag.substr(0, 2)) / archive_name; + const fs::path archive_path = archives_root_dir / archive_subpath; + const fs::path archive_tombstone_path = archives_root_dir / "fail" / archive_subpath; if (fs.exists(archive_path)) { @@ -613,10 +610,12 @@ namespace vcpkg::Build decompress_archive(paths, spec, archive_path); auto maybe_bcf = Paragraphs::try_load_cached_package(paths, spec); - bcf = std::make_unique(std::move(maybe_bcf).value_or_exit(VCPKG_LINE_INFO)); + std::unique_ptr bcf = + std::make_unique(std::move(maybe_bcf).value_or_exit(VCPKG_LINE_INFO)); return {BuildResult::SUCCEEDED, std::move(bcf)}; } - else if (fs.exists(archive_tombstone_path)) + + if (fs.exists(archive_tombstone_path)) { System::println("Found failure tombstone: %s", archive_tombstone_path.u8string()); return BuildResult::BUILD_FAILED; @@ -635,7 +634,7 @@ namespace vcpkg::Build if (result.code == BuildResult::SUCCEEDED) { - auto tmp_archive_path = paths.buildtrees / spec.name() / (spec.triplet().to_string() + ".zip"); + const auto tmp_archive_path = paths.buildtrees / spec.name() / (spec.triplet().to_string() + ".zip"); compress_archive(paths, spec, tmp_archive_path); @@ -656,11 +655,9 @@ namespace vcpkg::Build return result; } - else - { - return do_build_package_and_clean_buildtrees( - paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); - } + + return do_build_package_and_clean_buildtrees( + paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); } const std::string& to_string(const BuildResult build_result) @@ -774,7 +771,7 @@ namespace vcpkg::Build const fs::path ports_cmake_script_path = paths.scripts / "get_triplet_environment.cmake"; const fs::path triplet_file_path = paths.triplets / (triplet.canonical_name() + ".cmake"); - auto triplet_abi_tag = [&]() { + const std::string triplet_abi_tag = [&]() { static std::map s_hash_cache; if (GlobalState::g_binary_caching) -- cgit v1.2.3 From 627e91a08fbd2cc407b87bbf961067761dec78c0 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:51:36 -0700 Subject: Util::unused() for commands that don't have arguments --- toolsrc/src/vcpkg/commands.cache.cpp | 2 +- toolsrc/src/vcpkg/commands.create.cpp | 2 +- toolsrc/src/vcpkg/commands.dependinfo.cpp | 3 +-- toolsrc/src/vcpkg/commands.import.cpp | 2 +- toolsrc/src/vcpkg/commands.integrate.cpp | 2 +- toolsrc/src/vcpkg/commands.owns.cpp | 2 +- toolsrc/src/vcpkg/commands.portsdiff.cpp | 2 +- toolsrc/src/vcpkg/commands.version.cpp | 2 +- 8 files changed, 8 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp index 85bf5fb4d..a9d8ba03c 100644 --- a/toolsrc/src/vcpkg/commands.cache.cpp +++ b/toolsrc/src/vcpkg/commands.cache.cpp @@ -38,7 +38,7 @@ namespace vcpkg::Commands::Cache void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - args.parse_arguments(COMMAND_STRUCTURE); + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); const std::vector binary_paragraphs = read_all_binary_paragraphs(paths); if (binary_paragraphs.empty()) diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp index 60769c9ef..dfb3ab784 100644 --- a/toolsrc/src/vcpkg/commands.create.cpp +++ b/toolsrc/src/vcpkg/commands.create.cpp @@ -18,7 +18,7 @@ namespace vcpkg::Commands::Create void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - args.parse_arguments(COMMAND_STRUCTURE); + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); const std::string port_name = args.command_arguments.at(0); const std::string url = args.command_arguments.at(1); diff --git a/toolsrc/src/vcpkg/commands.dependinfo.cpp b/toolsrc/src/vcpkg/commands.dependinfo.cpp index bb300d96e..1ca658216 100644 --- a/toolsrc/src/vcpkg/commands.dependinfo.cpp +++ b/toolsrc/src/vcpkg/commands.dependinfo.cpp @@ -19,7 +19,7 @@ namespace vcpkg::Commands::DependInfo void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - args.parse_arguments(COMMAND_STRUCTURE); + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); std::vector> source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); @@ -30,7 +30,6 @@ namespace vcpkg::Commands::DependInfo Util::erase_remove_if(source_control_files, [&](const std::unique_ptr& source_control_file) { - const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; if (Strings::case_insensitive_ascii_contains(source_paragraph.name, filter)) diff --git a/toolsrc/src/vcpkg/commands.import.cpp b/toolsrc/src/vcpkg/commands.import.cpp index 24394207b..4b595697a 100644 --- a/toolsrc/src/vcpkg/commands.import.cpp +++ b/toolsrc/src/vcpkg/commands.import.cpp @@ -103,7 +103,7 @@ namespace vcpkg::Commands::Import void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - args.parse_arguments(COMMAND_STRUCTURE); + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); const fs::path control_file_path(args.command_arguments[0]); const fs::path include_directory(args.command_arguments[1]); diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index d6ae27181..044a88d80 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -352,7 +352,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - args.parse_arguments(COMMAND_STRUCTURE); + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); #if defined(_WIN32) if (args.command_arguments[0] == Subcommand::INSTALL) diff --git a/toolsrc/src/vcpkg/commands.owns.cpp b/toolsrc/src/vcpkg/commands.owns.cpp index 52249187b..ee9584651 100644 --- a/toolsrc/src/vcpkg/commands.owns.cpp +++ b/toolsrc/src/vcpkg/commands.owns.cpp @@ -34,7 +34,7 @@ namespace vcpkg::Commands::Owns void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - args.parse_arguments(COMMAND_STRUCTURE); + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); const StatusParagraphs status_db = database_load_check(paths); search_file(paths, args.command_arguments[0], status_db); diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp index c6b02582f..0a72b3435 100644 --- a/toolsrc/src/vcpkg/commands.portsdiff.cpp +++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp @@ -128,7 +128,7 @@ namespace vcpkg::Commands::PortsDiff void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - args.parse_arguments(COMMAND_STRUCTURE); + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); const fs::path& git_exe = paths.get_tool_exe(Tools::GIT); diff --git a/toolsrc/src/vcpkg/commands.version.cpp b/toolsrc/src/vcpkg/commands.version.cpp index ffc5d2c8f..2ad91b57d 100644 --- a/toolsrc/src/vcpkg/commands.version.cpp +++ b/toolsrc/src/vcpkg/commands.version.cpp @@ -83,7 +83,7 @@ namespace vcpkg::Commands::Version void perform_and_exit(const VcpkgCmdArguments& args) { - args.parse_arguments(COMMAND_STRUCTURE); + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); System::println("Vcpkg package management program version %s\n" "\n" -- cgit v1.2.3 From 8d343ce6dfc850abdfbfd098765df072271ae6ad Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 02:58:30 -0700 Subject: [commands] Clang-tidy fixes --- toolsrc/src/vcpkg/commands.contact.cpp | 14 +++++++++----- toolsrc/src/vcpkg/commands.edit.cpp | 2 +- toolsrc/src/vcpkg/commands.integrate.cpp | 2 +- toolsrc/src/vcpkg/commands.list.cpp | 2 +- toolsrc/src/vcpkg/commands.upgrade.cpp | 3 ++- 5 files changed, 14 insertions(+), 9 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.contact.cpp b/toolsrc/src/vcpkg/commands.contact.cpp index ffed07557..9f86a67dc 100644 --- a/toolsrc/src/vcpkg/commands.contact.cpp +++ b/toolsrc/src/vcpkg/commands.contact.cpp @@ -14,24 +14,28 @@ namespace vcpkg::Commands::Contact return S_EMAIL; } - static const CommandSwitch switches[] = {{"--survey", "Launch default browser to the current vcpkg survey"}}; + static constexpr StringLiteral OPTION_SURVEY = "--survey"; + + static constexpr std::array SWITCHES = {{ + {OPTION_SURVEY, "Launch default browser to the current vcpkg survey"}, + }}; const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("contact"), 0, 0, - {switches, {}}, + {SWITCHES, {}}, nullptr, }; void perform_and_exit(const VcpkgCmdArguments& args) { - auto parsed_args = args.parse_arguments(COMMAND_STRUCTURE); + const ParsedArguments parsed_args = args.parse_arguments(COMMAND_STRUCTURE); - if (Util::Sets::contains(parsed_args.switches, switches[0].name)) + if (Util::Sets::contains(parsed_args.switches, SWITCHES[0].name)) { auto maybe_now = Chrono::CTime::get_current_date_time(); - if (auto p_now = maybe_now.get()) + if (const auto p_now = maybe_now.get()) { auto& fs = Files::get_real_filesystem(); auto config = UserConfig::try_read_data(fs); diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index 6c696018e..f0ddd43c5 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -93,7 +93,7 @@ namespace vcpkg::Commands::Edit const std::vector from_registry = find_from_registry(); candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend()); - auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { return fs.exists(p); }); + const auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { return fs.exists(p); }); if (it == candidate_paths.cend()) { System::println( diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 044a88d80..e70d9b2e3 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -108,7 +108,7 @@ namespace vcpkg::Commands::Integrate #if defined(_WIN32) static ElevationPromptChoice elevated_cmd_execute(const std::string& param) { - SHELLEXECUTEINFOW sh_ex_info = {0}; + SHELLEXECUTEINFOW sh_ex_info{}; sh_ex_info.cbSize = sizeof(sh_ex_info); sh_ex_info.fMask = SEE_MASK_NOCLOSEPROCESS; sh_ex_info.hwnd = nullptr; diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp index a5efd5442..4c4518d25 100644 --- a/toolsrc/src/vcpkg/commands.list.cpp +++ b/toolsrc/src/vcpkg/commands.list.cpp @@ -10,7 +10,7 @@ namespace vcpkg::Commands::List static constexpr StringLiteral OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually - static void do_print(const StatusParagraph& pgh, bool full_desc) + static void do_print(const StatusParagraph& pgh, const bool full_desc) { if (full_desc) { diff --git a/toolsrc/src/vcpkg/commands.upgrade.cpp b/toolsrc/src/vcpkg/commands.upgrade.cpp index c5b48f2a2..a902ddeaf 100644 --- a/toolsrc/src/vcpkg/commands.upgrade.cpp +++ b/toolsrc/src/vcpkg/commands.upgrade.cpp @@ -144,7 +144,8 @@ namespace vcpkg::Commands::Upgrade const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES, Build::CleanBuildtrees::NO, - Build::CleanPackages::NO}; + Build::CleanPackages::NO, + Build::DownloadTool::BUILT_IN}; // Set build settings for all install actions for (auto&& action : plan) -- cgit v1.2.3 From f07026539835aad4b87e2a88b3e38e144edaa9dd Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 03:12:15 -0700 Subject: [export.cpp] Define all valuse in BuildOptions --- toolsrc/src/vcpkg/export.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 32151c791..eda909635 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -70,8 +70,11 @@ namespace vcpkg::Export { static constexpr std::array ORDER = {ExportPlanType::ALREADY_BUILT, ExportPlanType::NOT_BUILT}; - static constexpr Build::BuildPackageOptions build_options = {Build::UseHeadVersion::NO, - Build::AllowDownloads::YES}; + static constexpr Build::BuildPackageOptions BUILD_OPTIONS = {Build::UseHeadVersion::NO, + Build::AllowDownloads::YES, + Build::CleanBuildtrees::NO, + Build::CleanPackages::NO, + Build::DownloadTool::BUILT_IN}; for (const ExportPlanType plan_type : ORDER) { @@ -84,7 +87,7 @@ namespace vcpkg::Export std::vector cont = it->second; std::sort(cont.begin(), cont.end(), &ExportPlanAction::compare_by_name); const std::string as_string = Strings::join("\n", cont, [](const ExportPlanAction* p) { - return Dependencies::to_output_string(p->request_type, p->spec.to_string(), build_options); + return Dependencies::to_output_string(p->request_type, p->spec.to_string(), BUILD_OPTIONS); }); switch (plan_type) -- cgit v1.2.3 From 269e78bb610369cbdc193be92c4fdd5bba1f7831 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 03:12:33 -0700 Subject: Remove unused #include directives --- toolsrc/src/vcpkg/export.cpp | 2 -- toolsrc/src/vcpkg/parse.cpp | 1 - toolsrc/src/vcpkg/triplet.cpp | 3 +-- 3 files changed, 1 insertion(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index eda909635..85a4dfad1 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -13,8 +13,6 @@ #include #include -#include - namespace vcpkg::Export { using Dependencies::ExportPlanAction; diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp index c2670f561..d50296cf8 100644 --- a/toolsrc/src/vcpkg/parse.cpp +++ b/toolsrc/src/vcpkg/parse.cpp @@ -2,7 +2,6 @@ #include -#include #include namespace vcpkg::Parse diff --git a/toolsrc/src/vcpkg/triplet.cpp b/toolsrc/src/vcpkg/triplet.cpp index ef0fab183..c4ad3f690 100644 --- a/toolsrc/src/vcpkg/triplet.cpp +++ b/toolsrc/src/vcpkg/triplet.cpp @@ -1,6 +1,5 @@ #include "pch.h" -#include #include #include @@ -38,7 +37,7 @@ namespace vcpkg const Triplet Triplet::ARM_UWP = from_canonical_name("arm-uwp"); const Triplet Triplet::ARM64_UWP = from_canonical_name("arm64-uwp"); const Triplet Triplet::ARM_WINDOWS = from_canonical_name("arm-windows"); - const Triplet Triplet::ARM64_WINDOWS = from_canonical_name("arm64-windows"); + const Triplet Triplet::ARM64_WINDOWS = from_canonical_name("arm64-windows"); bool Triplet::operator==(const Triplet& other) const { return this->m_instance == other.m_instance; } -- cgit v1.2.3 From 77338ee0df064fe89f9eb991b61bc9bb467f755c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 7 Apr 2018 03:24:45 -0700 Subject: Remove more unused #include directives --- toolsrc/src/vcpkg/commands.portsdiff.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp index 0a72b3435..2d2b4bd5f 100644 --- a/toolsrc/src/vcpkg/commands.portsdiff.cpp +++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 8da8f3e5b3cca98e9151d421a91f5c1590a47086 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 10 Apr 2018 04:48:02 -0700 Subject: [vcpkg] Rework dependencies.cpp to improve type safety and error detection --- toolsrc/src/tests.plan.cpp | 146 ++++++++---- toolsrc/src/vcpkg/commands.list.cpp | 9 +- toolsrc/src/vcpkg/dependencies.cpp | 435 +++++++++++++++++----------------- toolsrc/src/vcpkg/remove.cpp | 4 +- toolsrc/src/vcpkg/statusparagraph.cpp | 8 +- toolsrc/src/vcpkg/update.cpp | 11 +- toolsrc/src/vcpkg/vcpkglib.cpp | 24 +- 7 files changed, 355 insertions(+), 282 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index a99f1abb9..b054702a1 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -81,7 +81,7 @@ namespace UnitTest1 { std::unordered_map map; Triplet triplet; - PackageSpecMap(const Triplet& t) { triplet = t; } + PackageSpecMap(const Triplet& t = Triplet::X86_WINDOWS) { triplet = t; } PackageSpec emplace(const char* name, const char* depends = "", @@ -105,7 +105,7 @@ namespace UnitTest1 { std::vector> status_paragraphs; - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a", "b"); auto spec_b = spec_map.emplace("b", "c"); auto spec_c = spec_map.emplace("c"); @@ -124,7 +124,7 @@ namespace UnitTest1 { std::vector> status_paragraphs; - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a", "d"); auto spec_b = spec_map.emplace("b", "d, e"); auto spec_c = spec_map.emplace("c", "e, h"); @@ -167,7 +167,7 @@ namespace UnitTest1 std::vector> status_paragraphs; status_paragraphs.push_back(make_status_pgh("a")); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = FullPackageSpec{spec_map.emplace("a")}; auto install_plan = @@ -187,7 +187,7 @@ namespace UnitTest1 { std::vector> status_paragraphs; - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = FullPackageSpec{spec_map.emplace("a", "b")}; auto spec_b = FullPackageSpec{spec_map.emplace("b")}; @@ -216,7 +216,7 @@ namespace UnitTest1 status_paragraphs.push_back(make_status_pgh("j", "k")); status_paragraphs.push_back(make_status_pgh("k")); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a", "b, c, d, e, f, g, h, j, k"); auto spec_b = spec_map.emplace("b", "c, d, e, f, g, h, j, k"); @@ -251,7 +251,7 @@ namespace UnitTest1 status_paragraphs.push_back(make_status_pgh("b")); status_paragraphs.push_back(make_status_feature_pgh("b", "b1")); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; @@ -271,7 +271,7 @@ namespace UnitTest1 { std::vector> status_paragraphs; - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; @@ -291,7 +291,7 @@ namespace UnitTest1 std::vector> status_paragraphs; status_paragraphs.push_back(make_status_pgh("a")); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; auto spec_b = FullPackageSpec{spec_map.emplace("b")}; @@ -315,7 +315,7 @@ namespace UnitTest1 status_paragraphs.push_back(make_status_pgh("a")); status_paragraphs.push_back(make_status_feature_pgh("a", "a1", "")); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}})}; auto spec_b = FullPackageSpec{spec_map.emplace("b")}; @@ -334,7 +334,7 @@ namespace UnitTest1 { std::vector> status_paragraphs; - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = FullPackageSpec{spec_map.emplace("a", "", {{"a1", "b[b1]"}, {"a2", "b[b2]"}, {"a3", "a[a2]"}}), {"a3"}}; @@ -355,7 +355,7 @@ namespace UnitTest1 std::vector> status_paragraphs; status_paragraphs.push_back(make_status_pgh("b")); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[core]"), {"core"}}; auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; @@ -376,7 +376,7 @@ namespace UnitTest1 status_paragraphs.push_back(make_status_pgh("x", "b")); status_paragraphs.push_back(make_status_pgh("b")); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = FullPackageSpec{spec_map.emplace("a")}; auto spec_x = FullPackageSpec{spec_map.emplace("x", "a"), {"core"}}; @@ -674,17 +674,35 @@ namespace UnitTest1 Assert::IsTrue(install_plan[0].install_action.get()->computed_dependencies == std::vector{}); } + TEST_METHOD(install_with_default_features) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a", "")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto b_spec = spec_map.emplace("b", "", {{"0", ""}}, {"0"}); + auto a_spec = spec_map.emplace("a", "b[core]", {{"0", ""}}); + + // Install "a" and indicate that "b" should not install default features + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, {FeatureSpec{a_spec, "0"}, FeatureSpec{b_spec, "core"}}, status_db); + + Assert::IsTrue(install_plan.size() == 3); + remove_plan_check(&install_plan[0], "a"); + features_check(&install_plan[1], "b", {"core"}); + features_check(&install_plan[2], "a", {"0", "core"}); + } + TEST_METHOD(upgrade_with_default_features_1) { std::vector> pghs; pghs.push_back(make_status_pgh("a", "", "1")); pghs.push_back(make_status_feature_pgh("a", "0")); - pghs.back()->package.spec = - PackageSpec::from_name_and_triplet("a", Triplet::X86_WINDOWS).value_or_exit(VCPKG_LINE_INFO); StatusParagraphs status_db(std::move(pghs)); // Add a port "a" of which "core" and "0" are already installed. - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}, {"1"}); Dependencies::MapPortFileProvider provider(spec_map.map); @@ -697,23 +715,47 @@ namespace UnitTest1 Assert::AreEqual(size_t(2), plan.size()); Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - - Assert::AreEqual("a", plan[1].spec().name().c_str()); - features_check(&plan[1], "a", {"core", "0"}, Triplet::X86_WINDOWS); + remove_plan_check(&plan[0], "a"); + features_check(&plan[1], "a", {"core", "0"}); } TEST_METHOD(upgrade_with_default_features_2) { std::vector> pghs; - pghs.push_back(make_status_pgh("b")); - pghs.push_back(make_status_pgh("a", "b[core]")); - pghs.back()->package.spec = - PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + // B is currently installed _without_ default feature b0 + pghs.push_back(make_status_pgh("b", "", "b0", "x64-windows")); + pghs.push_back(make_status_pgh("a", "b[core]", "", "x64-windows")); + + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a = spec_map.emplace("a", "b[core]"); + auto spec_b = spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b0", "b1"}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + graph.upgrade(spec_b); + auto plan = graph.serialize(); + + // The upgrade should install the new default feature b1 but not b0 + Assert::AreEqual(size_t(4), plan.size()); + remove_plan_check(&plan[0], "a", Triplet::X64_WINDOWS); + remove_plan_check(&plan[1], "b", Triplet::X64_WINDOWS); + features_check(&plan[2], "b", {"core", "b1"}, Triplet::X64_WINDOWS); + features_check(&plan[3], "a", {"core"}, Triplet::X64_WINDOWS); + } + + TEST_METHOD(upgrade_with_default_features_3) + { + std::vector> pghs; + // note: unrelated package due to x86 triplet + pghs.push_back(make_status_pgh("b", "", "", "x86-windows")); + pghs.push_back(make_status_pgh("a", "", "", "x64-windows")); StatusParagraphs status_db(std::move(pghs)); - // Add a port "a" of which "core" and "0" are already installed. PackageSpecMap spec_map(Triplet::X64_WINDOWS); auto spec_a = spec_map.emplace("a", "b[core]"); spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b0"}); @@ -724,17 +766,33 @@ namespace UnitTest1 graph.upgrade(spec_a); auto plan = graph.serialize(); - // The upgrade should not install the default feature + // The upgrade should install the default feature Assert::AreEqual(size_t(3), plan.size()); + remove_plan_check(&plan[0], "a", Triplet::X64_WINDOWS); + features_check(&plan[1], "b", {"b0", "core"}, Triplet::X64_WINDOWS); + features_check(&plan[2], "a", {"core"}, Triplet::X64_WINDOWS); + } - Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); + TEST_METHOD(upgrade_with_new_default_feature) + { + std::vector> pghs; + pghs.push_back(make_status_pgh("a", "", "0", "x86-windows")); - Assert::AreEqual("b", plan[1].spec().name().c_str()); - features_check(&plan[1], "b", {"b0", "core"}, Triplet::X64_WINDOWS); + StatusParagraphs status_db(std::move(pghs)); - Assert::AreEqual("a", plan[2].spec().name().c_str()); - features_check(&plan[2], "a", {"core"}, Triplet::X64_WINDOWS); + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "", {{"0", ""}, {"1", ""}, {"2", ""}}, {"0", "1"}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + auto plan = graph.serialize(); + + // The upgrade should install the new default feature but not the old default feature 0 + Assert::AreEqual(size_t(2), plan.size()); + remove_plan_check(&plan[0], "a", Triplet::X86_WINDOWS); + features_check(&plan[1], "a", {"core", "1"}, Triplet::X86_WINDOWS); } TEST_METHOD(transitive_features_test) @@ -924,7 +982,7 @@ namespace UnitTest1 pghs.push_back(make_status_pgh("a")); StatusParagraphs status_db(std::move(pghs)); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a"); Dependencies::MapPortFileProvider provider(spec_map.map); @@ -948,7 +1006,7 @@ namespace UnitTest1 pghs.push_back(make_status_pgh("b", "a")); StatusParagraphs status_db(std::move(pghs)); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a"); spec_map.emplace("b", "a"); @@ -980,7 +1038,7 @@ namespace UnitTest1 pghs.push_back(make_status_pgh("b")); StatusParagraphs status_db(std::move(pghs)); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a"); spec_map.emplace("b", "a"); @@ -1004,7 +1062,7 @@ namespace UnitTest1 pghs.push_back(make_status_pgh("a")); StatusParagraphs status_db(std::move(pghs)); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a", "b"); spec_map.emplace("b"); @@ -1031,7 +1089,7 @@ namespace UnitTest1 pghs.push_back(make_status_feature_pgh("a", "a1")); StatusParagraphs status_db(std::move(pghs)); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}); Dependencies::MapPortFileProvider provider(spec_map.map); @@ -1057,7 +1115,7 @@ namespace UnitTest1 StatusParagraphs status_db(std::move(pghs)); // a1 was added as a default feature and should be installed in upgrade - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}, {"a1"}); Dependencies::MapPortFileProvider provider(spec_map.map); @@ -1083,7 +1141,7 @@ namespace UnitTest1 pghs.push_back(make_status_feature_pgh("a", "a2", "a[a1]")); StatusParagraphs status_db(std::move(pghs)); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a", "", {{"a1", ""}, {"a2", "a[a1]"}}); Dependencies::MapPortFileProvider provider(spec_map.map); @@ -1112,7 +1170,7 @@ namespace UnitTest1 pghs.push_back(make_status_pgh("a")); StatusParagraphs status_db(std::move(pghs)); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a"); auto plan = Dependencies::create_export_plan({spec_a}, status_db); @@ -1129,7 +1187,7 @@ namespace UnitTest1 pghs.push_back(make_status_pgh("b", "a")); StatusParagraphs status_db(std::move(pghs)); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a"); auto spec_b = spec_map.emplace("b", "a"); @@ -1150,7 +1208,7 @@ namespace UnitTest1 pghs.push_back(make_status_pgh("b")); StatusParagraphs status_db(std::move(pghs)); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a"); auto spec_b = spec_map.emplace("b", "a"); @@ -1165,7 +1223,7 @@ namespace UnitTest1 { StatusParagraphs status_db; - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a"); auto plan = Dependencies::create_export_plan({spec_a}, status_db); @@ -1183,7 +1241,7 @@ namespace UnitTest1 pghs.push_back(make_status_feature_pgh("a", "a1", "b[core]")); StatusParagraphs status_db(std::move(pghs)); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + PackageSpecMap spec_map; auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}); auto plan = Dependencies::create_export_plan({spec_a}, status_db); diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp index 4c4518d25..1bfbc4247 100644 --- a/toolsrc/src/vcpkg/commands.list.cpp +++ b/toolsrc/src/vcpkg/commands.list.cpp @@ -44,14 +44,19 @@ namespace vcpkg::Commands::List const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const StatusParagraphs status_paragraphs = database_load_check(paths); - std::vector installed_packages = get_installed_ports(status_paragraphs); + auto installed_ipv = get_installed_ports(status_paragraphs); - if (installed_packages.empty()) + if (installed_ipv.empty()) { System::println("No packages are installed. Did you mean `search`?"); Checks::exit_success(VCPKG_LINE_INFO); } + auto installed_packages = Util::fmap(installed_ipv, [](const InstalledPackageView& ipv) { return ipv.core; }); + auto installed_features = + Util::fmap_flatten(installed_ipv, [](const InstalledPackageView& ipv) { return ipv.features; }); + installed_packages.insert(installed_packages.end(), installed_features.begin(), installed_features.end()); + std::sort(installed_packages.begin(), installed_packages.end(), [](const StatusParagraph* lhs, const StatusParagraph* rhs) -> bool { diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index f6d81c973..a8bc901a0 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -13,11 +13,17 @@ namespace vcpkg::Dependencies { - struct FeatureNodeEdges + struct ClusterInstalled { - std::vector remove_edges; - std::vector build_edges; - bool plus = false; + InstalledPackageView ipv; + std::set remove_edges; + std::set original_features; + }; + + struct ClusterSource + { + const SourceControlFile* scf; + std::unordered_map> build_edges; }; /// @@ -25,14 +31,15 @@ namespace vcpkg::Dependencies /// struct Cluster : Util::MoveOnlyBase { - InstalledPackageView installed_package; - - Optional source_control_file; PackageSpec spec; - std::unordered_map edges_by_feature; + + Optional installed; + Optional source; + + // Note: this map can contain "special" strings such as "" and "*" + std::unordered_map plus; std::set to_install_features; - std::set original_features; - bool will_remove = false; + bool minus = false; bool transient_uninstalled = true; RequestType request_type = RequestType::AUTO_SELECTED; }; @@ -88,27 +95,26 @@ namespace vcpkg::Dependencies auto maybe_scf = m_provider.get_control_file(spec.name()); auto& clust = m_graph[spec]; clust.spec = spec; - if (auto p_scf = maybe_scf.get()) cluster_from_scf(*p_scf, clust); + if (auto p_scf = maybe_scf.get()) + { + clust.source = cluster_from_scf(*p_scf, clust.spec.triplet()); + } return clust; } return it->second; } private: - void cluster_from_scf(const SourceControlFile& scf, Cluster& out_cluster) const + static ClusterSource cluster_from_scf(const SourceControlFile& scf, Triplet t) { - FeatureNodeEdges core_dependencies; - core_dependencies.build_edges = - filter_dependencies_to_specs(scf.core_paragraph->depends, out_cluster.spec.triplet()); - out_cluster.edges_by_feature.emplace("core", std::move(core_dependencies)); + ClusterSource ret; + ret.build_edges.emplace("core", filter_dependencies_to_specs(scf.core_paragraph->depends, t)); for (const auto& feature : scf.feature_paragraphs) - { - FeatureNodeEdges added_edges; - added_edges.build_edges = filter_dependencies_to_specs(feature->depends, out_cluster.spec.triplet()); - out_cluster.edges_by_feature.emplace(feature->name, std::move(added_edges)); - } - out_cluster.source_control_file = &scf; + ret.build_edges.emplace(feature->name, filter_dependencies_to_specs(feature->depends, t)); + + ret.scf = &scf; + return ret; } std::unordered_map m_graph; @@ -155,11 +161,10 @@ namespace vcpkg::Dependencies { } - InstallPlanAction::InstallPlanAction(const PackageSpec& spec, - InstalledPackageView&& ipv, + InstallPlanAction::InstallPlanAction(InstalledPackageView&& ipv, const std::set& features, const RequestType& request_type) - : spec(spec) + : spec(ipv.spec()) , installed_package(std::move(ipv)) , plan_type(InstallPlanType::ALREADY_INSTALLED) , request_type(request_type) @@ -289,11 +294,11 @@ namespace vcpkg::Dependencies struct RemoveAdjacencyProvider final : Graphs::AdjacencyProvider { const StatusParagraphs& status_db; - const std::vector& installed_ports; + const std::vector& installed_ports; const std::unordered_set& specs_as_set; RemoveAdjacencyProvider(const StatusParagraphs& status_db, - const std::vector& installed_ports, + const std::vector& installed_ports, const std::unordered_set& specs_as_set) : status_db(status_db), installed_ports(installed_ports), specs_as_set(specs_as_set) { @@ -308,24 +313,13 @@ namespace vcpkg::Dependencies const PackageSpec& spec = plan.spec; std::vector dependents; - for (const StatusParagraph* an_installed_package : installed_ports) + for (auto&& ipv : installed_ports) { - if (an_installed_package->package.spec.triplet() != spec.triplet()) continue; + auto deps = ipv.dependencies(); - std::vector deps = an_installed_package->package.depends; - // - // This is a hack to work around existing installations that put featurespecs into binary packages - // (example: curl[core]) Eventually, this can be returned to a simple string search. - for (auto&& dep : deps) - { - dep.erase(std::find(dep.begin(), dep.end(), '['), dep.end()); - } - Util::unstable_keep_if(deps, - [&](auto&& e) { return e != an_installed_package->package.spec.name(); }); - // - if (std::find(deps.begin(), deps.end(), spec.name()) == deps.end()) continue; + if (std::find(deps.begin(), deps.end(), spec) == deps.end()) continue; - dependents.push_back(an_installed_package->package.spec); + dependents.push_back(ipv.spec()); } return dependents; @@ -347,7 +341,7 @@ namespace vcpkg::Dependencies std::string to_string(const PackageSpec& spec) const override { return spec.to_string(); } }; - const std::vector& installed_ports = get_installed_ports(status_db); + auto installed_ports = get_installed_ports(status_db); const std::unordered_set specs_as_set(specs.cbegin(), specs.cend()); return Graphs::topological_sort(specs, RemoveAdjacencyProvider{status_db, installed_ports, specs_as_set}); } @@ -405,161 +399,201 @@ namespace vcpkg::Dependencies Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan, - const std::unordered_set& prevent_default_features = {}); + const std::unordered_set& prevent_default_features); - static void mark_minus(Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan); + static void mark_minus(Cluster& cluster, + ClusterGraph& graph, + GraphPlan& graph_plan, + const std::unordered_set& prevent_default_features); - MarkPlusResult mark_plus(const std::string& feature, - Cluster& cluster, - ClusterGraph& graph, - GraphPlan& graph_plan, - const std::unordered_set& prevent_default_features) + static MarkPlusResult follow_plus_dependencies(const std::string& feature, + Cluster& cluster, + ClusterGraph& graph, + GraphPlan& graph_plan, + const std::unordered_set& prevent_default_features) { - if (feature.empty()) + if (auto p_source = cluster.source.get()) { - if (prevent_default_features.find(cluster.spec.name()) == prevent_default_features.end()) + auto it_build_edges = p_source->build_edges.find(feature); + if (it_build_edges != p_source->build_edges.end()) { - // Indicates that core was not specified in the reference + // mark this package for rebuilding if needed + mark_minus(cluster, graph, graph_plan, prevent_default_features); + + graph_plan.install_graph.add_vertex({&cluster}); + cluster.to_install_features.insert(feature); - // Add default features for this package, if this is the "core" feature and we - // are not supposed to prevent default features for this package - if (auto scf = cluster.source_control_file.value_or(nullptr)) + if (feature != "core") { - for (auto&& default_feature : scf->core_paragraph.get()->default_features) - { - auto res = mark_plus(default_feature, cluster, graph, graph_plan, prevent_default_features); - if (res != MarkPlusResult::SUCCESS) - { - return res; - } - } + // All features implicitly depend on core + auto res = mark_plus("core", cluster, graph, graph_plan, prevent_default_features); + + // Should be impossible for "core" to not exist + Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS); } - // "core" is always an implicit default feature. In case we did not add it as - // a dependency above (e.g. no default features), add it here. - auto res = mark_plus("core", cluster, graph, graph_plan, prevent_default_features); - if (res != MarkPlusResult::SUCCESS) + if (!cluster.installed.get() && !Util::Sets::contains(prevent_default_features, cluster.spec.name())) { - return res; + // Add the default features of this package if it was not previously installed and it isn't being + // suppressed. + auto res = mark_plus("", cluster, graph, graph_plan, prevent_default_features); + + Checks::check_exit(VCPKG_LINE_INFO, + res == MarkPlusResult::SUCCESS, + "Error: Unable to satisfy default dependencies of %s", + cluster.spec); + } + + for (auto&& depend : it_build_edges->second) + { + auto& depend_cluster = graph.get(depend.spec()); + auto res = mark_plus(depend.feature(), depend_cluster, graph, graph_plan, prevent_default_features); + + Checks::check_exit(VCPKG_LINE_INFO, + res == MarkPlusResult::SUCCESS, + "Error: Unable to satisfy dependency %s of %s", + depend, + FeatureSpec(cluster.spec, feature)); + + if (&depend_cluster == &cluster) continue; + graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); } - return MarkPlusResult::SUCCESS; - } - else - { - // Skip adding the default features, as explicitly told not to. return MarkPlusResult::SUCCESS; } } - auto it = cluster.edges_by_feature.find(feature); - if (it == cluster.edges_by_feature.end()) return MarkPlusResult::FEATURE_NOT_FOUND; + // The feature was not available in the installed package nor the source paragraph. + return MarkPlusResult::FEATURE_NOT_FOUND; + } - if (cluster.edges_by_feature[feature].plus) return MarkPlusResult::SUCCESS; + MarkPlusResult mark_plus(const std::string& feature, + Cluster& cluster, + ClusterGraph& graph, + GraphPlan& graph_plan, + const std::unordered_set& prevent_default_features) + { + auto& plus = cluster.plus[feature]; + if (plus) return MarkPlusResult::SUCCESS; + plus = true; - if (cluster.original_features.find(feature) == cluster.original_features.end()) + if (feature.empty()) { - cluster.transient_uninstalled = true; - } + // Add default features for this package. This is an exact reference, so ignore prevent_default_features. + if (auto p_source = cluster.source.get()) + { + for (auto&& default_feature : p_source->scf->core_paragraph.get()->default_features) + { + auto res = mark_plus(default_feature, cluster, graph, graph_plan, prevent_default_features); + if (res != MarkPlusResult::SUCCESS) + { + return res; + } + } + } + else + { + Checks::exit_with_message(VCPKG_LINE_INFO, + "Error: Unable to install default features because can't find CONTROL for %s", + cluster.spec); + } - if (!cluster.transient_uninstalled) - { - return MarkPlusResult::SUCCESS; + // "core" is always required. + return mark_plus("core", cluster, graph, graph_plan, prevent_default_features); } - cluster.edges_by_feature[feature].plus = true; - if (!cluster.original_features.empty()) + if (feature == "*") { - mark_minus(cluster, graph, graph_plan); - } + if (auto p_source = cluster.source.get()) + { + for (auto&& feature : p_source->scf->feature_paragraphs) + { + auto res = mark_plus(feature->name, cluster, graph, graph_plan, prevent_default_features); - graph_plan.install_graph.add_vertex({&cluster}); - auto& tracked = cluster.to_install_features; - tracked.insert(feature); + Checks::check_exit(VCPKG_LINE_INFO, + res == MarkPlusResult::SUCCESS, + "Error: Unable to locate feature %s in %s", + feature->name, + cluster.spec); + } - if (feature != "core") - { - // All features implicitly depend on core - auto res = mark_plus("core", cluster, graph, graph_plan, prevent_default_features); + auto res = mark_plus("core", cluster, graph, graph_plan, prevent_default_features); - // Should be impossible for "core" to not exist - Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS); - } - else - { - // Add the default features of this package. - auto res = mark_plus("", cluster, graph, graph_plan, prevent_default_features); + Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS); + } + else + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "Error: Unable to handle '*' because can't find CONTROL for %s", cluster.spec); + } + return MarkPlusResult::SUCCESS; } - for (auto&& depend : cluster.edges_by_feature[feature].build_edges) + if (auto p_installed = cluster.installed.get()) { - auto& depend_cluster = graph.get(depend.spec()); - auto res = mark_plus(depend.feature(), depend_cluster, graph, graph_plan, prevent_default_features); - - Checks::check_exit(VCPKG_LINE_INFO, - res == MarkPlusResult::SUCCESS, - "Error: Unable to satisfy dependency %s of %s", - depend, - FeatureSpec(cluster.spec, feature)); - - if (&depend_cluster == &cluster) continue; - graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); + if (p_installed->original_features.find(feature) != p_installed->original_features.end()) + { + return MarkPlusResult::SUCCESS; + } } - return MarkPlusResult::SUCCESS; + // This feature was or will be uninstalled, therefore we need to rebuild + mark_minus(cluster, graph, graph_plan, prevent_default_features); + + return follow_plus_dependencies(feature, cluster, graph, graph_plan, prevent_default_features); } - void mark_minus(Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) + void mark_minus(Cluster& cluster, + ClusterGraph& graph, + GraphPlan& graph_plan, + const std::unordered_set& prevent_default_features) { - if (cluster.will_remove) return; - cluster.will_remove = true; - - std::unordered_set prevent_default_features; + if (cluster.minus) return; + cluster.minus = true; + cluster.transient_uninstalled = true; - if (cluster.request_type == RequestType::USER_REQUESTED) - { - // Do not install default features for packages which the user - // installed explicitly. New default features for dependent - // clusters should still be upgraded. - prevent_default_features.insert(cluster.spec.name()); + auto p_installed = cluster.installed.get(); + auto p_source = cluster.source.get(); - // For dependent packages this is handles through the recursion - } + Checks::check_exit( + VCPKG_LINE_INFO, + p_source, + "Error: cannot locate new portfile for %s. Please explicitly remove this package with `vcpkg remove %s`.", + cluster.spec, + cluster.spec); - graph_plan.remove_graph.add_vertex({&cluster}); - for (auto&& pair : cluster.edges_by_feature) + if (p_installed) { - auto& remove_edges_edges = pair.second.remove_edges; - for (auto&& depend : remove_edges_edges) + graph_plan.remove_graph.add_vertex({&cluster}); + for (auto&& edge : p_installed->remove_edges) { - auto& depend_cluster = graph.get(depend.spec()); - if (&depend_cluster != &cluster) graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); - mark_minus(depend_cluster, graph, graph_plan); + auto& depend_cluster = graph.get(edge); + Checks::check_exit(VCPKG_LINE_INFO, &cluster != &depend_cluster); + graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); + mark_minus(depend_cluster, graph, graph_plan, prevent_default_features); } - } - cluster.transient_uninstalled = true; - for (auto&& original_feature : cluster.original_features) - { - auto res = mark_plus(original_feature, cluster, graph, graph_plan, prevent_default_features); - if (res != MarkPlusResult::SUCCESS) + // Reinstall all original features. Don't use mark_plus because it will ignore them since they are + // "already installed". + for (auto&& f : p_installed->original_features) { - System::println(System::Color::warning, - "Warning: could not reinstall feature %s", - FeatureSpec{cluster.spec, original_feature}); + auto res = follow_plus_dependencies(f, cluster, graph, graph_plan, prevent_default_features); + if (res != MarkPlusResult::SUCCESS) + { + System::println(System::Color::warning, + "Warning: could not reinstall feature %s", + FeatureSpec{cluster.spec, f}); + } } - } - // Check if any default features have been added - if (auto scf = cluster.source_control_file.value_or(nullptr)) - { - auto& previous_df = cluster.installed_package.core->package.default_features; - for (auto&& default_feature : scf->core_paragraph->default_features) + // Check if any default features have been added + auto& previous_df = p_installed->ipv.core->package.default_features; + for (auto&& default_feature : p_source->scf->core_paragraph->default_features) { if (std::find(previous_df.begin(), previous_df.end(), default_feature) == previous_df.end()) { - // this is a new default feature, mark it for installation - auto res = mark_plus(default_feature, cluster, graph, graph_plan); + // This is a new default feature, mark it for installation + auto res = mark_plus(default_feature, cluster, graph, graph_plan, prevent_default_features); if (res != MarkPlusResult::SUCCESS) { System::println(System::Color::warning, @@ -588,7 +622,11 @@ namespace vcpkg::Dependencies PackageGraph pgraph(provider, status_db); for (auto&& spec : specs) + { + // If preventing default features, ignore the automatically generated "" references + if (spec.feature().empty() && Util::Sets::contains(prevent_default_features, spec.name())) continue; pgraph.install(spec, prevent_default_features); + } return pgraph.serialize(); } @@ -614,37 +652,10 @@ namespace vcpkg::Dependencies { Cluster& spec_cluster = m_graph->get(spec.spec()); spec_cluster.request_type = RequestType::USER_REQUESTED; - if (spec.feature() == "*") - { - if (auto p_scf = spec_cluster.source_control_file.value_or(nullptr)) - { - for (auto&& feature : p_scf->feature_paragraphs) - { - auto res = - mark_plus(feature->name, spec_cluster, *m_graph, *m_graph_plan, prevent_default_features); - - Checks::check_exit( - VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); - } - - auto res = mark_plus("core", spec_cluster, *m_graph, *m_graph_plan, prevent_default_features); - Checks::check_exit( - VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); - } - else - { - Checks::exit_with_message( - VCPKG_LINE_INFO, "Error: Unable to handle '*' because can't find CONTROL for %s", spec.spec()); - } - } - else - { - auto res = mark_plus(spec.feature(), spec_cluster, *m_graph, *m_graph_plan, prevent_default_features); + auto res = mark_plus(spec.feature(), spec_cluster, *m_graph, *m_graph_plan, prevent_default_features); - Checks::check_exit( - VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); - } + Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); m_graph_plan->install_graph.add_vertex(ClusterPtr{&spec_cluster}); } @@ -654,7 +665,7 @@ namespace vcpkg::Dependencies Cluster& spec_cluster = m_graph->get(spec); spec_cluster.request_type = RequestType::USER_REQUESTED; - mark_minus(spec_cluster, *m_graph, *m_graph_plan); + mark_minus(spec_cluster, *m_graph, *m_graph_plan, {}); } std::vector PackageGraph::serialize() const @@ -669,11 +680,8 @@ namespace vcpkg::Dependencies for (auto&& p_cluster : remove_toposort) { - auto scf = *p_cluster->source_control_file.get(); - auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, p_cluster->spec.triplet()) - .value_or_exit(VCPKG_LINE_INFO); plan.emplace_back(RemovePlanAction{ - std::move(spec), + std::move(p_cluster->spec), RemovePlanType::REMOVE, p_cluster->request_type, }); @@ -684,8 +692,7 @@ namespace vcpkg::Dependencies if (p_cluster->transient_uninstalled) { // If it will be transiently uninstalled, we need to issue a full installation command - auto pscf = p_cluster->source_control_file.value_or_exit(VCPKG_LINE_INFO); - Checks::check_exit(VCPKG_LINE_INFO, pscf != nullptr); + auto pscf = p_cluster->source.value_or_exit(VCPKG_LINE_INFO).scf; auto dep_specs = Util::fmap(m_graph_plan->install_graph.adjacency_list(p_cluster), [](ClusterPtr const& p) { return p->spec; }); @@ -703,10 +710,10 @@ namespace vcpkg::Dependencies { // If the package isn't transitively installed, still include it if the user explicitly requested it if (p_cluster->request_type != RequestType::USER_REQUESTED) continue; + auto&& installed = p_cluster->installed.value_or_exit(VCPKG_LINE_INFO); plan.emplace_back(InstallPlanAction{ - p_cluster->spec, - InstalledPackageView{p_cluster->installed_package}, - p_cluster->original_features, + InstalledPackageView{installed.ipv}, + installed.original_features, p_cluster->request_type, }); } @@ -722,44 +729,36 @@ namespace vcpkg::Dependencies auto installed_ports = get_installed_ports(status_db); - for (auto&& status_paragraph : installed_ports) + for (auto&& ipv : installed_ports) { - Cluster& cluster = graph->get(status_paragraph->package.spec); + Cluster& cluster = graph->get(ipv.spec()); cluster.transient_uninstalled = false; - auto& status_paragraph_feature = status_paragraph->package.feature; - - // In this case, empty string indicates the "core" paragraph for a package. - if (status_paragraph_feature.empty()) - { - cluster.original_features.insert("core"); - cluster.installed_package.core = status_paragraph; - } - else - { - cluster.original_features.insert(status_paragraph_feature); - cluster.installed_package.features.emplace_back(status_paragraph); - } + cluster.installed = [](const InstalledPackageView& ipv) -> ClusterInstalled { + ClusterInstalled ret; + ret.ipv = ipv; + ret.original_features.emplace("core"); + for (auto&& feature : ipv.features) + ret.original_features.emplace(feature->package.feature); + return ret; + }(ipv); } // Populate the graph with "remove edges", which are the reverse of the Build-Depends edges. - for (auto&& status_paragraph : installed_ports) + for (auto&& ipv : installed_ports) { - auto& spec = status_paragraph->package.spec; - auto& status_paragraph_feature = status_paragraph->package.feature; - auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, - status_paragraph->package.spec.triplet()); + auto deps = ipv.dependencies(); - for (auto&& dependency : reverse_edges) + for (auto&& dep : deps) { - auto& dep_cluster = graph->get(dependency.spec()); - - auto depends_name = dependency.feature(); - if (depends_name.empty()) depends_name = "core"; - - auto& target_node = dep_cluster.edges_by_feature[depends_name]; - target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); + auto p_installed = graph->get(dep).installed.get(); + Checks::check_exit(VCPKG_LINE_INFO, + p_installed, + "Error: database corrupted. Package %s is installed but dependency %s is not.", + ipv.spec(), + dep); + p_installed->remove_edges.emplace(ipv.spec()); } } return graph; diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 32433b234..13cc9325e 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -201,9 +201,9 @@ namespace vcpkg::Remove static std::vector valid_arguments(const VcpkgPaths& paths) { const StatusParagraphs status_db = database_load_check(paths); - const std::vector installed_packages = get_installed_ports(status_db); + auto installed_packages = get_installed_ports(status_db); - return Util::fmap(installed_packages, [](auto&& pgh) -> std::string { return pgh->package.spec.to_string(); }); + return Util::fmap(installed_packages, [](auto&& pgh) -> std::string { return pgh.spec().to_string(); }); } const CommandStructure COMMAND_STRUCTURE = { diff --git a/toolsrc/src/vcpkg/statusparagraph.cpp b/toolsrc/src/vcpkg/statusparagraph.cpp index 62d1d4b42..236689494 100644 --- a/toolsrc/src/vcpkg/statusparagraph.cpp +++ b/toolsrc/src/vcpkg/statusparagraph.cpp @@ -95,7 +95,7 @@ namespace vcpkg // Add the core paragraph dependencies to the list deps.insert(deps.end(), core->package.depends.begin(), core->package.depends.end()); - auto&& spec = core->package.spec; + auto&& l_spec = spec(); // // This is a hack to work around existing installations that put featurespecs into binary packages @@ -104,12 +104,12 @@ namespace vcpkg { dep.erase(std::find(dep.begin(), dep.end(), '['), dep.end()); } - Util::unstable_keep_if(deps, [&](auto&& e) { return e != spec.name(); }); + Util::unstable_keep_if(deps, [&](auto&& e) { return e != l_spec.name(); }); // Util::sort_unique_erase(deps); return Util::fmap(deps, [&](const std::string& dep) -> PackageSpec { - auto maybe_dependency_spec = PackageSpec::from_name_and_triplet(dep, spec.triplet()); + auto maybe_dependency_spec = PackageSpec::from_name_and_triplet(dep, l_spec.triplet()); if (auto dependency_spec = maybe_dependency_spec.get()) { return std::move(*dependency_spec); @@ -120,7 +120,7 @@ namespace vcpkg "Invalid dependency [%s] in package [%s]\n" "%s", dep, - spec.name(), + l_spec.name(), vcpkg::to_string(error_type)); }); } diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp index d6c5614ed..57259f952 100644 --- a/toolsrc/src/vcpkg/update.cpp +++ b/toolsrc/src/vcpkg/update.cpp @@ -17,17 +17,12 @@ namespace vcpkg::Update std::vector find_outdated_packages(const Dependencies::PortFileProvider& provider, const StatusParagraphs& status_db) { - const std::vector installed_packages = get_installed_ports(status_db); + auto installed_packages = get_installed_ports(status_db); std::vector output; - for (const StatusParagraph* pgh : installed_packages) + for (auto&& ipv : installed_packages) { - if (!pgh->package.feature.empty()) - { - // Skip feature paragraphs; only consider master paragraphs for needing updates. - continue; - } - + const auto& pgh = ipv.core; auto maybe_scf = provider.get_control_file(pgh->package.spec.name()); if (auto p_scf = maybe_scf.get()) { diff --git a/toolsrc/src/vcpkg/vcpkglib.cpp b/toolsrc/src/vcpkg/vcpkglib.cpp index 7979fd9a5..c8e95dab1 100644 --- a/toolsrc/src/vcpkg/vcpkglib.cpp +++ b/toolsrc/src/vcpkg/vcpkglib.cpp @@ -169,16 +169,32 @@ namespace vcpkg fs.rename(updated_listfile_path, listfile_path); } - std::vector get_installed_ports(const StatusParagraphs& status_db) + std::vector get_installed_ports(const StatusParagraphs& status_db) { - std::vector installed_packages; + std::map ipv_map; + + std::vector installed_packages; for (auto&& pgh : status_db) { if (!pgh->is_installed()) continue; - installed_packages.push_back(pgh.get()); + auto& ipv = ipv_map[pgh->package.spec]; + if (pgh->package.feature.empty()) + { + ipv.core = pgh.get(); + } + else + { + ipv.features.emplace_back(pgh.get()); + } } - return installed_packages; + for (auto&& ipv : ipv_map) + Checks::check_exit(VCPKG_LINE_INFO, + ipv.second.core != nullptr, + "Database is corrupted: package %s has features but no core paragraph.", + ipv.first); + + return Util::fmap(ipv_map, [](auto&& p) -> InstalledPackageView { return std::move(p.second); }); } std::vector get_installed_files(const VcpkgPaths& paths, -- cgit v1.2.3 From a2aeb2f1949c42622ccc7f9572a441e2a4475132 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 12 Apr 2018 00:47:17 -0700 Subject: [vcpkg] Mark many types noexcept. Make certain code patterns more transparent to /analyze. #ifdef-out unused code on non-windows. --- toolsrc/src/tests.plan.cpp | 2 +- toolsrc/src/vcpkg.cpp | 2 ++ toolsrc/src/vcpkg/base/cofffilereader.cpp | 7 ++++--- toolsrc/src/vcpkg/base/files.cpp | 17 +++++++++------- toolsrc/src/vcpkg/base/strings.cpp | 14 ++++++++------ toolsrc/src/vcpkg/base/system.cpp | 32 ++++++++++++++----------------- toolsrc/src/vcpkg/binaryparagraph.cpp | 2 +- toolsrc/src/vcpkg/build.cpp | 14 ++++++-------- toolsrc/src/vcpkg/commands.ci.cpp | 7 ++----- toolsrc/src/vcpkg/commands.edit.cpp | 5 +++-- toolsrc/src/vcpkg/commands.fetch.cpp | 5 ++--- toolsrc/src/vcpkg/commands.hash.cpp | 11 +++++++---- toolsrc/src/vcpkg/commands.integrate.cpp | 21 +++++++++++++++++++- toolsrc/src/vcpkg/dependencies.cpp | 25 +++++++++++++++++------- toolsrc/src/vcpkg/export.cpp | 12 ++++++------ toolsrc/src/vcpkg/metrics.cpp | 6 ------ toolsrc/src/vcpkg/postbuildlint.cpp | 8 ++++++-- toolsrc/src/vcpkg/statusparagraph.cpp | 3 ++- toolsrc/src/vcpkg/versiont.cpp | 4 ++-- 19 files changed, 114 insertions(+), 83 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index b054702a1..238aa7032 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -81,7 +81,7 @@ namespace UnitTest1 { std::unordered_map map; Triplet triplet; - PackageSpecMap(const Triplet& t = Triplet::X86_WINDOWS) { triplet = t; } + PackageSpecMap(const Triplet& t = Triplet::X86_WINDOWS) noexcept { triplet = t; } PackageSpec emplace(const char* name, const char* depends = "", diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index a65045aa8..06c99e9a8 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -223,6 +223,7 @@ static void load_config() } } +#if defined(_WIN32) static std::string trim_path_from_command_line(const std::string& full_command_line) { Checks::check_exit( @@ -243,6 +244,7 @@ static std::string trim_path_from_command_line(const std::string& full_command_l ++it; return std::string(it, full_command_line.cend()); } +#endif #if defined(_WIN32) int wmain(const int argc, const wchar_t* const* const argv) diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp index 5b06a885c..fca0b627e 100644 --- a/toolsrc/src/vcpkg/base/cofffilereader.cpp +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -148,17 +148,18 @@ namespace vcpkg::CoffFileReader { static OffsetsArray read(fstream& fs, const uint32_t offset_count) { - static constexpr size_t OFFSET_WIDTH = 4; + static constexpr uint32_t OFFSET_WIDTH = 4; std::string raw_offsets; - const size_t raw_offset_size = offset_count * OFFSET_WIDTH; + const uint32_t raw_offset_size = offset_count * OFFSET_WIDTH; raw_offsets.resize(raw_offset_size); fs.read(&raw_offsets[0], raw_offset_size); OffsetsArray ret; for (uint32_t i = 0; i < offset_count; ++i) { - const std::string value_as_string = raw_offsets.substr(OFFSET_WIDTH * i, OFFSET_WIDTH * (i + 1)); + const std::string value_as_string = raw_offsets.substr(OFFSET_WIDTH * static_cast(i), + OFFSET_WIDTH * (static_cast(i) + 1)); const auto value = reinterpret_bytes(value_as_string.c_str()); // Ignore offsets that point to offset 0. See vcpkg github #223 #288 #292 diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 4e61666b7..1723b467e 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -22,9 +22,9 @@ namespace vcpkg::Files auto length = file_stream.tellg(); file_stream.seekg(0, file_stream.beg); - if (length > SIZE_MAX) + if (length == std::streampos(-1)) { - return std::make_error_code(std::errc::file_too_large); + return std::make_error_code(std::errc::io_error); } std::string output; @@ -185,12 +185,15 @@ namespace vcpkg::Files return; } - auto count = fwrite(data.data(), sizeof(data[0]), data.size(), f); - fclose(f); - - if (count != data.size()) + if (f != nullptr) { - ec = std::make_error_code(std::errc::no_space_on_device); + auto count = fwrite(data.data(), sizeof(data[0]), data.size(), f); + fclose(f); + + if (count != data.size()) + { + ec = std::make_error_code(std::errc::no_space_on_device); + } } } }; diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index 541b1f2d9..fbc33ca42 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -39,7 +39,7 @@ namespace vcpkg::Strings::details _vsnprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args); #else va_start(args, fmtstr); - auto res = vsnprintf(&output.at(0), output.size() + 1, fmtstr, args); + vsnprintf(&output.at(0), output.size() + 1, fmtstr, args); #endif va_end(args); @@ -52,23 +52,25 @@ namespace vcpkg::Strings std::wstring to_utf16(const CStringView& s) { #if defined(_WIN32) - const int size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0); std::wstring output; + const size_t size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0); + if (size == 0) return output; output.resize(size - 1); - MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, output.data(), size - 1); + MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, output.data(), static_cast(size) - 1); return output; #else Checks::unreachable(VCPKG_LINE_INFO); #endif } - std::string to_utf8(const CWStringView& w) + std::string to_utf8(const wchar_t* w) { #if defined(_WIN32) - const int size = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr); std::string output; + const size_t size = WideCharToMultiByte(CP_UTF8, 0, w, -1, nullptr, 0, nullptr, nullptr); + if (size == 0) return output; output.resize(size - 1); - WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, output.data(), size - 1, nullptr, nullptr); + WideCharToMultiByte(CP_UTF8, 0, w, -1, output.data(), static_cast(size) - 1, nullptr, nullptr); return output; #else Checks::unreachable(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 3f2f47d72..d4210fe6d 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -214,7 +214,7 @@ namespace vcpkg::System for (auto&& env_wstring : env_wstrings) { - const Optional value = System::get_environment_variable(Strings::to_utf8(env_wstring)); + const Optional value = System::get_environment_variable(Strings::to_utf8(env_wstring.c_str())); const auto v = value.get(); if (!v || v->empty()) continue; @@ -298,17 +298,6 @@ namespace vcpkg::System return exit_code; } - // On Win7, output from powershell calls contain a byte order mark, so we strip it out if it is present - static void remove_byte_order_marks(std::wstring* s) - { - const wchar_t* a = s->c_str(); - // This is the UTF-8 byte-order mark - while (s->size() >= 3 && a[0] == 0xEF && a[1] == 0xBB && a[2] == 0xBF) - { - s->erase(0, 3); - } - } - ExitCodeAndOutput cmd_execute_and_capture_output(const CStringView cmd_line) { // Flush stdout before launching external process @@ -325,7 +314,7 @@ namespace vcpkg::System const auto pipe = _wpopen(Strings::to_utf16(actual_cmd_line).c_str(), L"r"); if (pipe == nullptr) { - return {1, Strings::to_utf8(output)}; + return {1, Strings::to_utf8(output.c_str())}; } while (fgetws(buf, 1024, pipe)) { @@ -333,15 +322,22 @@ namespace vcpkg::System } if (!feof(pipe)) { - return {1, Strings::to_utf8(output)}; + return {1, Strings::to_utf8(output.c_str())}; } const auto ec = _pclose(pipe); - remove_byte_order_marks(&output); + + // On Win7, output from powershell calls contain a utf-8 byte order mark in the utf-16 stream, so we strip it + // out if it is present. 0xEF,0xBB,0xBF is the UTF-8 byte-order mark + const wchar_t* a = output.c_str(); + while (output.size() >= 3 && a[0] == 0xEF && a[1] == 0xBB && a[2] == 0xBF) + { + output.erase(0, 3); + } Debug::println("_pclose() returned %d after %8d us", ec, static_cast(timer.microseconds())); - return {ec, Strings::to_utf8(output)}; + return {ec, Strings::to_utf8(output.c_str())}; #else const auto actual_cmd_line = Strings::format(R"###(%s 2>&1)###", cmd_line); @@ -481,7 +477,7 @@ namespace vcpkg::System const auto sz2 = GetEnvironmentVariableW(w_varname.c_str(), ret.data(), static_cast(ret.size())); Checks::check_exit(VCPKG_LINE_INFO, sz2 + 1 == sz); ret.pop_back(); - return Strings::to_utf8(ret); + return Strings::to_utf8(ret.c_str()); #else auto v = getenv(varname.c_str()); if (!v) return nullopt; @@ -522,7 +518,7 @@ namespace vcpkg::System return nullopt; ret.pop_back(); // remove extra trailing null byte - return Strings::to_utf8(ret); + return Strings::to_utf8(ret.c_str()); } #else Optional get_registry_string(void* base_hkey, const CStringView sub_key, const CStringView valuename) diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp index 73ca23df1..126c7df97 100644 --- a/toolsrc/src/vcpkg/binaryparagraph.cpp +++ b/toolsrc/src/vcpkg/binaryparagraph.cpp @@ -24,7 +24,7 @@ namespace vcpkg static const std::string DEFAULTFEATURES = "Default-Features"; } - BinaryParagraph::BinaryParagraph() = default; + BinaryParagraph::BinaryParagraph() noexcept = default; BinaryParagraph::BinaryParagraph(std::unordered_map fields) { diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 76381f862..7a9d35667 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -330,8 +330,7 @@ namespace vcpkg::Build const PreBuildInfo& pre_build_info, const PackageSpec& spec, const std::string& abi_tag, - const BuildPackageConfig& config, - const StatusParagraphs& status_db) + const BuildPackageConfig& config) { auto& fs = paths.get_filesystem(); const Triplet& triplet = spec.triplet(); @@ -419,10 +418,9 @@ namespace vcpkg::Build const PreBuildInfo& pre_build_info, const PackageSpec& spec, const std::string& abi_tag, - const BuildPackageConfig& config, - const StatusParagraphs& status_db) + const BuildPackageConfig& config) { - auto result = do_build_package(paths, pre_build_info, spec, abi_tag, config, status_db); + auto result = do_build_package(paths, pre_build_info, spec, abi_tag, config); if (config.build_package_options.clean_buildtrees == CleanBuildtrees::YES) { @@ -564,7 +562,7 @@ namespace vcpkg::Build auto dep_pspecs = Util::fmap(required_fspecs, [](FeatureSpec const& fspec) { return fspec.spec(); }); Util::sort_unique_erase(dep_pspecs); - // Find all features that aren't installed. This destroys required_fspecs. + // Find all features that aren't installed. This mutates required_fspecs. Util::unstable_keep_if(required_fspecs, [&](FeatureSpec const& fspec) { return !status_db.is_installed(fspec) && fspec.name() != name; }); @@ -624,7 +622,7 @@ namespace vcpkg::Build System::println("Could not locate cached archive: %s", archive_path.u8string()); ExtendedBuildResult result = do_build_package_and_clean_buildtrees( - paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); + paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config); std::error_code ec; fs.create_directories(paths.package_dir(spec) / "share" / spec.name(), ec); @@ -657,7 +655,7 @@ namespace vcpkg::Build } return do_build_package_and_clean_buildtrees( - paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); + paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config); } const std::string& to_string(const BuildResult build_result) diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 45eb1c83e..04b42ea00 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -77,11 +77,8 @@ namespace vcpkg::Commands::CI { auto triplet = p->spec.triplet(); - const Build::BuildPackageConfig build_config{p->source_control_file.value_or_exit(VCPKG_LINE_INFO), - triplet, - paths.port_dir(p->spec), - install_plan_options, - p->feature_list}; + const Build::BuildPackageConfig build_config{ + *scf, triplet, paths.port_dir(p->spec), install_plan_options, p->feature_list}; auto dependency_abis = Util::fmap(p->computed_dependencies, [&](const PackageSpec& spec) -> Build::AbiEntry { diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index f0ddd43c5..82569dd07 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -9,14 +9,15 @@ namespace vcpkg::Commands::Edit { static std::vector find_from_registry() { + std::vector output; + +#if defined(_WIN32) static const std::array REGKEYS = { R"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1)", R"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", }; - std::vector output; -#if defined(_WIN32) for (auto&& keypath : REGKEYS) { const Optional code_installpath = diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 9652d0b9e..7a1e6a810 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -269,8 +269,6 @@ namespace vcpkg::Commands::Fetch #endif static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data) { - const auto& fs = paths.get_filesystem(); - const fs::path& scripts_folder = paths.scripts; const std::array& version = tool_data.version; const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); @@ -280,7 +278,7 @@ namespace vcpkg::Commands::Fetch tool_name, version_as_string); #if defined(_WIN32) - const fs::path script = scripts_folder / "fetchtool.ps1"; + const fs::path script = paths.scripts / "fetchtool.ps1"; const std::string title = Strings::format( "Fetching %s version %s (No sufficient installed version was found)", tool_name, version_as_string); const System::PowershellParameter tool_param("tool", tool_name); @@ -300,6 +298,7 @@ namespace vcpkg::Commands::Fetch actual_downloaded_path.u8string()); return actual_downloaded_path; #else + const auto& fs = paths.get_filesystem(); if (!fs.exists(tool_data.download_path)) { System::println("Downloading %s...", tool_name); diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index c23a63e1e..1f709f87b 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -127,12 +127,15 @@ namespace vcpkg::Commands::Hash FILE* file = nullptr; const auto ec = _wfopen_s(&file, path.c_str(), L"rb"); Checks::check_exit(VCPKG_LINE_INFO, ec == 0, "Failed to open file: %s", path.u8string()); - unsigned char buffer[4096]; - while (const auto actual_size = fread(buffer, 1, sizeof(buffer), file)) + if (file != nullptr) { - hash_data(hash_handle, buffer, actual_size); + unsigned char buffer[4096]; + while (const auto actual_size = fread(buffer, 1, sizeof(buffer), file)) + { + hash_data(hash_handle, buffer, actual_size); + } + fclose(file); } - fclose(file); return finalize_hash_handle(hash_handle, length_in_bytes); } diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index e70d9b2e3..7061a3984 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -8,6 +8,7 @@ namespace vcpkg::Commands::Integrate { +#if defined(_WIN32) static std::string create_appdata_targets_shortcut(const std::string& target_path) noexcept { return Strings::format(R"###( @@ -18,7 +19,9 @@ namespace vcpkg::Commands::Integrate target_path, target_path); } +#endif +#if defined(_WIN32) static std::string create_system_targets_shortcut() noexcept { return R"###( @@ -31,7 +34,9 @@ namespace vcpkg::Commands::Integrate )###"; } +#endif +#if defined(_WIN32) static std::string create_nuget_targets_file_contents(const fs::path& msbuild_vcpkg_targets_file) noexcept { const std::string as_string = msbuild_vcpkg_targets_file.string(); @@ -47,7 +52,9 @@ namespace vcpkg::Commands::Integrate as_string, as_string); } +#endif +#if defined(_WIN32) static std::string create_nuget_props_file_contents() noexcept { return R"###( @@ -58,7 +65,9 @@ namespace vcpkg::Commands::Integrate )###"; } +#endif +#if defined(_WIN32) static std::string get_nuget_id(const fs::path& vcpkg_root_dir) { std::string dir_id = vcpkg_root_dir.generic_string(); @@ -71,7 +80,9 @@ namespace vcpkg::Commands::Integrate const std::string nuget_id = "vcpkg." + dir_id; return nuget_id; } +#endif +#if defined(_WIN32) static std::string create_nuspec_file_contents(const fs::path& vcpkg_root_dir, const std::string& nuget_id, const std::string& nupkg_version) @@ -98,14 +109,15 @@ namespace vcpkg::Commands::Integrate content = Strings::replace_all(std::move(content), "@VERSION@", nupkg_version); return content; } +#endif +#if defined(_WIN32) enum class ElevationPromptChoice { YES, NO }; -#if defined(_WIN32) static ElevationPromptChoice elevated_cmd_execute(const std::string& param) { SHELLEXECUTEINFOW sh_ex_info{}; @@ -272,6 +284,7 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")", } #endif +#if defined(WIN32) static void integrate_project(const VcpkgPaths& paths) { auto& fs = paths.get_filesystem(); @@ -319,13 +332,19 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console Checks::exit_success(VCPKG_LINE_INFO); } +#endif +#if defined(_WIN32) const char* const INTEGRATE_COMMAND_HELPSTRING = " vcpkg integrate install Make installed packages available user-wide. Requires admin privileges on " "first use\n" " vcpkg integrate remove Remove user-wide integration\n" " vcpkg integrate project Generate a referencing nuget package for individual VS project use\n" " vcpkg integrate powershell Enable PowerShell Tab-Completion\n"; +#else + const char* const INTEGRATE_COMMAND_HELPSTRING = + "No user-wide integration methods are available on this platform\n"; +#endif namespace Subcommand { diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index a8bc901a0..8fb35b0da 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -22,7 +22,7 @@ namespace vcpkg::Dependencies struct ClusterSource { - const SourceControlFile* scf; + const SourceControlFile* scf = nullptr; std::unordered_map> build_edges; }; @@ -145,7 +145,10 @@ namespace vcpkg::Dependencies } } - InstallPlanAction::InstallPlanAction() : plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} + InstallPlanAction::InstallPlanAction() noexcept + : plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN), build_options{} + { + } InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const SourceControlFile& scf, @@ -156,6 +159,7 @@ namespace vcpkg::Dependencies , source_control_file(scf) , plan_type(InstallPlanType::BUILD_AND_INSTALL) , request_type(request_type) + , build_options{} , feature_list(features) , computed_dependencies(std::move(dependencies)) { @@ -168,6 +172,7 @@ namespace vcpkg::Dependencies , installed_package(std::move(ipv)) , plan_type(InstallPlanType::ALREADY_INSTALLED) , request_type(request_type) + , build_options{} , feature_list(features) , computed_dependencies(installed_package.get()->dependencies()) { @@ -189,7 +194,10 @@ namespace vcpkg::Dependencies return left->spec.name() < right->spec.name(); } - RemovePlanAction::RemovePlanAction() : plan_type(RemovePlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} + RemovePlanAction::RemovePlanAction() noexcept + : plan_type(RemovePlanType::UNKNOWN), request_type(RequestType::UNKNOWN) + { + } RemovePlanAction::RemovePlanAction(const PackageSpec& spec, const RemovePlanType& plan_type, @@ -218,7 +226,10 @@ namespace vcpkg::Dependencies return left->spec.name() < right->spec.name(); } - ExportPlanAction::ExportPlanAction() : plan_type(ExportPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} + ExportPlanAction::ExportPlanAction() noexcept + : plan_type(ExportPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) + { + } ExportPlanAction::ExportPlanAction(const PackageSpec& spec, InstalledPackageView&& installed_package, @@ -506,14 +517,14 @@ namespace vcpkg::Dependencies { if (auto p_source = cluster.source.get()) { - for (auto&& feature : p_source->scf->feature_paragraphs) + for (auto&& fpgh : p_source->scf->feature_paragraphs) { - auto res = mark_plus(feature->name, cluster, graph, graph_plan, prevent_default_features); + auto res = mark_plus(fpgh->name, cluster, graph, graph_plan, prevent_default_features); Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s in %s", - feature->name, + fpgh->name, cluster.spec); } diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 85a4dfad1..152252018 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -247,12 +247,12 @@ namespace vcpkg::Export struct ExportArguments { - bool dry_run; - bool raw; - bool nuget; - bool ifw; - bool zip; - bool seven_zip; + bool dry_run = false; + bool raw = false; + bool nuget = false; + bool ifw = false; + bool zip = false; + bool seven_zip = false; Optional maybe_output; diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 4067efc95..8890c067f 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -245,12 +245,6 @@ namespace vcpkg::Metrics bool get_compiled_metrics_enabled() { return DISABLE_METRICS == 0; } - static fs::path get_vcpkg_root() - { - return Files::get_real_filesystem().find_file_recursively_up( - fs::stdfs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root"); - } - std::string get_MAC_user() { #if defined(_WIN32) diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp index a31518ad7..6fe11951f 100644 --- a/toolsrc/src/vcpkg/postbuildlint.cpp +++ b/toolsrc/src/vcpkg/postbuildlint.cpp @@ -361,6 +361,7 @@ namespace vcpkg::PostBuildLint std::string actual_arch; }; +#if defined(_WIN32) static std::string get_actual_architecture(const MachineType& machine_type) { switch (machine_type) @@ -374,7 +375,9 @@ namespace vcpkg::PostBuildLint default: return "Machine Type Code = " + std::to_string(static_cast(machine_type)); } } +#endif +#if defined(_WIN32) static void print_invalid_architecture_files(const std::string& expected_architecture, std::vector binaries_with_invalid_architecture) { @@ -391,7 +394,6 @@ namespace vcpkg::PostBuildLint static LintStatus check_dll_architecture(const std::string& expected_architecture, const std::vector& files) { -#if defined(_WIN32) std::vector binaries_with_invalid_architecture; for (const fs::path& file : files) @@ -414,10 +416,10 @@ namespace vcpkg::PostBuildLint print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture); return LintStatus::ERROR_DETECTED; } -#endif return LintStatus::SUCCESS; } +#endif static LintStatus check_lib_architecture(const std::string& expected_architecture, const std::vector& files) @@ -802,7 +804,9 @@ namespace vcpkg::PostBuildLint check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info, pre_build_info); } +#if defined(_WIN32) error_count += check_dll_architecture(pre_build_info.target_architecture, dlls); +#endif break; } case Build::LinkageType::STATIC: diff --git a/toolsrc/src/vcpkg/statusparagraph.cpp b/toolsrc/src/vcpkg/statusparagraph.cpp index 236689494..462d8d8ed 100644 --- a/toolsrc/src/vcpkg/statusparagraph.cpp +++ b/toolsrc/src/vcpkg/statusparagraph.cpp @@ -12,7 +12,7 @@ namespace vcpkg static const std::string STATUS = "Status"; } - StatusParagraph::StatusParagraph() : want(Want::ERROR_STATE), state(InstallState::ERROR_STATE) {} + StatusParagraph::StatusParagraph() noexcept : want(Want::ERROR_STATE), state(InstallState::ERROR_STATE) {} void serialize(const StatusParagraph& pgh, std::string& out_str) { @@ -25,6 +25,7 @@ namespace vcpkg } StatusParagraph::StatusParagraph(std::unordered_map&& fields) + : want(Want::ERROR_STATE), state(InstallState::ERROR_STATE) { auto status_it = fields.find(BinaryParagraphRequiredField::STATUS); Checks::check_exit(VCPKG_LINE_INFO, status_it != fields.end(), "Expected 'Status' field in status paragraph"); diff --git a/toolsrc/src/vcpkg/versiont.cpp b/toolsrc/src/vcpkg/versiont.cpp index 0d4a39255..d20e6b577 100644 --- a/toolsrc/src/vcpkg/versiont.cpp +++ b/toolsrc/src/vcpkg/versiont.cpp @@ -5,7 +5,7 @@ namespace vcpkg { - VersionT::VersionT() : value("0.0.0") {} + VersionT::VersionT() noexcept : value("0.0.0") {} VersionT::VersionT(std::string&& value) : value(std::move(value)) {} VersionT::VersionT(const std::string& value) : value(value) {} const std::string& VersionT::to_string() const { return value; } @@ -13,7 +13,7 @@ namespace vcpkg bool operator!=(const VersionT& left, const VersionT& right) { return left.to_string() != right.to_string(); } std::string to_printf_arg(const VersionT& version) { return version.to_string(); } - VersionDiff::VersionDiff() : left(), right() {} + VersionDiff::VersionDiff() noexcept : left(), right() {} VersionDiff::VersionDiff(const VersionT& left, const VersionT& right) : left(left), right(right) {} std::string VersionDiff::to_string() const -- cgit v1.2.3 From 5886a48dc7c5be48be3baf73ce2e8e136252aede Mon Sep 17 00:00:00 2001 From: "Billy O'Neal (VC LIBS)" Date: Thu, 12 Apr 2018 15:31:11 -0700 Subject: Remove call to nonexistent member of std::fpos. See http://eel.is/c++draft/fpos -- to get to an offset you can convert to int; there is no seekpos member. --- toolsrc/src/vcpkg/base/cofffilereader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp index fca0b627e..2c09e2c19 100644 --- a/toolsrc/src/vcpkg/base/cofffilereader.cpp +++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp @@ -247,7 +247,7 @@ namespace vcpkg::CoffFileReader { void set_to_offset(const fpos_t position) { this->m_absolute_position = position; } - void set_to_current_pos(fstream& fs) { this->m_absolute_position = fs.tellg().seekpos(); } + void set_to_current_pos(fstream& fs) { this->m_absolute_position = fs.tellg(); } void seek_to_marker(fstream& fs) const { fs.seekg(this->m_absolute_position, ios_base::beg); } -- cgit v1.2.3 From a9b1541fd6d308a17848ab4eb5396598ffa1a240 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Mon, 16 Apr 2018 16:14:50 -0700 Subject: [vcpkg, xml] Parse with string-search instead of regex Resolves issue with inconsistent regex behavior between platforms. For example [/s/S]*? does not properly match on Clang. String-searching is also generally more performant. --- toolsrc/src/vcpkg/commands.fetch.cpp | 83 +++++++++++++++++------------------- 1 file changed, 40 insertions(+), 43 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 7a1e6a810..1e31e6bc4 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -41,6 +41,22 @@ namespace vcpkg::Commands::Fetch return result; } + static Optional extract_string_between_delimiters(const std::string& input, + const std::string& left_delim, + const std::string& right_delim, + const size_t& starting_offset = 0) + { + const size_t from = input.find(left_delim, starting_offset); + if (from == std::string::npos) return nullopt; + + const size_t substring_start = from + left_delim.length(); + + const size_t to = input.find(right_delim, substring_start); + if (from == std::string::npos) return nullopt; + + return input.substr(substring_start, to - substring_start); + } + static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool) { #if defined(_WIN32) @@ -57,33 +73,21 @@ namespace vcpkg::Commands::Fetch static const std::string XML_VERSION = "2"; static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; - const auto maybe_get_string_inside_tags = [](const std::string& input, - const std::regex& regex) -> Optional { - std::smatch match; - const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); - if (!has_match) return nullopt; - return match[1]; - }; - const auto get_string_inside_tags = - [](const std::string& input, const std::regex& regex, const std::string& tag_name) -> std::string { - std::smatch match; - const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); - Checks::check_exit( - VCPKG_LINE_INFO, has_match, "Could not find tag <%s> in %s", tag_name, XML_PATH.generic_string()); + [](const std::string& input, const std::string& left_delim, const std::string& right_delim) -> std::string { + Optional result = extract_string_between_delimiters(input, left_delim, right_delim); + Checks::check_exit(VCPKG_LINE_INFO, + result.has_value(), + "Could not find tag <%s>.*<%s> in %s", + left_delim, + right_delim, + XML_PATH.generic_string()); - return match[1]; + return *result.get(); }; static const std::regex XML_VERSION_REGEX{R"###()###"}; static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO); - static const std::regex VERSION_REGEX{R"###(([\s\S]*?))###"}; - static const std::regex EXE_RELATIVE_PATH_REGEX{ - Strings::format(R"###(([\s\S]*?))###")}; - static const std::regex ARCHIVE_NAME_REGEX{Strings::format(R"###(([\s\S]*?))###")}; - static const std::regex URL_REGEX{Strings::format(R"###(([\s\S]*?))###")}; - static const std::regex SHA512_REGEX{Strings::format(R"###(([\s\S]*?))###")}; - std::smatch match_xml_version; const bool has_xml_version = std::regex_search(XML.cbegin(), XML.cend(), match_xml_version, XML_VERSION_REGEX); Checks::check_exit(VCPKG_LINE_INFO, @@ -98,43 +102,36 @@ namespace vcpkg::Commands::Fetch XML_VERSION, match_xml_version[1]); - const std::regex tool_regex{ - Strings::format(R"###(([\s\S]*?)<\/tool>)###", tool, OS_STRING)}; - - std::smatch match_tool; - const bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); + const std::regex tool_regex{Strings::format(R"###()###", tool, OS_STRING)}; + std::smatch match_tool_entry; + const bool has_tool_entry = std::regex_search(XML.cbegin(), XML.cend(), match_tool_entry, tool_regex); Checks::check_exit(VCPKG_LINE_INFO, - has_match_tool, + has_tool_entry, "Could not find entry for tool [%s] in %s", tool, XML_PATH.generic_string()); - const std::string tool_data_as_string = get_string_inside_tags(XML, tool_regex, tool); - - const std::string required_version_as_string = - get_string_inside_tags(tool_data_as_string, VERSION_REGEX, "version"); - - const std::string url = get_string_inside_tags(tool_data_as_string, URL_REGEX, "url"); + const std::string tool_data = get_string_inside_tags(XML, match_tool_entry[0], R"()"); + const std::string version_as_string = get_string_inside_tags(tool_data, "", R"()"); const std::string exe_relative_path = - get_string_inside_tags(tool_data_as_string, EXE_RELATIVE_PATH_REGEX, "exeRelativePath"); - - auto archive_name = maybe_get_string_inside_tags(tool_data_as_string, ARCHIVE_NAME_REGEX); + get_string_inside_tags(tool_data, "", R"()"); + const std::string url = get_string_inside_tags(tool_data, "", R"()"); + const std::string sha512 = get_string_inside_tags(tool_data, "", R"()"); + auto archive_name = extract_string_between_delimiters(tool_data, "", R"()"); - const Optional> required_version = parse_version_string(required_version_as_string); + const Optional> version = parse_version_string(version_as_string); Checks::check_exit(VCPKG_LINE_INFO, - required_version.has_value(), + version.has_value(), "Could not parse version for tool %s. Version string was: %s", tool, - required_version_as_string); + version_as_string); - const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, required_version_as_string, OS_STRING); + const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, version_as_string, OS_STRING); const fs::path tool_dir_path = paths.downloads / "tools" / tool_dir_name; const fs::path exe_path = tool_dir_path / exe_relative_path; - const std::string sha512 = get_string_inside_tags(tool_data_as_string, SHA512_REGEX, "sha512"); - - return ToolData{*required_version.get(), + return ToolData{*version.get(), exe_path, url, paths.downloads / archive_name.value_or(exe_relative_path), -- cgit v1.2.3 From c3062a7b8d06ea20c2105e8b277ccc76af99a2d2 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 17 Apr 2018 13:45:01 -0700 Subject: Use ~/.vcpkg/config instead of ~/vcpkg/config --- toolsrc/src/vcpkg/userconfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp index 9db2e5d47..574a97b64 100644 --- a/toolsrc/src/vcpkg/userconfig.cpp +++ b/toolsrc/src/vcpkg/userconfig.cpp @@ -35,7 +35,7 @@ namespace vcpkg return get_localappdata() / "vcpkg" / "config"; #else auto maybe_home = System::get_environment_variable("HOME"); - return fs::path(maybe_home.value_or("/var")) / "vcpkg" / "config"; + return fs::path(maybe_home.value_or("/var")) / ".vcpkg" / "config"; #endif } -- cgit v1.2.3 From 8fcb1073abe8611fa24b43f7c1cda0d7404e108e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 18 Apr 2018 18:52:22 -0700 Subject: [vcpkg edit] Now accepts multiple ports as arg --- toolsrc/src/vcpkg/commands.edit.cpp | 70 +++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 27 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index 82569dd07..b6324565c 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include #include #include #include @@ -52,11 +53,42 @@ namespace vcpkg::Commands::Edit const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("edit zlib"), 1, - 1, + 10, {EDIT_SWITCHES, {}}, &valid_arguments, }; + static std::vector create_editor_arguments(const VcpkgPaths& paths, + const ParsedArguments& options, + const std::vector& ports) + { + if (Util::Sets::contains(options.switches, OPTION_ALL)) + { + return Util::fmap(ports, [&](const std::string& port_name) -> std::string { + const auto portpath = paths.ports / port_name; + const auto portfile = portpath / "portfile.cmake"; + const auto buildtrees_current_dir = paths.buildtrees / port_name; + return Strings::format(R"###("%s" "%s" "%s")###", + portpath.u8string(), + portfile.u8string(), + buildtrees_current_dir.u8string()); + }); + } + + if (Util::Sets::contains(options.switches, OPTION_BUILDTREES)) + { + return Util::fmap(ports, [&](const std::string& port_name) -> std::string { + return (paths.buildtrees / port_name).u8string(); + }); + } + + return Util::fmap(ports, [&](const std::string& port_name) -> std::string { + const auto portpath = paths.ports / port_name; + const auto portfile = portpath / "portfile.cmake"; + return Strings::format(R"###("%s" "%s")###", portpath.u8string(), portfile.u8string()); + }); + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { static const fs::path VS_CODE_INSIDERS = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe"; @@ -65,10 +97,14 @@ namespace vcpkg::Commands::Edit auto& fs = paths.get_filesystem(); const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); - const std::string port_name = args.command_arguments.at(0); - const fs::path portpath = paths.ports / port_name; - Checks::check_exit(VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name); + const std::vector& ports = args.command_arguments; + for (auto&& port_name : ports) + { + const fs::path portpath = paths.ports / port_name; + Checks::check_exit( + VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name); + } std::vector candidate_paths; auto maybe_editor_path = System::get_environment_variable("EDITOR"); @@ -107,29 +143,9 @@ namespace vcpkg::Commands::Edit } const fs::path env_editor = *it; - if (Util::Sets::contains(options.switches, OPTION_BUILDTREES)) - { - const auto buildtrees_current_dir = paths.buildtrees / port_name; - - const auto cmd_line = - Strings::format(R"("%s" "%s" -n)", env_editor.u8string(), buildtrees_current_dir.u8string()); - Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); - } - - if (Util::Sets::contains(options.switches, OPTION_ALL)) - { - const auto buildtrees_current_dir = paths.buildtrees / port_name; - - const auto cmd_line = Strings::format( - R"("%s" "%s" "%s" -n)", env_editor.u8string(), portpath.u8string(), buildtrees_current_dir.u8string()); - Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); - } - - const auto cmd_line = Strings::format( - R"("%s" "%s" "%s" -n)", - env_editor.u8string(), - portpath.u8string(), - (portpath / "portfile.cmake").u8string()); + const std::vector arguments = create_editor_arguments(paths, options, ports); + const auto args_as_string = Strings::join(" ", arguments); + const auto cmd_line = Strings::format(R"("%s" %s -n)", env_editor.u8string(), args_as_string); Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); } } -- cgit v1.2.3 From d126acab7bc5789e8f75197c2ac1fda03584caba Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 24 Apr 2018 11:02:57 -0700 Subject: [vcpkg integrate] Do nothing on linux instead of showing error message --- toolsrc/src/vcpkg/commands.integrate.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 7061a3984..2e1750c80 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -392,8 +392,10 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console paths.scripts / "addPoshVcpkgToPowershellProfile.ps1"); Checks::exit_success(VCPKG_LINE_INFO); } -#endif Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown parameter %s for integrate", args.command_arguments[0]); +#else + Checks::exit_success(VCPKG_LINE_INFO); +#endif } } -- cgit v1.2.3 From 967765f294f1390a9963e21c2918502e22e64caf Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 24 Apr 2018 22:56:18 -0700 Subject: [osx] Ignore .DS_Store file. Fixes #3306 --- toolsrc/src/vcpkg/paragraphs.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp index 41ffceec7..77c028937 100644 --- a/toolsrc/src/vcpkg/paragraphs.cpp +++ b/toolsrc/src/vcpkg/paragraphs.cpp @@ -253,6 +253,10 @@ namespace vcpkg::Paragraphs LoadResults ret; auto port_dirs = fs.get_files_non_recursive(ports_dir); Util::sort(port_dirs); + Util::erase_remove_if(port_dirs, [&](auto&& port_dir_entry) { + return fs.is_regular_file(port_dir_entry) && port_dir_entry.filename() == ".DS_Store"; + }); + for (auto&& path : port_dirs) { auto maybe_spgh = try_load_port(fs, path); -- cgit v1.2.3 From f6530368eb31734734c0e1e7ce990c0cb93f0b24 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 25 Apr 2018 00:19:27 -0700 Subject: Remove noexcept from BinaryParagraph() --- toolsrc/src/vcpkg/binaryparagraph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp index 126c7df97..73ca23df1 100644 --- a/toolsrc/src/vcpkg/binaryparagraph.cpp +++ b/toolsrc/src/vcpkg/binaryparagraph.cpp @@ -24,7 +24,7 @@ namespace vcpkg static const std::string DEFAULTFEATURES = "Default-Features"; } - BinaryParagraph::BinaryParagraph() noexcept = default; + BinaryParagraph::BinaryParagraph() = default; BinaryParagraph::BinaryParagraph(std::unordered_map fields) { -- cgit v1.2.3 From 9167511656715c81d01cc87af5db1835f026f5b6 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 25 Apr 2018 18:14:24 -0700 Subject: Fix #3170 issue with /permissive- --- toolsrc/src/tests.paragraph.cpp | 9 --------- toolsrc/src/tests.utils.cpp | 30 ------------------------------ 2 files changed, 39 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/tests.paragraph.cpp b/toolsrc/src/tests.paragraph.cpp index dca89bc59..9a56ad9ee 100644 --- a/toolsrc/src/tests.paragraph.cpp +++ b/toolsrc/src/tests.paragraph.cpp @@ -5,15 +5,6 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; -namespace Microsoft::VisualStudio::CppUnitTestFramework -{ - template<> - inline std::wstring ToString(const vcpkg::PackageSpecParseResult& t) - { - return ToString(static_cast(t)); - } -} - namespace Strings = vcpkg::Strings; namespace UnitTest1 diff --git a/toolsrc/src/tests.utils.cpp b/toolsrc/src/tests.utils.cpp index a3d8ffc7d..ac391f559 100644 --- a/toolsrc/src/tests.utils.cpp +++ b/toolsrc/src/tests.utils.cpp @@ -5,36 +5,6 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace vcpkg; -namespace Microsoft::VisualStudio::CppUnitTestFramework -{ - std::wstring ToString(const vcpkg::Dependencies::InstallPlanType& t) - { - switch (t) - { - case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; - case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; - case Dependencies::InstallPlanType::EXCLUDED: return L"EXCLUDED"; - case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; - default: return ToString(static_cast(t)); - } - } - - std::wstring ToString(const vcpkg::Dependencies::RequestType& t) - { - switch (t) - { - case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED"; - case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED"; - case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN"; - default: return ToString(static_cast(t)); - } - } - - std::wstring ToString(const vcpkg::PackageSpecParseResult& t) { return ToString(static_cast(t)); } - - std::wstring ToString(const vcpkg::PackageSpec& t) { return ToString(t.to_string()); } -} - std::unique_ptr make_status_pgh(const char* name, const char* depends, const char* default_features, -- cgit v1.2.3 From 039abe258b956fe51b5893b3fb2d20661f2a8eb4 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 18 Apr 2018 02:32:37 -0700 Subject: [ci] Don't block binarycaching = false --- toolsrc/src/vcpkg/commands.ci.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 04b42ea00..e2b93dc7e 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -154,8 +154,10 @@ namespace vcpkg::Commands::CI void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - Checks::check_exit( - VCPKG_LINE_INFO, GlobalState::g_binary_caching, "The ci command requires binary caching to be enabled."); + if (!GlobalState::g_binary_caching) + { + System::println(System::Color::warning, "Warning: Running ci without binary caching!"); + } const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); -- cgit v1.2.3 From a9d989ec056246ea320a56ca7d02b161a6fee387 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 28 Apr 2018 11:26:57 -0700 Subject: [vcpkg-integrate-install] Add vcpkg.path.txt to localappdata for more generic consumption. --- toolsrc/src/vcpkg/commands.integrate.cpp | 87 ++++++++++++++++++++++---------- toolsrc/src/vcpkg/userconfig.cpp | 11 ++-- 2 files changed, 68 insertions(+), 30 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 2e1750c80..8897ea138 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace vcpkg::Commands::Integrate { @@ -156,8 +157,10 @@ namespace vcpkg::Commands::Integrate } #endif + static fs::path get_path_txt_path() { return get_user_dir() / "vcpkg.path.txt"; } + #if defined(_WIN32) - static void integrate_install(const VcpkgPaths& paths) + static void integrate_install_msbuild14(Files::Filesystem& fs, const fs::path& tmp_dir) { static const std::array OLD_SYSTEM_TARGET_FILES = { System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) / @@ -168,8 +171,6 @@ namespace vcpkg::Commands::Integrate System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; - auto& fs = paths.get_filesystem(); - // TODO: This block of code should eventually be removed for (auto&& old_system_wide_targets_file : OLD_SYSTEM_TARGET_FILES) { @@ -188,12 +189,6 @@ namespace vcpkg::Commands::Integrate } } } - - std::error_code ec; - const fs::path tmp_dir = paths.buildsystems / "tmp"; - fs.create_directory(paths.buildsystems, ec); - fs.create_directory(tmp_dir, ec); - bool should_install_system = true; const Expected system_wide_file_contents = fs.read_contents(SYSTEM_WIDE_TARGETS_FILE); static const std::regex RE(R"###()###"); @@ -232,24 +227,52 @@ namespace vcpkg::Commands::Integrate "Error: failed to copy targets file to %s", SYSTEM_WIDE_TARGETS_FILE.string()); } + } +#endif - const fs::path appdata_src_path = tmp_dir / "vcpkg.user.targets"; - fs.write_contents(appdata_src_path, - create_appdata_targets_shortcut(paths.buildsystems_msbuild_targets.string())); - auto appdata_dst_path = get_appdata_targets_path(); + static void integrate_install(const VcpkgPaths& paths) + { + auto& fs = paths.get_filesystem(); + +#if defined(_WIN32) + { + std::error_code ec; + const fs::path tmp_dir = paths.buildsystems / "tmp"; + fs.create_directory(paths.buildsystems, ec); + fs.create_directory(tmp_dir, ec); + + integrate_install_msbuild14(fs, tmp_dir); + + const fs::path appdata_src_path = tmp_dir / "vcpkg.user.targets"; + fs.write_contents(appdata_src_path, + create_appdata_targets_shortcut(paths.buildsystems_msbuild_targets.string())); + auto appdata_dst_path = get_appdata_targets_path(); - const auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec); + const auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec); + + if (!rc || ec) + { + System::println(System::Color::error, + "Error: Failed to copy file: %s -> %s", + appdata_src_path.string(), + appdata_dst_path.string()); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } +#endif - if (!rc || ec) + const auto pathtxt = get_path_txt_path(); + std::error_code ec; + fs.write_contents(pathtxt, paths.root.generic_u8string(), ec); + if (ec) { - System::println(System::Color::error, - "Error: Failed to copy file: %s -> %s", - appdata_src_path.string(), - appdata_dst_path.string()); + System::println(System::Color::error, "Error: Failed to write file: %s", pathtxt.string()); Checks::exit_fail(VCPKG_LINE_INFO); } + System::println(System::Color::success, "Applied user-wide integration for this vcpkg root."); const fs::path cmake_toolchain = paths.buildsystems / "vcpkg.cmake"; +#if defined(_WIN32) System::println( R"( All MSBuild C++ projects can now #include any installed libraries. @@ -258,17 +281,29 @@ Installing new libraries will make them instantly available. CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")", cmake_toolchain.generic_string()); +#else + System::println( + R"( +CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")", + cmake_toolchain.generic_string()); +#endif Checks::exit_success(VCPKG_LINE_INFO); } static void integrate_remove(Files::Filesystem& fs) { + std::error_code ec; + bool was_deleted = false; + +#if defined(_WIN32) const fs::path path = get_appdata_targets_path(); - std::error_code ec; - const bool was_deleted = fs.remove(path, ec); + was_deleted |= fs.remove(path, ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %s", ec.message()); +#endif + was_deleted |= fs.remove(get_path_txt_path(), ec); Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %s", ec.message()); if (was_deleted) @@ -282,7 +317,6 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")", Checks::exit_success(VCPKG_LINE_INFO); } -#endif #if defined(WIN32) static void integrate_project(const VcpkgPaths& paths) @@ -343,7 +377,8 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console " vcpkg integrate powershell Enable PowerShell Tab-Completion\n"; #else const char* const INTEGRATE_COMMAND_HELPSTRING = - "No user-wide integration methods are available on this platform\n"; + " vcpkg integrate install Make installed packages available user-wide.\n" + " vcpkg integrate remove Remove user-wide integration\n"; #endif namespace Subcommand @@ -373,7 +408,6 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console { Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); -#if defined(_WIN32) if (args.command_arguments[0] == Subcommand::INSTALL) { return integrate_install(paths); @@ -382,6 +416,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console { return integrate_remove(paths.get_filesystem()); } +#if defined(_WIN32) if (args.command_arguments[0] == Subcommand::PROJECT) { return integrate_project(paths); @@ -392,10 +427,8 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console paths.scripts / "addPoshVcpkgToPowershellProfile.ps1"); Checks::exit_success(VCPKG_LINE_INFO); } +#endif Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown parameter %s for integrate", args.command_arguments[0]); -#else - Checks::exit_success(VCPKG_LINE_INFO); -#endif } } diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp index 574a97b64..4945fdaaa 100644 --- a/toolsrc/src/vcpkg/userconfig.cpp +++ b/toolsrc/src/vcpkg/userconfig.cpp @@ -29,16 +29,21 @@ namespace namespace vcpkg { - static fs::path get_config_path() + fs::path get_user_dir() { #if defined(_WIN32) - return get_localappdata() / "vcpkg" / "config"; + return get_localappdata() / "vcpkg"; #else auto maybe_home = System::get_environment_variable("HOME"); - return fs::path(maybe_home.value_or("/var")) / ".vcpkg" / "config"; + return fs::path(maybe_home.value_or("/var")) / ".vcpkg"; #endif } + static fs::path get_config_path() + { + return get_user_dir() / "config"; + } + UserConfig UserConfig::try_read_data(const Files::Filesystem& fs) { UserConfig ret; -- cgit v1.2.3 From 8f0ebdf8d561ef8402db44cd9abb2c912cff276d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 3 May 2018 15:03:35 -0700 Subject: [vcpkg] Remove utf16 usage from non-Windows --- toolsrc/src/vcpkg.cpp | 4 +++- toolsrc/src/vcpkg/base/files.cpp | 7 ++++--- toolsrc/src/vcpkg/base/strings.cpp | 12 ++++-------- 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 06c99e9a8..ac2eec876 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -70,7 +70,7 @@ static void inner(const VcpkgCmdArguments& args) fs::path vcpkg_root_dir; if (args.vcpkg_root_dir != nullptr) { - vcpkg_root_dir = fs::stdfs::absolute(Strings::to_utf16(*args.vcpkg_root_dir)); + vcpkg_root_dir = fs::stdfs::absolute(fs::u8path(*args.vcpkg_root_dir)); } else { @@ -94,6 +94,8 @@ static void inner(const VcpkgCmdArguments& args) Checks::check_exit(VCPKG_LINE_INFO, !vcpkg_root_dir.empty(), "Error: Could not detect vcpkg-root."); + Debug::println("Using vcpkg-root: %s", vcpkg_root_dir.u8string()); + auto default_vs_path = System::get_environment_variable("VCPKG_DEFAULT_VS_PATH").value_or(""); const Expected expected_paths = VcpkgPaths::create(vcpkg_root_dir, default_vs_path); diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 1723b467e..0542af1e7 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -56,16 +56,17 @@ namespace vcpkg::Files const std::string& filename) const override { fs::path current_dir = starting_dir; - for (; !current_dir.empty(); current_dir = current_dir.parent_path()) + fs::path unix_root = "/"; + for (; !current_dir.empty() && current_dir != unix_root; current_dir = current_dir.parent_path()) { const fs::path candidate = current_dir / filename; if (exists(candidate)) { - break; + return current_dir; } } - return current_dir; + return fs::path(); } virtual std::vector get_files_recursive(const fs::path& dir) const override diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index fbc33ca42..48dc5ed09 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -49,33 +49,29 @@ namespace vcpkg::Strings::details namespace vcpkg::Strings { +#if defined(_WIN32) std::wstring to_utf16(const CStringView& s) { -#if defined(_WIN32) std::wstring output; const size_t size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0); if (size == 0) return output; output.resize(size - 1); MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, output.data(), static_cast(size) - 1); return output; -#else - Checks::unreachable(VCPKG_LINE_INFO); -#endif } +#endif +#if defined(_WIN32) std::string to_utf8(const wchar_t* w) { -#if defined(_WIN32) std::string output; const size_t size = WideCharToMultiByte(CP_UTF8, 0, w, -1, nullptr, 0, nullptr, nullptr); if (size == 0) return output; output.resize(size - 1); WideCharToMultiByte(CP_UTF8, 0, w, -1, output.data(), static_cast(size) - 1, nullptr, nullptr); return output; -#else - Checks::unreachable(VCPKG_LINE_INFO); -#endif } +#endif std::string escape_string(const CStringView& s, char char_to_escape, char escape_char) { -- cgit v1.2.3 From 120f444af37f4b6e2cb4205b0ef5f8c6b97e8637 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 3 May 2018 15:51:02 -0700 Subject: [vcpkg] Add missing debug statement and fix libc++ Filesystem TS issue. --- toolsrc/src/vcpkg/base/system.cpp | 5 ++++- toolsrc/src/vcpkg/build.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index d4210fe6d..95c9511f9 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -274,8 +274,11 @@ namespace vcpkg::System Debug::println("CreateProcessW() returned %lu", exit_code); return static_cast(exit_code); #else + Debug::println("system(%s)", cmd_line.c_str()); fflush(nullptr); - return system(cmd_line.c_str()); + int rc = system(cmd_line.c_str()); + Debug::println("system() returned %d", rc); + return rc; #endif } diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 7a9d35667..3616348d6 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -357,7 +357,7 @@ namespace vcpkg::Build { {"CMD", "BUILD"}, {"PORT", config.scf.core_paragraph->name}, - {"CURRENT_PORT_DIR", config.port_dir / "/."}, + {"CURRENT_PORT_DIR", config.port_dir}, {"TARGET_TRIPLET", spec.triplet().canonical_name()}, {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, {"VCPKG_USE_HEAD_VERSION", -- cgit v1.2.3 From 9265fe76bf3ed53db03eb31cad9be1c7594bfcb3 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 4 May 2018 16:49:07 -0700 Subject: unix_root -> UNIX_ROOT static const --- toolsrc/src/vcpkg/base/files.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 0542af1e7..3d96e834b 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -55,9 +55,9 @@ namespace vcpkg::Files virtual fs::path find_file_recursively_up(const fs::path& starting_dir, const std::string& filename) const override { + static const fs::path UNIX_ROOT = "/"; fs::path current_dir = starting_dir; - fs::path unix_root = "/"; - for (; !current_dir.empty() && current_dir != unix_root; current_dir = current_dir.parent_path()) + for (; !current_dir.empty() && current_dir != UNIX_ROOT; current_dir = current_dir.parent_path()) { const fs::path candidate = current_dir / filename; if (exists(candidate)) -- cgit v1.2.3 From ab58f531ccf6da9895502cb8ae7bd85b29823d1d Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 4 May 2018 18:14:54 -0700 Subject: git for linux/osx version moved to vcpkgTools.xml --- toolsrc/src/vcpkg/commands.fetch.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 1e31e6bc4..a6cfec3f0 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -83,7 +83,8 @@ namespace vcpkg::Commands::Fetch right_delim, XML_PATH.generic_string()); - return *result.get(); + auto r = *result.get(); + return Strings::trim(std::move(r)); }; static const std::regex XML_VERSION_REGEX{R"###()###"}; @@ -255,8 +256,8 @@ namespace vcpkg::Commands::Fetch const std::string download_path_part = download_path.u8string() + ".part"; std::error_code ec; fs.remove(download_path_part, ec); - const auto code = System::cmd_execute(Strings::format( - R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part)); + const auto code = System::cmd_execute( + Strings::format(R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part)); Checks::check_exit(VCPKG_LINE_INFO, code == 0, "Could not download %s", url); verify_hash(paths, url, download_path_part, sha512); @@ -267,8 +268,13 @@ namespace vcpkg::Commands::Fetch static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data) { const std::array& version = tool_data.version; - const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); + Checks::check_exit(VCPKG_LINE_INFO, + !tool_data.url.empty(), + "A suitable version of %s was not found (required v%s) and unable to automatically " + "download a portable one. Please install a newer version of git.", + tool_name, + version_as_string); System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", tool_name, version_as_string, @@ -401,11 +407,7 @@ namespace vcpkg::Commands::Fetch static fs::path get_git_path(const VcpkgPaths& paths) { -#if defined(_WIN32) static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "git"); -#else - static const ToolData TOOL_DATA = ToolData{{2, 7, 4}, ""}; -#endif static const std::string VERSION_CHECK_ARGUMENTS = "--version"; std::vector candidate_paths; -- cgit v1.2.3 From 6c4c7c0d78f4dd71aa75785fbc09004bbfe345ca Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 9 May 2018 19:26:12 -0700 Subject: Improve unsupported toolchain error message --- toolsrc/src/vcpkg/build.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 3616348d6..1ed5e744a 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -217,7 +217,12 @@ namespace vcpkg::Build if (it != toolset.supported_architectures.end()) return it->name; } - Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported toolchain combination %s", target_architecture); + Checks::exit_with_message(VCPKG_LINE_INFO, + "Unsupported toolchain combination. Target was: %s but supported ones were:\n%s", + target_architecture, + Strings::join(",", toolset.supported_architectures, [](const ToolsetArchOption& t) { + return t.name.c_str(); + })); } std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset) @@ -520,8 +525,8 @@ namespace vcpkg::Build System::cmd_execute_clean(Strings::format( R"("%s" x "%s" -o"%s" -y >nul)", seven_zip_exe.u8string(), archive_path.u8string(), pkg_path.u8string())); #else - System::cmd_execute_clean(Strings::format( - R"(unzip -qq "%s" "-d%s")", archive_path.u8string(), pkg_path.u8string())); + System::cmd_execute_clean( + Strings::format(R"(unzip -qq "%s" "-d%s")", archive_path.u8string(), pkg_path.u8string())); #endif } @@ -537,11 +542,10 @@ namespace vcpkg::Build #if defined(_WIN32) auto&& seven_zip_exe = paths.get_tool_exe(Tools::SEVEN_ZIP); - System::cmd_execute_clean(Strings::format( - R"("%s" a "%s" "%s\*" >nul)", - seven_zip_exe.u8string(), - tmp_archive_path.u8string(), - paths.package_dir(spec).u8string())); + System::cmd_execute_clean(Strings::format(R"("%s" a "%s" "%s\*" >nul)", + seven_zip_exe.u8string(), + tmp_archive_path.u8string(), + paths.package_dir(spec).u8string())); #else System::cmd_execute_clean(Strings::format( R"(cd '%s' && zip --quiet -r '%s' *)", paths.package_dir(spec).u8string(), tmp_archive_path.u8string())); -- cgit v1.2.3 From 1b0682a39e1143660c3d5aa371f66591a64e8a5d Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 5 May 2018 04:23:19 -0700 Subject: [vcpkg] Significantly reduce usage of powershell. Reduce console font switching bug --- toolsrc/src/vcpkg/base/checks.cpp | 2 + toolsrc/src/vcpkg/base/system.cpp | 19 +- toolsrc/src/vcpkg/build.cpp | 14 +- toolsrc/src/vcpkg/commands.cpp | 2 +- toolsrc/src/vcpkg/commands.fetch.cpp | 509 ++++++++++++++++++++++++++--------- toolsrc/src/vcpkg/commands.hash.cpp | 7 +- toolsrc/src/vcpkg/export.cpp | 2 - toolsrc/src/vcpkg/vcpkgpaths.cpp | 9 +- 8 files changed, 416 insertions(+), 148 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp index d96cb98ff..2ac5f9a15 100644 --- a/toolsrc/src/vcpkg/base/checks.cpp +++ b/toolsrc/src/vcpkg/base/checks.cpp @@ -16,6 +16,8 @@ namespace vcpkg::Checks const auto elapsed_us = GlobalState::timer.lock()->microseconds(); + Debug::println("Exiting after %d us", static_cast(elapsed_us)); + auto metrics = Metrics::g_metrics.lock(); metrics->track_metric("elapsed_us", elapsed_us); GlobalState::debugging = false; diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 95c9511f9..4da4548af 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -155,6 +155,7 @@ namespace vcpkg::System int cmd_execute_clean(const CStringView cmd_line, const std::unordered_map& extra_env) { + auto timer = Chrono::ElapsedTimer::create_started(); #if defined(_WIN32) static const std::string SYSTEM_ROOT = get_environment_variable("SystemRoot").value_or_exit(VCPKG_LINE_INFO); static const std::string SYSTEM_32 = SYSTEM_ROOT + R"(\system32)"; @@ -271,7 +272,7 @@ namespace vcpkg::System DWORD exit_code = 0; GetExitCodeProcess(process_info.hProcess, &exit_code); - Debug::println("CreateProcessW() returned %lu", exit_code); + Debug::println("CreateProcessW() returned %lu after %d us", exit_code, static_cast(timer.microseconds())); return static_cast(exit_code); #else Debug::println("system(%s)", cmd_line.c_str()); @@ -369,13 +370,20 @@ namespace vcpkg::System #endif } +#if defined(_WIN32) void powershell_execute(const std::string& title, const fs::path& script_path, const std::vector& parameters) { + SetConsoleCP(437); + SetConsoleOutputCP(437); + const std::string cmd = make_powershell_cmd(script_path, parameters); const int rc = System::cmd_execute(cmd); + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); + if (rc) { System::println(Color::error, @@ -394,14 +402,22 @@ namespace vcpkg::System Checks::exit_with_code(VCPKG_LINE_INFO, rc); } } +#endif +#if defined(_WIN32) std::string powershell_execute_and_capture_output(const std::string& title, const fs::path& script_path, const std::vector& parameters) { + SetConsoleCP(437); + SetConsoleOutputCP(437); + const std::string cmd = make_powershell_cmd(script_path, parameters); auto rc = System::cmd_execute_and_capture_output(cmd); + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); + if (rc.exit_code) { System::println(Color::error, @@ -433,6 +449,7 @@ namespace vcpkg::System return rc.output; } +#endif void println() { putchar('\n'); } diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 1ed5e744a..b8ccb15bf 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -461,9 +461,9 @@ namespace vcpkg::Build abi_tag_entries.insert(abi_tag_entries.end(), dependency_abis.begin(), dependency_abis.end()); abi_tag_entries.emplace_back( - AbiEntry{"portfile", Commands::Hash::get_file_hash(paths, config.port_dir / "portfile.cmake", "SHA1")}); + AbiEntry{"portfile", Commands::Hash::get_file_hash(fs, config.port_dir / "portfile.cmake", "SHA1")}); abi_tag_entries.emplace_back( - AbiEntry{"control", Commands::Hash::get_file_hash(paths, config.port_dir / "CONTROL", "SHA1")}); + AbiEntry{"control", Commands::Hash::get_file_hash(fs, config.port_dir / "CONTROL", "SHA1")}); abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag}); @@ -498,7 +498,7 @@ namespace vcpkg::Build const auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt"); fs.write_contents(abi_file_path, full_abi_info); - return AbiTagAndFile{Commands::Hash::get_file_hash(paths, abi_file_path, "SHA1"), abi_file_path}; + return AbiTagAndFile{Commands::Hash::get_file_hash(fs, abi_file_path, "SHA1"), abi_file_path}; } System::println( @@ -783,14 +783,12 @@ namespace vcpkg::Build { return it_hash->second; } - auto hash = Commands::Hash::get_file_hash(paths, triplet_file_path, "SHA1"); + auto hash = Commands::Hash::get_file_hash(paths.get_filesystem(), triplet_file_path, "SHA1"); s_hash_cache.emplace(triplet_file_path, hash); return hash; } - else - { - return std::string(); - } + + return std::string(); }(); const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path, diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index 8b6ffb3d7..09da57705 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -43,7 +43,7 @@ namespace vcpkg::Commands {"portsdiff", &PortsDiff::perform_and_exit}, {"autocomplete", &Autocomplete::perform_and_exit}, {"hash", &Hash::perform_and_exit}, - // {"fetch", &Fetch::perform_and_exit}, + {"fetch", &Fetch::perform_and_exit}, }; return t; } diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index a6cfec3f0..d50d13c59 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include +#include #include #include #include @@ -19,6 +20,7 @@ namespace vcpkg::Commands::Fetch fs::path exe_path; std::string url; fs::path download_path; + bool is_archive; fs::path tool_dir_path; std::string sha512; }; @@ -41,20 +43,85 @@ namespace vcpkg::Commands::Fetch return result; } - static Optional extract_string_between_delimiters(const std::string& input, - const std::string& left_delim, - const std::string& right_delim, - const size_t& starting_offset = 0) + struct VcpkgStringRange { - const size_t from = input.find(left_delim, starting_offset); - if (from == std::string::npos) return nullopt; + VcpkgStringRange() = default; - const size_t substring_start = from + left_delim.length(); + // Implicit by design + VcpkgStringRange(const std::string& s) : begin(s.cbegin()), end(s.cend()) {} - const size_t to = input.find(right_delim, substring_start); - if (from == std::string::npos) return nullopt; + VcpkgStringRange(const std::string::const_iterator begin, const std::string::const_iterator end) + : begin(begin), end(end) + { + } + + std::string::const_iterator begin; + std::string::const_iterator end; + + std::string to_string() const { return std::string(this->begin, this->end); } + }; + + static std::vector find_all_enclosed(const VcpkgStringRange& input, + const std::string& left_delim, + const std::string& right_delim) + { + std::string::const_iterator it_left = input.begin; + std::string::const_iterator it_right = input.begin; + + std::vector output; - return input.substr(substring_start, to - substring_start); + while (true) + { + it_left = std::search(it_right, input.end, left_delim.cbegin(), left_delim.cend()); + if (it_left == input.end) break; + + it_left += left_delim.length(); + + it_right = std::search(it_left, input.end, right_delim.cbegin(), right_delim.cend()); + if (it_right == input.end) break; + + output.emplace_back(it_left, it_right); + + ++it_right; + } + + return output; + } + + static VcpkgStringRange find_exactly_one_enclosed(const VcpkgStringRange& input, + const std::string& left_tag, + const std::string& right_tag) + { + std::vector result = find_all_enclosed(input, left_tag, right_tag); + Checks::check_exit(VCPKG_LINE_INFO, + result.size() == 1, + "Found %d sets of %s.*%s but expected exactly 1, in block:\n%s", + result.size(), + left_tag, + right_tag, + input); + return std::move(result.front()); + } + + static Optional find_at_most_one_enclosed(const VcpkgStringRange& input, + const std::string& left_tag, + const std::string& right_tag) + { + std::vector result = find_all_enclosed(input, left_tag, right_tag); + Checks::check_exit(VCPKG_LINE_INFO, + result.size() <= 1, + "Found %d sets of %s.*%s but expected at most 1, in block:\n%s", + result.size(), + left_tag, + right_tag, + input); + + if (result.empty()) + { + return nullopt; + } + + return result.front(); } static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool) @@ -72,21 +139,6 @@ namespace vcpkg::Commands::Fetch #if defined(_WIN32) || defined(__APPLE__) || defined(__linux__) static const std::string XML_VERSION = "2"; static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; - - const auto get_string_inside_tags = - [](const std::string& input, const std::string& left_delim, const std::string& right_delim) -> std::string { - Optional result = extract_string_between_delimiters(input, left_delim, right_delim); - Checks::check_exit(VCPKG_LINE_INFO, - result.has_value(), - "Could not find tag <%s>.*<%s> in %s", - left_delim, - right_delim, - XML_PATH.generic_string()); - - auto r = *result.get(); - return Strings::trim(std::move(r)); - }; - static const std::regex XML_VERSION_REGEX{R"###()###"}; static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO); std::smatch match_xml_version; @@ -112,14 +164,14 @@ namespace vcpkg::Commands::Fetch tool, XML_PATH.generic_string()); - const std::string tool_data = get_string_inside_tags(XML, match_tool_entry[0], R"()"); - - const std::string version_as_string = get_string_inside_tags(tool_data, "", R"()"); + const std::string tool_data = find_exactly_one_enclosed(XML, match_tool_entry[0], "").to_string(); + const std::string version_as_string = + find_exactly_one_enclosed(tool_data, "", "").to_string(); const std::string exe_relative_path = - get_string_inside_tags(tool_data, "", R"()"); - const std::string url = get_string_inside_tags(tool_data, "", R"()"); - const std::string sha512 = get_string_inside_tags(tool_data, "", R"()"); - auto archive_name = extract_string_between_delimiters(tool_data, "", R"()"); + find_exactly_one_enclosed(tool_data, "", "").to_string(); + const std::string url = find_exactly_one_enclosed(tool_data, "", "").to_string(); + const std::string sha512 = find_exactly_one_enclosed(tool_data, "", "").to_string(); + auto archive_name = find_at_most_one_enclosed(tool_data, "", ""); const Optional> version = parse_version_string(version_as_string); Checks::check_exit(VCPKG_LINE_INFO, @@ -129,13 +181,14 @@ namespace vcpkg::Commands::Fetch version_as_string); const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, version_as_string, OS_STRING); - const fs::path tool_dir_path = paths.downloads / "tools" / tool_dir_name; + const fs::path tool_dir_path = paths.tools / tool_dir_name; const fs::path exe_path = tool_dir_path / exe_relative_path; return ToolData{*version.get(), exe_path, url, - paths.downloads / archive_name.value_or(exe_relative_path), + paths.downloads / archive_name.value_or(exe_relative_path).to_string(), + archive_name.has_value(), tool_dir_path, sha512}; #endif @@ -163,51 +216,87 @@ namespace vcpkg::Commands::Fetch actual_version[2] >= expected_version[2])); } - static Optional find_if_has_equal_or_greater_version(const std::vector& candidate_paths, + static Optional find_if_has_equal_or_greater_version(Files::Filesystem& fs, + const std::vector& candidate_paths, const std::string& version_check_arguments, const std::array& expected_version) { - auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { + const auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { + if (!fs.exists(p)) return false; const std::string cmd = Strings::format(R"("%s" %s)", p.u8string(), version_check_arguments); return exists_and_has_equal_or_greater_version(cmd, expected_version); }); if (it != candidate_paths.cend()) { - return std::move(*it); + return *it; } return nullopt; } - static std::vector keep_data_lines(const std::string& data_blob) - { - static const std::regex DATA_LINE_REGEX(R"(::(.+?)(?=::))"); - - std::vector data_lines; - - const std::sregex_iterator it(data_blob.cbegin(), data_blob.cend(), DATA_LINE_REGEX); - const std::sregex_iterator end; - for (std::sregex_iterator i = it; i != end; ++i) - { - const std::smatch match = *i; - data_lines.push_back(match[1].str()); - } - - return data_lines; - } - -#if !defined(_WIN32) static void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path) { Files::Filesystem& fs = paths.get_filesystem(); const fs::path to_path_partial = to_path.u8string() + ".partial"; std::error_code ec; + fs.remove_all(to_path, ec); fs.remove_all(to_path_partial, ec); fs.create_directories(to_path_partial, ec); - const auto ext = archive.extension(); +#if defined(_WIN32) + if (ext == ".nupkg") + { + static bool recursion_limiter_sevenzip_old = false; + Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip_old); + recursion_limiter_sevenzip_old = true; + const auto nuget_exe = get_tool_path(paths, Tools::NUGET); + + const std::string stem = archive.stem().u8string(); + // assuming format of [name].[version in the form d.d.d] + // This assumption may not always hold + std::smatch match; + const bool has_match = std::regex_match(stem, match, std::regex{R"###(^(.+)\.(\d+\.\d+\.\d+)$)###"}); + Checks::check_exit(VCPKG_LINE_INFO, + has_match, + "Could not deduce nuget id and version from filename: %s", + archive.u8string()); + + const std::string nugetid = match[1]; + const std::string version = match[2]; + + const auto code_and_output = System::cmd_execute_and_capture_output(Strings::format( + R"("%s" install %s -Version %s -OutputDirectory "%s" -Source "%s" -nocache -DirectDownload -NonInteractive -ForceEnglishOutput -PackageSaveMode nuspec)", + nuget_exe.u8string(), + nugetid, + version, + to_path_partial.u8string(), + paths.downloads.u8string())); + + Checks::check_exit(VCPKG_LINE_INFO, + code_and_output.exit_code == 0, + "Failed to extract '%s' with message:\n%s", + archive.u8string(), + code_and_output.output); + recursion_limiter_sevenzip_old = false; + } + else + { + static bool recursion_limiter_sevenzip = false; + Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip); + recursion_limiter_sevenzip = true; + const auto seven_zip = get_tool_path(paths, Tools::SEVEN_ZIP); + const auto code_and_output = System::cmd_execute_and_capture_output(Strings::format( + R"("%s" x "%s" -o"%s" -y)", seven_zip.u8string(), archive.u8string(), to_path_partial.u8string())); + Checks::check_exit(VCPKG_LINE_INFO, + code_and_output.exit_code == 0, + "7zip failed while extracting '%s' with message:\n%s", + archive.u8string(), + code_and_output.output); + recursion_limiter_sevenzip = false; + } +#else if (ext == ".gz" && ext.extension() != ".tar") { const auto code = System::cmd_execute( @@ -224,16 +313,23 @@ namespace vcpkg::Commands::Fetch { Checks::exit_with_message(VCPKG_LINE_INFO, "Unexpected archive extension: %s", ext.u8string()); } +#endif - fs.rename(to_path_partial, to_path); + fs.rename(to_path_partial, to_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Failed to do post-extract rename-in-place.\nfs.rename(%s, %s, %s)", + to_path_partial.u8string(), + to_path.u8string(), + ec.message()); } - static void verify_hash(const VcpkgPaths& paths, + static void verify_hash(const Files::Filesystem& fs, const std::string& url, const fs::path& path, const std::string& sha512) { - const std::string actual_hash = Hash::get_file_hash(paths, path, "SHA512"); + const std::string actual_hash = Hash::get_file_hash(fs, path, "SHA512"); Checks::check_exit(VCPKG_LINE_INFO, sha512 == actual_hash, "File does not have the expected hash:\n" @@ -247,24 +343,119 @@ namespace vcpkg::Commands::Fetch actual_hash); } - static void download_file(const VcpkgPaths& paths, +#if defined(_WIN32) + static void winhttp_download_file(Files::Filesystem& fs, + CStringView target_file_path, + CStringView hostname, + CStringView url_path) + { + // Make sure the directories are present, otherwise fopen_s fails + const auto dir = fs::path(target_file_path.c_str()).parent_path(); + std::error_code ec; + fs.create_directories(dir, ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not create directories %s", dir.u8string()); + + FILE* f = nullptr; + const errno_t err = fopen_s(&f, target_file_path.c_str(), "wb"); + Checks::check_exit(VCPKG_LINE_INFO, + !err, + "Could not download https://%s%s. Failed to open file %s. Error code was %s", + hostname, + url_path, + target_file_path, + std::to_string(err)); + + auto hSession = WinHttpOpen( + L"vcpkg/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); + Checks::check_exit(VCPKG_LINE_INFO, hSession, "WinHttpOpen() failed: %d", GetLastError()); + + // Use Windows 10 defaults on Windows 7 + DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2); + WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols)); + + // Specify an HTTP server. + auto hConnect = WinHttpConnect(hSession, Strings::to_utf16(hostname).c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0); + Checks::check_exit(VCPKG_LINE_INFO, hConnect, "WinHttpConnect() failed: %d", GetLastError()); + + // Create an HTTP request handle. + auto hRequest = WinHttpOpenRequest(hConnect, + L"GET", + Strings::to_utf16(url_path).c_str(), + nullptr, + WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, + WINHTTP_FLAG_SECURE); + Checks::check_exit(VCPKG_LINE_INFO, hRequest, "WinHttpOpenRequest() failed: %d", GetLastError()); + + // Send a request. + auto bResults = + WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); + Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpSendRequest() failed: %d", GetLastError()); + + // End the request. + bResults = WinHttpReceiveResponse(hRequest, NULL); + Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReceiveResponse() failed: %d", GetLastError()); + + std::vector buf; + + size_t total_downloaded_size = 0; + DWORD dwSize = 0; + do + { + DWORD downloaded_size = 0; + bResults = WinHttpQueryDataAvailable(hRequest, &dwSize); + Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpQueryDataAvailable() failed: %d", GetLastError()); + + if (buf.size() < dwSize) buf.resize(dwSize * 2); + + bResults = WinHttpReadData(hRequest, (LPVOID)buf.data(), dwSize, &downloaded_size); + Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReadData() failed: %d", GetLastError()); + fwrite(buf.data(), 1, downloaded_size, f); + + total_downloaded_size += downloaded_size; + } while (dwSize > 0); + + WinHttpCloseHandle(hSession); + WinHttpCloseHandle(hConnect); + WinHttpCloseHandle(hRequest); + fflush(f); + fclose(f); + } +#endif + + static void download_file(Files::Filesystem& fs, const std::string& url, const fs::path& download_path, const std::string& sha512) { - Files::Filesystem& fs = paths.get_filesystem(); const std::string download_path_part = download_path.u8string() + ".part"; std::error_code ec; + fs.remove(download_path, ec); fs.remove(download_path_part, ec); +#if defined(_WIN32) + auto url_no_proto = url.substr(8); // drop https:// + auto path_begin = Util::find(url_no_proto, '/'); + std::string hostname(url_no_proto.begin(), path_begin); + std::string path(path_begin, url_no_proto.end()); + + winhttp_download_file(fs, download_path_part.c_str(), hostname, path); +#else const auto code = System::cmd_execute( Strings::format(R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part)); Checks::check_exit(VCPKG_LINE_INFO, code == 0, "Could not download %s", url); +#endif - verify_hash(paths, url, download_path_part, sha512); - fs.rename(download_path_part, download_path); + verify_hash(fs, url, download_path_part, sha512); + fs.rename(download_path_part, download_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Failed to do post-download rename-in-place.\nfs.rename(%s, %s, %s)", + download_path_part, + download_path.u8string(), + ec.message()); } -#endif static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data) { const std::array& version = tool_data.version; @@ -280,50 +471,37 @@ namespace vcpkg::Commands::Fetch version_as_string, tool_name, version_as_string); -#if defined(_WIN32) - const fs::path script = paths.scripts / "fetchtool.ps1"; - const std::string title = Strings::format( - "Fetching %s version %s (No sufficient installed version was found)", tool_name, version_as_string); - const System::PowershellParameter tool_param("tool", tool_name); - const std::string output = System::powershell_execute_and_capture_output(title, script, {tool_param}); - - const std::vector tool_path = keep_data_lines(output); - Checks::check_exit(VCPKG_LINE_INFO, tool_path.size() == 1, "Expected tool path, but got %s", output); - - const fs::path actual_downloaded_path = Strings::trim(std::string{tool_path.at(0)}); - const fs::path& expected_downloaded_path = tool_data.exe_path; - std::error_code ec; - const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - eq && !ec, - "Expected tool downloaded path to be %s, but was %s", - expected_downloaded_path.u8string(), - actual_downloaded_path.u8string()); - return actual_downloaded_path; -#else - const auto& fs = paths.get_filesystem(); + auto& fs = paths.get_filesystem(); if (!fs.exists(tool_data.download_path)) { System::println("Downloading %s...", tool_name); - download_file(paths, tool_data.url, tool_data.download_path, tool_data.sha512); + download_file(fs, tool_data.url, tool_data.download_path, tool_data.sha512); System::println("Downloading %s... done.", tool_name); } else { - verify_hash(paths, tool_data.url, tool_data.download_path, tool_data.sha512); + verify_hash(fs, tool_data.url, tool_data.download_path, tool_data.sha512); } - System::println("Extracting %s...", tool_name); - extract_archive(paths, tool_data.download_path, tool_data.tool_dir_path); - System::println("Extracting %s... done.", tool_name); + if (tool_data.is_archive) + { + System::println("Extracting %s...", tool_name); + extract_archive(paths, tool_data.download_path, tool_data.tool_dir_path); + System::println("Extracting %s... done.", tool_name); + } + else + { + std::error_code ec; + fs.create_directories(tool_data.exe_path.parent_path(), ec); + fs.rename(tool_data.download_path, tool_data.exe_path, ec); + } Checks::check_exit(VCPKG_LINE_INFO, fs.exists(tool_data.exe_path), - "Expected %s to exist after extracting", - tool_data.exe_path); + "Expected %s to exist after fetching", + tool_data.exe_path.u8string()); return tool_data.exe_path; -#endif } static fs::path get_cmake_path(const VcpkgPaths& paths) @@ -345,8 +523,8 @@ namespace vcpkg::Commands::Fetch const auto& program_files_32_bit = System::get_program_files_32_bit(); if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe"); - const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version); + const Optional path = find_if_has_equal_or_greater_version( + paths.get_filesystem(), candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version); if (const auto p = path.get()) { return *p; @@ -378,7 +556,8 @@ namespace vcpkg::Commands::Fetch const std::vector from_path = Files::find_from_PATH("ninja"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - auto path = find_if_has_equal_or_greater_version(candidate_paths, "--version", TOOL_DATA.version); + auto path = find_if_has_equal_or_greater_version( + paths.get_filesystem(), candidate_paths, "--version", TOOL_DATA.version); if (const auto p = path.get()) { return *p; @@ -396,7 +575,8 @@ namespace vcpkg::Commands::Fetch const std::vector from_path = Files::find_from_PATH("nuget"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - auto path = find_if_has_equal_or_greater_version(candidate_paths, "", TOOL_DATA.version); + auto path = + find_if_has_equal_or_greater_version(paths.get_filesystem(), candidate_paths, "", TOOL_DATA.version); if (const auto p = path.get()) { return *p; @@ -422,8 +602,8 @@ namespace vcpkg::Commands::Fetch const auto& program_files_32_bit = System::get_program_files_32_bit(); if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe"); - const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version); + const Optional path = find_if_has_equal_or_greater_version( + paths.get_filesystem(), candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version); if (const auto p = path.get()) { return *p; @@ -448,8 +628,8 @@ namespace vcpkg::Commands::Fetch // candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" / // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); - const Optional path = - find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version); + const Optional path = find_if_has_equal_or_greater_version( + paths.get_filesystem(), candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version); if (const auto p = path.get()) { return *p; @@ -460,48 +640,114 @@ namespace vcpkg::Commands::Fetch struct VisualStudioInstance { + enum class ReleaseType + { + STABLE, + PRERELEASE, + LEGACY + }; + + static bool prefered_first_comparator(const VisualStudioInstance& left, const VisualStudioInstance& right) + { + const auto get_preference_weight = [](const ReleaseType& type) -> int { + switch (type) + { + case ReleaseType::STABLE: return 3; + case ReleaseType::PRERELEASE: return 2; + case ReleaseType::LEGACY: return 1; + default: Checks::unreachable(VCPKG_LINE_INFO); + } + }; + + if (left.release_type != right.release_type) + { + return get_preference_weight(left.release_type) > get_preference_weight(right.release_type); + } + + return left.version > right.version; + } + + VisualStudioInstance(fs::path&& root_path, std::string&& version, const ReleaseType& release_type) + : root_path(std::move(root_path)), version(std::move(version)), release_type(release_type) + { + } + fs::path root_path; std::string version; - std::string release_type; - std::string preference_weight; // Mostly unused, just for verification that order is as intended + ReleaseType release_type; std::string major_version() const { return version.substr(0, 2); } }; static std::vector get_visual_studio_instances(const VcpkgPaths& paths) { - const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; - const std::string output = - System::powershell_execute_and_capture_output("Detecting Visual Studio instances", script); + const auto& fs = paths.get_filesystem(); + + const auto& program_files_32_bit = System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO); + const fs::path vswhere_exe = program_files_32_bit / "Microsoft Visual Studio" / "Installer" / "vswhere.exe"; + Checks::check_exit( + VCPKG_LINE_INFO, fs.exists(vswhere_exe), "Could not locate vswhere at %s", vswhere_exe.u8string()); + + const auto code_and_output = System::cmd_execute_and_capture_output( + Strings::format(R"("%s" -prerelease -legacy -products * -format xml)", vswhere_exe.u8string())); - const std::vector instances_as_strings = keep_data_lines(output); Checks::check_exit(VCPKG_LINE_INFO, - !instances_as_strings.empty(), - "Could not detect any Visual Studio instances.\n" - "Powershell script:\n" - " %s\n" - "returned:\n" - "%s", - script.generic_string(), - output); + code_and_output.exit_code == 0, + "Running vswhere.exe failed with message:\n%s", + code_and_output.output); + + const auto& xml_as_string = code_and_output.output; + + const auto instance_entries = find_all_enclosed(xml_as_string, "", ""); std::vector instances; - for (const std::string& instance_as_string : instances_as_strings) + for (const VcpkgStringRange& instance : instance_entries) { - const std::vector split = Strings::split(instance_as_string, "::"); - Checks::check_exit(VCPKG_LINE_INFO, - split.size() == 4, - "Invalid Visual Studio instance format.\n" - "Expected: PreferenceWeight::ReleaseType::Version::PathToVisualStudio\n" - "Actual : %s\n", - instance_as_string); - instances.push_back({split.at(3), split.at(2), split.at(1), split.at(0)}); + auto maybe_is_prerelease = find_at_most_one_enclosed(instance, "", ""); + + VisualStudioInstance::ReleaseType release_type = VisualStudioInstance::ReleaseType::LEGACY; + if (auto p = maybe_is_prerelease.get()) + { + auto s = p->to_string(); + if (s == "0") + release_type = VisualStudioInstance::ReleaseType::STABLE; + else if (s == "1") + release_type = VisualStudioInstance::ReleaseType::PRERELEASE; + else + Checks::unreachable(VCPKG_LINE_INFO); + } + + instances.emplace_back( + find_exactly_one_enclosed(instance, "", "").to_string(), + find_exactly_one_enclosed(instance, "", "").to_string(), + release_type); } + const auto append_if_has_cl = [&](fs::path&& path_root) { + const auto cl_exe = path_root / "VC" / "bin" / "cl.exe"; + const auto vcvarsall_bat = path_root / "VC" / "vcvarsall.bat"; + + if (fs.exists(cl_exe) && fs.exists(vcvarsall_bat)) + instances.emplace_back(std::move(path_root), "14.0", VisualStudioInstance::ReleaseType::LEGACY); + }; + + auto maybe_vs140comntools = System::get_environment_variable("vs140comntools"); + if (const auto path_as_string = maybe_vs140comntools.get()) + { + // We want lexically_normal(), but it is not available + // Correct root path might be 2 or 3 levels up, depending on if the path has trailing backslash. Try both. + auto common7_tools = fs::path{*path_as_string}; + append_if_has_cl(fs::path{*path_as_string}.parent_path().parent_path()); + append_if_has_cl(fs::path{*path_as_string}.parent_path().parent_path().parent_path()); + } + + append_if_has_cl(program_files_32_bit / "Microsoft Visual Studio 14.0"); + return instances; } - std::vector find_toolset_instances(const VcpkgPaths& paths) +#if defined(_WIN32) + std::vector find_toolset_instances_prefered_first(const VcpkgPaths& paths) { using CPU = System::CPUArchitecture; @@ -513,12 +759,14 @@ namespace vcpkg::Commands::Fetch std::vector found_toolsets; std::vector excluded_toolsets; - const std::vector vs_instances = get_visual_studio_instances(paths); - const bool v140_is_available = Util::find_if(vs_instances, [&](const VisualStudioInstance& vs_instance) { + const SortedVector sorted{get_visual_studio_instances(paths), + VisualStudioInstance::prefered_first_comparator}; + + const bool v140_is_available = Util::find_if(sorted, [&](const VisualStudioInstance& vs_instance) { return vs_instance.major_version() == "14"; - }) != vs_instances.cend(); + }) != sorted.end(); - for (const VisualStudioInstance& vs_instance : vs_instances) + for (const VisualStudioInstance& vs_instance : sorted) { const std::string major_version = vs_instance.major_version(); if (major_version == "15") @@ -672,6 +920,7 @@ namespace vcpkg::Commands::Fetch return found_toolsets; } +#endif fs::path get_tool_path(const VcpkgPaths& paths, const std::string& tool) { diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 1f709f87b..d7d653ca3 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -154,10 +154,9 @@ namespace vcpkg::Commands::Hash }; } - std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type) + std::string get_file_hash(const Files::Filesystem& fs, const fs::path& path, const std::string& hash_type) { - Checks::check_exit( - VCPKG_LINE_INFO, paths.get_filesystem().exists(path), "File %s does not exist", path.u8string()); + Checks::check_exit(VCPKG_LINE_INFO, fs.exists(path), "File %s does not exist", path.u8string()); return BCryptHasher{hash_type}.hash_file(path); } @@ -239,7 +238,7 @@ namespace vcpkg::Commands::Hash const fs::path file_to_hash = args.command_arguments[0]; const std::string algorithm = args.command_arguments.size() == 2 ? args.command_arguments[1] : "SHA512"; - const std::string hash = get_file_hash(paths, file_to_hash, algorithm); + const std::string hash = get_file_hash(paths.get_filesystem(), file_to_hash, algorithm); System::println(hash); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 152252018..b13140de2 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -227,8 +227,6 @@ namespace vcpkg::Export {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"}, {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"}, {fs::path{"scripts"} / "getWindowsSDK.ps1"}, - {fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"}, - {fs::path{"scripts"} / "getProgramFiles32bit.ps1"}, {fs::path{"scripts"} / "VcpkgPowershellUtils.ps1"}, }; diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 0903c2d76..caf09f526 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -39,6 +39,7 @@ namespace vcpkg paths.triplets = paths.root / "triplets"; paths.scripts = paths.root / "scripts"; + paths.tools = paths.downloads / "tools"; paths.buildsystems = paths.scripts / "buildsystems"; paths.buildsystems_msbuild_targets = paths.buildsystems / "msbuild" / "vcpkg.targets"; @@ -113,9 +114,11 @@ namespace vcpkg return external_toolset; } - // Invariant: toolsets are non-empty and sorted with newest at back() +#if !defined(_WIN32) + Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot build windows triplets from non-windows."); +#else const std::vector& vs_toolsets = - this->toolsets.get_lazy([this]() { return Commands::Fetch::find_toolset_instances(*this); }); + this->toolsets.get_lazy([this]() { return Commands::Fetch::find_toolset_instances_prefered_first(*this); }); std::vector candidates = Util::element_pointers(vs_toolsets); const auto tsv = prebuildinfo.platform_toolset.get(); @@ -159,6 +162,8 @@ namespace vcpkg Checks::check_exit(VCPKG_LINE_INFO, !candidates.empty(), "No suitable Visual Studio instances were found"); return *candidates.front(); + +#endif } Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); } -- cgit v1.2.3 From 8bb28d0de4903075643a1683cad3c4e5ad89920a Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 15 May 2018 23:41:31 -0700 Subject: Fix signature of hashing function --- toolsrc/src/vcpkg/commands.hash.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index d7d653ca3..0c7aa72c4 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -201,11 +201,10 @@ namespace vcpkg::Commands::Hash return split[0]; } - std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type) + std::string get_file_hash(const Files::Filesystem& fs, const fs::path& path, const std::string& hash_type) { const std::string digest_size = get_digest_size(hash_type); - Checks::check_exit( - VCPKG_LINE_INFO, paths.get_filesystem().exists(path), "File %s does not exist", path.u8string()); + Checks::check_exit(VCPKG_LINE_INFO, fs.exists(path), "File %s does not exist", path.u8string()); const std::string cmd_line = Strings::format(R"(shasum -a %s "%s")", digest_size, path.u8string()); return run_shasum_and_post_process(cmd_line); } -- cgit v1.2.3 From f4c6fe61d0ec08d6911f914d0f57ab525a08ec0b Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 16 May 2018 15:11:55 -0700 Subject: [vcpkg.exe] Don't error if vswhere.exe is not found --- toolsrc/src/vcpkg/commands.fetch.cpp | 68 ++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index d50d13c59..c46031665 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -682,45 +682,43 @@ namespace vcpkg::Commands::Fetch static std::vector get_visual_studio_instances(const VcpkgPaths& paths) { const auto& fs = paths.get_filesystem(); + std::vector instances; const auto& program_files_32_bit = System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO); - const fs::path vswhere_exe = program_files_32_bit / "Microsoft Visual Studio" / "Installer" / "vswhere.exe"; - Checks::check_exit( - VCPKG_LINE_INFO, fs.exists(vswhere_exe), "Could not locate vswhere at %s", vswhere_exe.u8string()); - - const auto code_and_output = System::cmd_execute_and_capture_output( - Strings::format(R"("%s" -prerelease -legacy -products * -format xml)", vswhere_exe.u8string())); - - Checks::check_exit(VCPKG_LINE_INFO, - code_and_output.exit_code == 0, - "Running vswhere.exe failed with message:\n%s", - code_and_output.output); - const auto& xml_as_string = code_and_output.output; - - const auto instance_entries = find_all_enclosed(xml_as_string, "", ""); - - std::vector instances; - for (const VcpkgStringRange& instance : instance_entries) + // Instances from vswhere + const fs::path vswhere_exe = program_files_32_bit / "Microsoft Visual Studio" / "Installer" / "vswhere.exe"; + if (fs.exists(vswhere_exe)) { - auto maybe_is_prerelease = find_at_most_one_enclosed(instance, "", ""); + const auto code_and_output = System::cmd_execute_and_capture_output( + Strings::format(R"("%s" -prerelease -legacy -products * -format xml)", vswhere_exe.u8string())); + Checks::check_exit(VCPKG_LINE_INFO, + code_and_output.exit_code == 0, + "Running vswhere.exe failed with message:\n%s", + code_and_output.output); - VisualStudioInstance::ReleaseType release_type = VisualStudioInstance::ReleaseType::LEGACY; - if (auto p = maybe_is_prerelease.get()) + const auto instance_entries = find_all_enclosed(code_and_output.output, "", ""); + for (const VcpkgStringRange& instance : instance_entries) { - auto s = p->to_string(); - if (s == "0") - release_type = VisualStudioInstance::ReleaseType::STABLE; - else if (s == "1") - release_type = VisualStudioInstance::ReleaseType::PRERELEASE; - else - Checks::unreachable(VCPKG_LINE_INFO); - } + auto maybe_is_prerelease = find_at_most_one_enclosed(instance, "", ""); - instances.emplace_back( - find_exactly_one_enclosed(instance, "", "").to_string(), - find_exactly_one_enclosed(instance, "", "").to_string(), - release_type); + VisualStudioInstance::ReleaseType release_type = VisualStudioInstance::ReleaseType::LEGACY; + if (const auto p = maybe_is_prerelease.get()) + { + const auto s = p->to_string(); + if (s == "0") + release_type = VisualStudioInstance::ReleaseType::STABLE; + else if (s == "1") + release_type = VisualStudioInstance::ReleaseType::PRERELEASE; + else + Checks::unreachable(VCPKG_LINE_INFO); + } + + instances.emplace_back( + find_exactly_one_enclosed(instance, "", "").to_string(), + find_exactly_one_enclosed(instance, "", "").to_string(), + release_type); + } } const auto append_if_has_cl = [&](fs::path&& path_root) { @@ -731,8 +729,9 @@ namespace vcpkg::Commands::Fetch instances.emplace_back(std::move(path_root), "14.0", VisualStudioInstance::ReleaseType::LEGACY); }; - auto maybe_vs140comntools = System::get_environment_variable("vs140comntools"); - if (const auto path_as_string = maybe_vs140comntools.get()) + // VS2015 instance from environment variable + auto maybe_vs140_comntools = System::get_environment_variable("vs140comntools"); + if (const auto path_as_string = maybe_vs140_comntools.get()) { // We want lexically_normal(), but it is not available // Correct root path might be 2 or 3 levels up, depending on if the path has trailing backslash. Try both. @@ -741,6 +740,7 @@ namespace vcpkg::Commands::Fetch append_if_has_cl(fs::path{*path_as_string}.parent_path().parent_path().parent_path()); } + // VS2015 instance from Program Files append_if_has_cl(program_files_32_bit / "Microsoft Visual Studio 14.0"); return instances; -- cgit v1.2.3 From f69cce7051e4404e19fe8c049c23c4678fe8b3d4 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 16 May 2018 15:30:26 -0700 Subject: Fix typo --- toolsrc/src/vcpkg/commands.fetch.cpp | 6 +++--- toolsrc/src/vcpkg/vcpkgpaths.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index c46031665..c88ae9dd0 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -647,7 +647,7 @@ namespace vcpkg::Commands::Fetch LEGACY }; - static bool prefered_first_comparator(const VisualStudioInstance& left, const VisualStudioInstance& right) + static bool preferred_first_comparator(const VisualStudioInstance& left, const VisualStudioInstance& right) { const auto get_preference_weight = [](const ReleaseType& type) -> int { switch (type) @@ -747,7 +747,7 @@ namespace vcpkg::Commands::Fetch } #if defined(_WIN32) - std::vector find_toolset_instances_prefered_first(const VcpkgPaths& paths) + std::vector find_toolset_instances_preferred_first(const VcpkgPaths& paths) { using CPU = System::CPUArchitecture; @@ -760,7 +760,7 @@ namespace vcpkg::Commands::Fetch std::vector excluded_toolsets; const SortedVector sorted{get_visual_studio_instances(paths), - VisualStudioInstance::prefered_first_comparator}; + VisualStudioInstance::preferred_first_comparator}; const bool v140_is_available = Util::find_if(sorted, [&](const VisualStudioInstance& vs_instance) { return vs_instance.major_version() == "14"; diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index caf09f526..9b74bea74 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -117,8 +117,8 @@ namespace vcpkg #if !defined(_WIN32) Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot build windows triplets from non-windows."); #else - const std::vector& vs_toolsets = - this->toolsets.get_lazy([this]() { return Commands::Fetch::find_toolset_instances_prefered_first(*this); }); + const std::vector& vs_toolsets = this->toolsets.get_lazy( + [this]() { return Commands::Fetch::find_toolset_instances_preferred_first(*this); }); std::vector candidates = Util::element_pointers(vs_toolsets); const auto tsv = prebuildinfo.platform_toolset.get(); -- cgit v1.2.3 From 950a3d00493a90fed9bfc629bfbf9144da689d3f Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Wed, 16 May 2018 18:59:25 -0700 Subject: [vcpkg edit] Fix whitespace-in-path issue --- toolsrc/src/vcpkg/commands.edit.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index b6324565c..2569c2cea 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -78,7 +78,8 @@ namespace vcpkg::Commands::Edit if (Util::Sets::contains(options.switches, OPTION_BUILDTREES)) { return Util::fmap(ports, [&](const std::string& port_name) -> std::string { - return (paths.buildtrees / port_name).u8string(); + const auto buildtrees_current_dir = paths.buildtrees / port_name; + return Strings::format(R"###("%s")###", buildtrees_current_dir.u8string()); }); } -- cgit v1.2.3 From b31cfb8b87d7548c10b2b04b7298c753b0af1521 Mon Sep 17 00:00:00 2001 From: Sztergbaum Roman Date: Fri, 18 May 2018 21:46:34 +0200 Subject: fix compilation error on clang 6.0/APPLE (#3520) * fix compilation error on clang 6.0/APPLE * Update system.cpp --- toolsrc/src/vcpkg/base/system.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 4da4548af..73a92f2da 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -40,8 +40,9 @@ namespace vcpkg::System if (bytes == 0) std::abort(); return fs::path(buf, buf + bytes); #elif defined(__APPLE__) - uint32_t size = 1024 * 32; - char buf[size] = {}; + static constexpr const uint32_t buff_size = 1024 * 32; + uint32_t size = buff_size; + char buf[buff_size] = {}; bool result = _NSGetExecutablePath(buf, &size); Checks::check_exit(VCPKG_LINE_INFO, result != -1, "Could not determine current executable path."); std::unique_ptr canonicalPath(realpath(buf, NULL)); -- cgit v1.2.3 From 8549a095a8707c2aa38e9ee1642bef2cf0a90d81 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 19 May 2018 17:55:15 -0700 Subject: Remove stray entries --- toolsrc/src/vcpkg/export.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index b13140de2..c444cf3d0 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -226,8 +226,6 @@ namespace vcpkg::Export {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"}, {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"}, {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"}, - {fs::path{"scripts"} / "getWindowsSDK.ps1"}, - {fs::path{"scripts"} / "VcpkgPowershellUtils.ps1"}, }; for (const fs::path& file : integration_files_relative_to_root) -- cgit v1.2.3 From 285c69b0faa220311f3ccc60febaa2e7c6d87bb1 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Sat, 19 May 2018 19:01:10 -0700 Subject: [c++] Condense powershell helper code into the remaining single usage `vcpkg integrate powershell` uses it --- toolsrc/src/vcpkg/base/system.cpp | 106 ------------------------------- toolsrc/src/vcpkg/commands.integrate.cpp | 42 +++++++++++- 2 files changed, 39 insertions(+), 109 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index 73a92f2da..1aa12d0a4 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -129,31 +129,6 @@ namespace vcpkg::System R"("%s" %s -P "%s")", cmake_exe.u8string(), cmd_cmake_pass_variables, cmake_script.generic_u8string()); } - PowershellParameter::PowershellParameter(const CStringView varname, const char* varvalue) - : s(Strings::format(R"(-%s '%s')", varname, varvalue)) - { - } - - PowershellParameter::PowershellParameter(const CStringView varname, const std::string& varvalue) - : PowershellParameter(varname, varvalue.c_str()) - { - } - - PowershellParameter::PowershellParameter(const CStringView varname, const fs::path& path) - : PowershellParameter(varname, path.generic_u8string()) - { - } - - static std::string make_powershell_cmd(const fs::path& script_path, - const std::vector& parameters) - { - const std::string args = Strings::join(" ", parameters, [](auto&& v) { return v.s; }); - - // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned - return Strings::format( - R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args); - } - int cmd_execute_clean(const CStringView cmd_line, const std::unordered_map& extra_env) { auto timer = Chrono::ElapsedTimer::create_started(); @@ -371,87 +346,6 @@ namespace vcpkg::System #endif } -#if defined(_WIN32) - void powershell_execute(const std::string& title, - const fs::path& script_path, - const std::vector& parameters) - { - SetConsoleCP(437); - SetConsoleOutputCP(437); - - const std::string cmd = make_powershell_cmd(script_path, parameters); - const int rc = System::cmd_execute(cmd); - - SetConsoleCP(CP_UTF8); - SetConsoleOutputCP(CP_UTF8); - - if (rc) - { - System::println(Color::error, - "%s\n" - "Could not run:\n" - " '%s'", - title, - script_path.generic_string()); - - { - auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_property("error", "powershell script failed"); - locked_metrics->track_property("title", title); - } - - Checks::exit_with_code(VCPKG_LINE_INFO, rc); - } - } -#endif - -#if defined(_WIN32) - std::string powershell_execute_and_capture_output(const std::string& title, - const fs::path& script_path, - const std::vector& parameters) - { - SetConsoleCP(437); - SetConsoleOutputCP(437); - - const std::string cmd = make_powershell_cmd(script_path, parameters); - auto rc = System::cmd_execute_and_capture_output(cmd); - - SetConsoleCP(CP_UTF8); - SetConsoleOutputCP(CP_UTF8); - - if (rc.exit_code) - { - System::println(Color::error, - "%s\n" - "Could not run:\n" - " '%s'\n" - "Error message was:\n" - " %s", - title, - script_path.generic_string(), - rc.output); - - { - auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_property("error", "powershell script failed"); - locked_metrics->track_property("title", title); - } - - Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); - } - - // Remove newline from all output. - // Powershell returns newlines when it hits the column count of the console. - // For example, this is 80 in cmd on Windows 7. If the expected output is longer than 80 lines, we get - // newlines in-between the data. - // To solve this, we design our interaction with powershell to not depend on newlines, - // and then strip all newlines here. - rc.output = Strings::replace_all(std::move(rc.output), "\n", ""); - - return rc.output; - } -#endif - void println() { putchar('\n'); } void print(const CStringView message) { fputs(message.c_str(), stdout); } diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 8897ea138..82172e363 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include namespace vcpkg::Commands::Integrate @@ -368,6 +369,43 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console } #endif +#if defined(_WIN32) + static void integrate_powershell(const VcpkgPaths& paths) + { + static constexpr StringLiteral TITLE = "PowerShell Tab-Completion"; + const fs::path script_path = paths.scripts / "addPoshVcpkgToPowershellProfile.ps1"; + + // Console font corruption workaround + SetConsoleCP(437); + SetConsoleOutputCP(437); + + const std::string cmd = Strings::format( + R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), ""); + const int rc = System::cmd_execute(cmd); + + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); + + if (rc) + { + System::println(System::Color::error, + "%s\n" + "Could not run:\n" + " '%s'", + TITLE, + script_path.generic_string()); + + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_property("error", "powershell script failed"); + locked_metrics->track_property("title", TITLE); + } + } + + Checks::exit_with_code(VCPKG_LINE_INFO, rc); + } +#endif + #if defined(_WIN32) const char* const INTEGRATE_COMMAND_HELPSTRING = " vcpkg integrate install Make installed packages available user-wide. Requires admin privileges on " @@ -423,9 +461,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console } if (args.command_arguments[0] == Subcommand::POWERSHELL) { - System::powershell_execute("PowerShell Tab-Completion", - paths.scripts / "addPoshVcpkgToPowershellProfile.ps1"); - Checks::exit_success(VCPKG_LINE_INFO); + return integrate_powershell(paths); } #endif -- cgit v1.2.3 From 78e4d07e84afc0f1ab23179534aa08bf6e194b98 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 22 May 2018 03:37:40 -0700 Subject: [vcpkg] Improve CMake messages to account for case-sensitive filesystems. Improve CMake messages to display shortest targets first (which are hopefully the "public" ones). Also, fix bug in StringLiteral. --- toolsrc/src/vcpkg/base/strings.cpp | 6 +++++ toolsrc/src/vcpkg/commands.cache.cpp | 2 +- toolsrc/src/vcpkg/commands.list.cpp | 2 +- toolsrc/src/vcpkg/install.cpp | 43 ++++++++++++++++++++++++++++-------- 4 files changed, 42 insertions(+), 11 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index 48dc5ed09..8d43e7af7 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -128,6 +128,12 @@ namespace vcpkg::Strings #endif } + bool ends_with(const std::string& s, StringLiteral pattern) + { + if (s.size() < pattern.size()) return false; + return std::equal(s.end() - pattern.size(), s.end(), pattern.c_str(), pattern.c_str() + pattern.size()); + } + std::string replace_all(std::string&& s, const std::string& search, const std::string& rep) { size_t pos = 0; diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp index a9d8ba03c..464f4f9ee 100644 --- a/toolsrc/src/vcpkg/commands.cache.cpp +++ b/toolsrc/src/vcpkg/commands.cache.cpp @@ -61,7 +61,7 @@ namespace vcpkg::Commands::Cache for (const BinaryParagraph& binary_paragraph : binary_paragraphs) { const std::string displayname = binary_paragraph.displayname(); - if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end()) + if (!Strings::case_insensitive_ascii_contains(displayname, args.command_arguments[0])) { continue; } diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp index 1bfbc4247..cadc06ad3 100644 --- a/toolsrc/src/vcpkg/commands.list.cpp +++ b/toolsrc/src/vcpkg/commands.list.cpp @@ -76,7 +76,7 @@ namespace vcpkg::Commands::List for (const StatusParagraph* status_paragraph : installed_packages) { const std::string displayname = status_paragraph->package.displayname(); - if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end()) + if (!Strings::case_insensitive_ascii_contains(displayname, args.command_arguments[0])) { continue; } diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index fc336d6c7..40e696fa0 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -462,14 +462,14 @@ namespace vcpkg::Install auto files = fs.read_lines(paths.listfile_path(bpgh)); if (auto p_lines = files.get()) { + std::map config_files; std::map> library_targets; for (auto&& suffix : *p_lines) { - if (Strings::case_insensitive_ascii_find(suffix, "/share/") != suffix.end() && - suffix.substr(suffix.size() - 6) == ".cmake") + if (Strings::case_insensitive_ascii_contains(suffix, "/share/") && Strings::ends_with(suffix, ".cmake")) { - // File is inside the share folder + // CMake file is inside the share folder auto path = paths.installed / suffix; auto maybe_contents = fs.read_contents(path); auto find_package_name = path.parent_path().filename().u8string(); @@ -485,6 +485,21 @@ namespace vcpkg::Install ++next; } } + + auto filename = fs::u8path(suffix).filename().u8string(); + + if (Strings::ends_with(filename, "Config.cmake")) + { + auto root = filename.substr(0, filename.size() - 12); + if (Strings::case_insensitive_ascii_equals(root, find_package_name)) + config_files[find_package_name] = root; + } + else if (Strings::ends_with(filename, "-config.cmake")) + { + auto root = filename.substr(0, filename.size() - 13); + if (Strings::case_insensitive_ascii_equals(root, find_package_name)) + config_files[find_package_name] = root; + } } } @@ -497,11 +512,23 @@ namespace vcpkg::Install for (auto&& library_target_pair : library_targets) { + auto config_it = config_files.find(library_target_pair.first); + if (config_it != config_files.end()) + System::println(" find_package(%s CONFIG REQUIRED)", config_it->second); + else + System::println(" find_package(%s CONFIG REQUIRED)", library_target_pair.first); + + std::sort(library_target_pair.second.begin(), + library_target_pair.second.end(), + [](const std::string& l, const std::string& r) { + if (l.size() < r.size()) return true; + if (l.size() > r.size()) return false; + return l < r; + }); + if (library_target_pair.second.size() <= 4) { - System::println(" find_package(%s REQUIRED)\n" - " target_link_libraries(main PRIVATE %s)\n", - library_target_pair.first, + System::println(" target_link_libraries(main PRIVATE %s)\n", Strings::join(" ", library_target_pair.second)); } else @@ -509,10 +536,8 @@ namespace vcpkg::Install auto omitted = library_target_pair.second.size() - 4; library_target_pair.second.erase(library_target_pair.second.begin() + 4, library_target_pair.second.end()); - System::println(" find_package(%s REQUIRED)\n" - " # Note: %zd targets were omitted\n" + System::println(" # Note: %zd target(s) were omitted.\n" " target_link_libraries(main PRIVATE %s)\n", - library_target_pair.first, omitted, Strings::join(" ", library_target_pair.second)); } -- cgit v1.2.3 From 2a73e133448c14738271e8b0227c8b2eb4992ea3 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 22 May 2018 17:14:30 -0700 Subject: Direct-init instead of copy-init --- toolsrc/src/vcpkg/commands.fetch.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index c88ae9dd0..33c5c1dcc 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -816,7 +816,7 @@ namespace vcpkg::Commands::Fetch paths_examined.push_back(dumpbin_path); if (fs.exists(dumpbin_path)) { - const Toolset v141toolset = Toolset{ + const Toolset v141toolset{ vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}; auto english_language_pack = dumpbin_path.parent_path() / "1033"; @@ -831,12 +831,12 @@ namespace vcpkg::Commands::Fetch if (v140_is_available) { - const Toolset v140toolset = Toolset{vs_instance.root_path, - dumpbin_path, - vcvarsall_bat, - {"-vcvars_ver=14.0"}, - V_140, - supported_architectures}; + const Toolset v140toolset{vs_instance.root_path, + dumpbin_path, + vcvarsall_bat, + {"-vcvars_ver=14.0"}, + V_140, + supported_architectures}; found_toolsets.push_back(v140toolset); } -- cgit v1.2.3