aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authorBarath Kannan <barathsotd@gmail.com>2017-11-06 00:33:04 +1100
committerBarath Kannan <barathsotd@gmail.com>2017-11-06 00:33:04 +1100
commitb959f70a9969551a132d691fbd12046d5ea0702e (patch)
treed15d129bd480b1ba173322a0e50140ccf1ff487a /toolsrc/src
parent3a5b383bbec74dbaf0f1056e1a5d315e43d79375 (diff)
parent330b8d8bab6a3d07165bf7c05fea09a8e0d56348 (diff)
downloadvcpkg-b959f70a9969551a132d691fbd12046d5ea0702e.tar.gz
vcpkg-b959f70a9969551a132d691fbd12046d5ea0702e.zip
merge from master
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/tests.arguments.cpp11
-rw-r--r--toolsrc/src/tests.installplan.cpp40
-rw-r--r--toolsrc/src/tests.packagespec.cpp34
-rw-r--r--toolsrc/src/tests.paragraph.cpp30
-rw-r--r--toolsrc/src/tests.statusparagraphs.cpp85
-rw-r--r--toolsrc/src/vcpkg.cpp4
-rw-r--r--toolsrc/src/vcpkg/base/strings.cpp21
-rw-r--r--toolsrc/src/vcpkg/base/system.cpp40
-rw-r--r--toolsrc/src/vcpkg/binaryparagraph.cpp4
-rw-r--r--toolsrc/src/vcpkg/build.cpp55
-rw-r--r--toolsrc/src/vcpkg/commands.autocomplete.cpp43
-rw-r--r--toolsrc/src/vcpkg/commands.buildexternal.cpp20
-rw-r--r--toolsrc/src/vcpkg/commands.cache.cpp16
-rw-r--r--toolsrc/src/vcpkg/commands.ci.cpp95
-rw-r--r--toolsrc/src/vcpkg/commands.contact.cpp12
-rw-r--r--toolsrc/src/vcpkg/commands.cpp2
-rw-r--r--toolsrc/src/vcpkg/commands.create.cpp15
-rw-r--r--toolsrc/src/vcpkg/commands.dependinfo.cpp12
-rw-r--r--toolsrc/src/vcpkg/commands.edit.cpp21
-rw-r--r--toolsrc/src/vcpkg/commands.env.cpp12
-rw-r--r--toolsrc/src/vcpkg/commands.hash.cpp15
-rw-r--r--toolsrc/src/vcpkg/commands.import.cpp14
-rw-r--r--toolsrc/src/vcpkg/commands.integrate.cpp42
-rw-r--r--toolsrc/src/vcpkg/commands.list.cpp25
-rw-r--r--toolsrc/src/vcpkg/commands.owns.cpp15
-rw-r--r--toolsrc/src/vcpkg/commands.portsdiff.cpp15
-rw-r--r--toolsrc/src/vcpkg/commands.search.cpp37
-rw-r--r--toolsrc/src/vcpkg/commands.version.cpp11
-rw-r--r--toolsrc/src/vcpkg/dependencies.cpp68
-rw-r--r--toolsrc/src/vcpkg/export.cpp93
-rw-r--r--toolsrc/src/vcpkg/help.cpp111
-rw-r--r--toolsrc/src/vcpkg/install.cpp202
-rw-r--r--toolsrc/src/vcpkg/packagespec.cpp8
-rw-r--r--toolsrc/src/vcpkg/remove.cpp52
-rw-r--r--toolsrc/src/vcpkg/statusparagraphs.cpp26
-rw-r--r--toolsrc/src/vcpkg/update.cpp11
-rw-r--r--toolsrc/src/vcpkg/vcpkgcmdarguments.cpp145
-rw-r--r--toolsrc/src/vcpkg/vcpkgpaths.cpp85
38 files changed, 1026 insertions, 521 deletions
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<CommandSetting, 1> settings = { {{"--a", ""}} };
+ CommandStructure cmdstruct = { "", 0, SIZE_MAX, {{}, settings }, nullptr };
+
std::vector<std::string> 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<CommandSwitch, 2> switches = { {{"--a", ""}, {"--c", ""}} };
+ std::array<CommandSetting, 2> settings = { { {"--b", ""}, {"--d", ""}} };
+ CommandStructure cmdstruct = {"", 0, SIZE_MAX, {switches, settings}, nullptr};
+
std::vector<std::string> 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/tests.installplan.cpp b/toolsrc/src/tests.installplan.cpp
index 120009db5..129926317 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<int>(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<int>(t));
}
}
}
@@ -460,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);
@@ -483,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<std::unique_ptr<StatusParagraph>> 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);
+ }
};
-} \ No newline at end of file
+}
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 <vcpkg/paragraphs.h>
#include <vcpkg/base/strings.h>
+#include <vcpkg/base/util.h>
#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/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/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 <CppUnitTest.h>
+
+#include <vcpkg/base/util.h>
+#include <vcpkg/paragraphs.h>
+#include <vcpkg/statusparagraph.h>
+#include <vcpkg/statusparagraphs.h>
+
+using namespace Microsoft::VisualStudio::CppUnitTestFramework;
+
+using namespace vcpkg;
+using namespace vcpkg::Paragraphs;
+
+namespace UnitTest1
+{
+ class StatusParagraphsTests : public TestClass<StatusParagraphsTests>
+ {
+ 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<StatusParagraph>(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<StatusParagraph>(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<StatusParagraph>(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.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
diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp
index af41eed9a..27cfcbe71 100644
--- a/toolsrc/src/vcpkg/base/strings.cpp
+++ b/toolsrc/src/vcpkg/base/strings.cpp
@@ -114,24 +114,29 @@ namespace vcpkg::Strings
#endif
}
- void trim(std::string* s)
+ std::string replace_all(std::string&& s, const std::string& search, const std::string& rep)
{
- 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));
+ 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);
}
- std::string trimmed(const std::string& s)
+ std::string trim(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<std::string>* 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/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp
index b04f79414..47096ed63 100644
--- a/toolsrc/src/vcpkg/base/system.cpp
+++ b/toolsrc/src/vcpkg/base/system.cpp
@@ -3,6 +3,7 @@
#include <vcpkg/base/checks.h>
#include <vcpkg/base/system.h>
#include <vcpkg/globalstate.h>
+#include <vcpkg/metrics.h>
#include <time.h>
@@ -269,11 +270,46 @@ namespace vcpkg::System
#endif
}
- std::string create_powershell_script_cmd(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
- 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);
+
+ 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;
}
void println() { putchar('\n'); }
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');
}
}
diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp
index cf16c8f9c..ca0712a06 100644
--- a/toolsrc/src/vcpkg/build.cpp
+++ b/toolsrc/src/vcpkg/build.cpp
@@ -28,13 +28,13 @@ 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 std::unordered_set<std::string>& 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 (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));
@@ -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<std::string> 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);
@@ -87,6 +85,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));
@@ -97,17 +97,32 @@ namespace vcpkg::Build::Command
Checks::exit_success(VCPKG_LINE_INFO);
}
+ static const std::array<CommandSwitch, 1> 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);
- const std::unordered_set<std::string> options =
- args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY});
- perform_and_exit(spec, paths.port_dir(spec.package_spec), options, paths);
+ if (!spec.features.empty() && !GlobalState::feature_packages)
+ {
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO, "Feature packages are experimentally available under the --featurepackages flag.");
+ }
+ perform_and_exit_ex(spec, paths.port_dir(spec.package_spec), options, paths);
}
}
@@ -365,6 +380,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 +388,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);
}
}
@@ -472,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<std::string> lines = Strings::split(ec_data.output, "\n");
diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp
index addb9edaf..0df7ec5eb 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<std::string> valid_commands = {
+ // First try public commands
+ std::vector<std::string> 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<std::string> 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:<triplet>
@@ -100,9 +121,9 @@ 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},
+ CommandEntry{"integrate", R"###(^integrate(\s+)(\S*)$)###", Integrate::COMMAND_STRUCTURE},
};
for (auto&& command : COMMANDS)
@@ -112,20 +133,26 @@ namespace vcpkg::Commands::Autocomplete
const auto prefix = match[2].str();
std::vector<std::string> 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; });
+ 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) {
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());
diff --git a/toolsrc/src/vcpkg/commands.buildexternal.cpp b/toolsrc/src/vcpkg/commands.buildexternal.cpp
index 3991beb62..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 std::unordered_set<std::string> 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 77f0a20f6..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<BinaryParagraph> 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 1c98d1d83..dce294004 100644
--- a/toolsrc/src/vcpkg/commands.ci.cpp
+++ b/toolsrc/src/vcpkg/commands.ci.cpp
@@ -1,6 +1,5 @@
#include "pch.h"
-#include <vcpkg/base/chrono.h>
#include <vcpkg/base/files.h>
#include <vcpkg/base/system.h>
#include <vcpkg/base/util.h>
@@ -10,7 +9,6 @@
#include <vcpkg/help.h>
#include <vcpkg/input.h>
#include <vcpkg/install.h>
-#include <vcpkg/paragraphs.h>
#include <vcpkg/vcpkglib.h>
namespace vcpkg::Commands::CI
@@ -19,43 +17,92 @@ namespace vcpkg::Commands::CI
using Dependencies::InstallPlanAction;
using Dependencies::InstallPlanType;
- static std::vector<PackageSpec> load_all_package_specs(Files::Filesystem& fs,
- const fs::path& ports_directory,
- const Triplet& triplet)
+ static Install::InstallSummary run_ci_on_triplet(const Triplet& triplet,
+ const VcpkgPaths& paths,
+ const std::vector<std::string>& ports,
+ const std::set<std::string>& exclusions_set)
{
- 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<PackageSpec> specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet);
+
+ const std::vector<PackageSpec> specs = PackageSpec::to_package_specs(ports, triplet);
StatusParagraphs status_db = database_load_check(paths);
const auto& paths_port_file = Dependencies::PathsPortFile(paths);
std::vector<InstallPlanAction> 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};
const std::vector<Dependencies::AnyAction> 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));
});
- 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::KeepGoing::YES, paths, status_db);
+ }
+
+ struct TripletAndSummary
+ {
+ Triplet triplet;
+ Install::InstallSummary summary;
+ };
+
+ static const std::string OPTION_EXCLUDE = "--exclude";
+
+ static const std::array<CommandSetting, 1> 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)
+ {
+ const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
+ const std::vector<std::string> exclusions = Strings::split(options.settings.at(OPTION_EXCLUDE), ",");
+ const std::set<std::string> exclusions_set(exclusions.cbegin(), exclusions.cend());
+
+ std::vector<Triplet> 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);
+ }
+
+ const std::vector<std::string> ports = Install::get_all_port_names(paths);
+ std::vector<TripletAndSummary> results;
+ for (const Triplet& triplet : triplets)
+ {
+ Install::InstallSummary summary = run_ci_on_triplet(triplet, paths, ports, exclusions_set);
+ 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/commands.contact.cpp b/toolsrc/src/vcpkg/commands.contact.cpp
index 421b8a230..5d62faeea 100644
--- a/toolsrc/src/vcpkg/commands.contact.cpp
+++ b/toolsrc/src/vcpkg/commands.contact.cpp
@@ -2,6 +2,7 @@
#include <vcpkg/base/system.h>
#include <vcpkg/commands.h>
+#include <vcpkg/help.h>
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<const PackageNameAndFunction<CommandTypeA>> get_available_commands_type_a()
{
static std::vector<PackageNameAndFunction<CommandTypeA>> t = {
- {"install", &Install::perform_and_exit},
+ PackageNameAndFunction<CommandTypeA>{"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 85763f25e..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 89c7e0c7f..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<std::unique_ptr<SourceControlFile>> 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..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<std::string, 1> SWITCHES = {
- OPTION_BUILDTREES,
- };
- static const std::array<std::string, 0> SETTINGS;
-
static std::vector<std::string> 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<CommandSwitch, 1> 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,10 +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 std::unordered_set<std::string> 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;
@@ -95,7 +90,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..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 4bc58b509..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 119aee022..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 0d185476e..31b9ec722 100644
--- a/toolsrc/src/vcpkg/commands.integrate.cpp
+++ b/toolsrc/src/vcpkg/commands.integrate.cpp
@@ -93,9 +93,9 @@ namespace vcpkg::Commands::Integrate
</package>
)";
- 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:
@@ -326,24 +326,42 @@ 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 std::vector<std::string> 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,
+ {},
+ &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] == "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);
}
diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp
index d0e8e00b4..1f2387843 100644
--- a/toolsrc/src/vcpkg/commands.list.cpp
+++ b/toolsrc/src/vcpkg/commands.list.cpp
@@ -24,14 +24,23 @@ namespace vcpkg::Commands::List
}
}
+ static const std::array<CommandSwitch, 1> 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 std::unordered_set<std::string> 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<StatusParagraph*> installed_packages = get_installed_ports(status_paragraphs);
@@ -52,7 +61,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 +75,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..52249187b 100644
--- a/toolsrc/src/vcpkg/commands.owns.cpp
+++ b/toolsrc/src/vcpkg/commands.owns.cpp
@@ -23,15 +23,20 @@ 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);
- 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..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 3ba8707de..01291ddfb 100644
--- a/toolsrc/src/vcpkg/commands.search.cpp
+++ b/toolsrc/src/vcpkg/commands.search.cpp
@@ -79,18 +79,29 @@ namespace vcpkg::Commands::Search
}
}
+ static std::array<CommandSwitch, 2> 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 std::unordered_set<std::string> 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);
- 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 +112,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 +129,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 +140,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..3f44cf1a2 100644
--- a/toolsrc/src/vcpkg/commands.version.cpp
+++ b/toolsrc/src/vcpkg/commands.version.cpp
@@ -2,6 +2,7 @@
#include <vcpkg/base/system.h>
#include <vcpkg/commands.h>
+#include <vcpkg/help.h>
#include <vcpkg/metrics.h>
#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/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp
index 02b2ec785..6f599afd4 100644
--- a/toolsrc/src/vcpkg/dependencies.cpp
+++ b/toolsrc/src/vcpkg/dependencies.cpp
@@ -112,33 +112,41 @@ namespace vcpkg::Dependencies
std::vector<PackageSpec> AnyParagraph::dependencies(const Triplet& triplet) const
{
- auto to_package_specs = [&](const std::vector<std::string>& 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,
"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)
@@ -611,10 +619,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);
+ }
+ 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);
+ 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});
}
diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp
index 5e27d4126..9b86863eb 100644
--- a/toolsrc/src/vcpkg/export.cpp
+++ b/toolsrc/src/vcpkg/export.cpp
@@ -4,6 +4,7 @@
#include <vcpkg/base/util.h>
#include <vcpkg/commands.h>
#include <vcpkg/dependencies.h>
+#include <vcpkg/export.h>
#include <vcpkg/export.ifw.h>
#include <vcpkg/help.h>
#include <vcpkg/input.h>
@@ -44,12 +45,12 @@ namespace vcpkg::Export
</package>
)";
- 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;
}
@@ -68,6 +69,8 @@ namespace vcpkg::Export
{
static constexpr std::array<ExportPlanType, 2> 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 +83,7 @@ namespace vcpkg::Export
std::vector<const ExportPlanAction*> 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)
@@ -255,51 +258,57 @@ namespace vcpkg::Export
std::vector<PackageSpec> 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<CommandSwitch, 6> 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<CommandSetting, 7> 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, "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 = {
+ 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();
@@ -311,7 +320,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 2a0578211..c83f0277b 100644
--- a/toolsrc/src/vcpkg/help.cpp
+++ b/toolsrc/src/vcpkg/help.cpp
@@ -2,15 +2,68 @@
#include <vcpkg/base/system.h>
#include <vcpkg/commands.h>
+#include <vcpkg/export.h>
+#include <vcpkg/help.h>
+#include <vcpkg/install.h>
+#include <vcpkg/remove.h>
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<const CommandStructure& S>
+ 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<Topic, 12> topics = {{
+ {"create", command_topic_fn<Commands::Create::COMMAND_STRUCTURE>},
+ {"edit", command_topic_fn<Commands::Edit::COMMAND_STRUCTURE>},
+ {"env", command_topic_fn<Commands::Env::COMMAND_STRUCTURE>},
+ {"export", command_topic_fn<Export::COMMAND_STRUCTURE>},
+ {"help", command_topic_fn<Help::COMMAND_STRUCTURE>},
+ {"install", command_topic_fn<Install::COMMAND_STRUCTURE>},
+ {"integrate", integrate_topic_fn},
+ {"list", command_topic_fn<Commands::List::COMMAND_STRUCTURE>},
+ {"owns", command_topic_fn<Commands::Owns::COMMAND_STRUCTURE>},
+ {"remove", command_topic_fn<Remove::COMMAND_STRUCTURE>},
+ {"search", command_topic_fn<Commands::Search::COMMAND_STRUCTURE>},
+ {"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] <pkgs>...\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=<id> Specify the id for the exported NuGet package\n"
- " --nuget-version=<ver> 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,15 +124,9 @@ namespace vcpkg::Help
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({});
+ args.parse_arguments(COMMAND_STRUCTURE);
if (args.command_arguments.empty())
{
@@ -105,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/install.cpp b/toolsrc/src/vcpkg/install.cpp
index adbd8c943..20ffd3164 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);
}
}();
@@ -342,16 +341,23 @@ 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);
}
- static void print_plan(const std::vector<AnyAction>& action_plan, bool is_recursive)
+ static void print_plan(const std::vector<AnyAction>& action_plan, const bool is_recursive)
{
std::vector<const RemovePlanAction*> remove_plans;
std::vector<const InstallPlanAction*> rebuilt_plans;
std::vector<const InstallPlanAction*> only_install_plans;
std::vector<const InstallPlanAction*> new_plans;
std::vector<const InstallPlanAction*> already_installed_plans;
+ std::vector<const InstallPlanAction*> 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 +388,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,39 +404,40 @@ 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);
+
+ static auto actions_to_output_string = [](const std::vector<const InstallPlanAction*>& 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)
{
- 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)
@@ -444,15 +452,40 @@ namespace vcpkg::Install
}
}
- void perform_and_exit_ex(const std::vector<AnyAction>& 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<BuildResult> results;
- std::vector<std::string> 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<BuildResult, int> 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<const BuildResult, int>& entry : summary)
+ {
+ System::println(" %s: %d", Build::to_string(entry.first), entry.second);
+ }
+ }
+
+ InstallSummary perform(const std::vector<AnyAction>& action_plan,
+ const KeepGoing keep_going,
+ const VcpkgPaths& paths,
+ StatusParagraphs& status_db)
+ {
+ std::vector<SpecSummary> results;
+
const auto timer = Chrono::ElapsedTime::create_started();
size_t counter = 0;
const size_t package_count = action_plan.size();
@@ -462,23 +495,22 @@ 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())
{
- 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));
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 +522,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<BuildResult, int> 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<const BuildResult, int>& 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";
@@ -530,16 +535,16 @@ namespace vcpkg::Install
static const std::string OPTION_RECURSE = "--recurse";
static const std::string OPTION_KEEP_GOING = "--keep-going";
- static const std::array<std::string, 5> INSTALL_SWITCHES = {
- OPTION_DRY_RUN,
- OPTION_USE_HEAD_VERSION,
- OPTION_NO_DOWNLOADS,
- OPTION_RECURSE,
- OPTION_KEEP_GOING,
- };
+ static const std::array<CommandSwitch, 5> 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<std::string, 0> INSTALL_SETTINGS;
- static std::vector<std::string> valid_arguments(const VcpkgPaths& paths)
+ std::vector<std::string> get_all_port_names(const VcpkgPaths& paths)
{
auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports);
@@ -548,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,
- &valid_arguments,
+ {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<FullPackageSpec> 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)
@@ -576,14 +579,11 @@ namespace vcpkg::Install
}
}
- const std::unordered_set<std::string> 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 PrintSummary print_summary = to_print_summary(keep_going == KeepGoing::YES);
+ 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);
@@ -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<std::string, SourceControlFile> scf_map;
std::vector<AnyAction> action_plan;
if (GlobalState::feature_packages)
{
- std::unordered_map<std::string, SourceControlFile> scf_map;
auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
for (auto&& port : all_ports)
{
@@ -613,6 +614,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");
@@ -634,8 +645,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, 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") {}
}
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> PackageSpec::to_package_specs(const std::vector<std::string>& 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; }
diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp
index 2ec32855a..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<std::string, 5> REMOVE_SWITCHES = {
- OPTION_PURGE,
- OPTION_NO_PURGE,
- OPTION_RECURSE,
- OPTION_DRY_RUN,
- OPTION_OUTDATED,
- };
- static const std::array<std::string, 0> REMOVE_SETTINGS;
+ static const std::array<CommandSwitch, 5> 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<std::string> 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,
- REMOVE_SWITCHES,
- REMOVE_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 std::unordered_set<std::string> 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<PackageSpec> specs;
- if (options.find(OPTION_OUTDATED) != options.cend())
+ 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,26 +217,30 @@ 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)
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.");
- 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);
- 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<RemovePlanAction> 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/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<std::unique_ptr<StatusParagraph>>&& 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<StatusParagraph>& 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<StatusParagraph>& pgh) {
- const PackageSpec& spec = pgh->package.spec;
- return spec.name() == name && spec.triplet() == triplet;
- });
- }
-
std::vector<std::unique_ptr<StatusParagraph>*> 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<StatusParagraph>& 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
{
diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp
index 168949bc1..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..671a89892 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<std::string> 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<std::string>& valid_switches, const std::vector<std::string>& 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,38 @@ namespace vcpkg
{
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 <t>");
- System::println(" --vcpkg-root <path>");
+ System::println();
+ failed = true;
+ }
+ if (failed)
+ {
+ display_usage(command_structure);
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
+ void display_usage(const CommandStructure& command_structure)
{
- 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)
+ if (!command_structure.example_text.empty())
{
- 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);
+ System::println("%s", command_structure.example_text);
}
- }
- 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("Options:");
+ for (auto&& option : command_structure.options.switches)
{
- 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);
+ System::println(" %-40s %s", option.name, option.short_help_text);
}
- }
-
- 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)
+ for (auto&& option : command_structure.options.settings)
{
- 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);
+ System::println(" %-40s %s", (option.name + "=..."), option.short_help_text);
}
+ System::println(" %-40s %s", "--triplet <t>", "Set the default triplet for unqualified packages");
+ System::println(" %-40s %s",
+ "--vcpkg-root <path>",
+ "Specify the vcpkg directory to use instead of current directory or tool directory");
}
}
diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp
index 90f9cb00b..a553f4199 100644
--- a/toolsrc/src/vcpkg/vcpkgpaths.cpp
+++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp
@@ -62,6 +62,23 @@ namespace vcpkg
return nullopt;
}
+ static std::vector<std::string> keep_data_lines(const std::string& data_blob)
+ {
+ static const std::regex DATA_LINE_REGEX(R"(<sol>::(.+?)(?=::<eol>))");
+
+ std::vector<std::string> 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,
@@ -74,25 +91,15 @@ 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);
- 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<std::string> dependency_path = keep_data_lines(output);
+ Checks::check_exit(
+ VCPKG_LINE_INFO, dependency_path.size() == 1, "Expected dependency path, but got %s", output);
- const fs::path actual_downloaded_path = Strings::trimmed(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,
@@ -105,10 +112,10 @@ namespace vcpkg
static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder)
{
- static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 9, 3};
+ static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 9, 5};
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.5-win32-x86" / "bin" / "cmake.exe";
const std::vector<fs::path> from_path = Files::find_from_PATH("cmake");
std::vector<fs::path> candidate_paths;
@@ -131,9 +138,9 @@ namespace vcpkg
fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder)
{
- static constexpr std::array<int, 3> EXPECTED_VERSION = {4, 3, 0};
+ static constexpr std::array<int, 3> 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<fs::path> from_path = Files::find_from_PATH("nuget");
std::vector<fs::path> candidate_paths;
@@ -151,10 +158,10 @@ namespace vcpkg
fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder)
{
- static constexpr std::array<int, 3> EXPECTED_VERSION = {2, 14, 1};
+ static constexpr std::array<int, 3> EXPECTED_VERSION = {2, 15, 0};
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.15.0-32-bit" / "cmd" / "git.exe";
const std::vector<fs::path> from_path = Files::find_from_PATH("git");
std::vector<fs::path> candidate_paths;
@@ -324,20 +331,34 @@ namespace vcpkg
static std::vector<VisualStudioInstance> 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);
- 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<std::string> instances_as_strings = Strings::split(ec_data.output, "\n");
- std::vector<VisualStudioInstance> output;
+ const std::vector<std::string> 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<VisualStudioInstance> instances;
for (const std::string& instance_as_string : instances_as_strings)
{
const std::vector<std::string> split = Strings::split(instance_as_string, "::");
- output.push_back({split.at(3), split.at(2), split.at(1), split.at(0)});
+ 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 output;
+ return instances;
}
static std::vector<Toolset> find_toolset_instances(const VcpkgPaths& paths)