From 307b761df4197bf9cf1b69652808530e6219a868 Mon Sep 17 00:00:00 2001 From: Daniel Shaw Date: Tue, 25 Jul 2017 21:29:31 -0700 Subject: partial end to end feature packages hdf5 added vcpkg feature package support to other commands remove comments change qualifier bracket to parens added features to qualified dependencies --- toolsrc/include/BinaryParagraph.h | 6 ++ toolsrc/include/Paragraphs.h | 2 +- toolsrc/include/SourceParagraph.h | 15 ++- toolsrc/include/StatusParagraphs.h | 3 + toolsrc/include/vcpkg_Commands.h | 2 +- toolsrc/include/vcpkg_Dependencies.h | 5 +- toolsrc/src/BinaryParagraph.cpp | 12 ++- toolsrc/src/Paragraphs.cpp | 16 ++- toolsrc/src/SourceParagraph.cpp | 57 +++++++++- toolsrc/src/StatusParagraphs.cpp | 26 ++++- toolsrc/src/commands_depends.cpp | 2 +- toolsrc/src/commands_install.cpp | 200 ++++++++++++++++++++++++++++++----- toolsrc/src/commands_remove.cpp | 27 +++-- toolsrc/src/commands_search.cpp | 2 +- toolsrc/src/test_install_plan.cpp | 50 ++++++++- toolsrc/src/tests_dependencies.cpp | 2 +- toolsrc/src/tests_paragraph.cpp | 28 +++-- toolsrc/src/vcpkg_Build.cpp | 46 +++++--- toolsrc/src/vcpkg_Dependencies.cpp | 52 ++++++--- toolsrc/src/vcpkglib.cpp | 2 +- 20 files changed, 459 insertions(+), 96 deletions(-) diff --git a/toolsrc/include/BinaryParagraph.h b/toolsrc/include/BinaryParagraph.h index 1e12dd8a6..61e03343a 100644 --- a/toolsrc/include/BinaryParagraph.h +++ b/toolsrc/include/BinaryParagraph.h @@ -31,5 +31,11 @@ namespace vcpkg std::vector depends; }; + struct BinaryControlFile + { + BinaryParagraph core_paragraph; + std::vector features; + }; + void serialize(const BinaryParagraph& pgh, std::string& out_str); } \ No newline at end of file diff --git a/toolsrc/include/Paragraphs.h b/toolsrc/include/Paragraphs.h index 60f509266..aae46f7da 100644 --- a/toolsrc/include/Paragraphs.h +++ b/toolsrc/include/Paragraphs.h @@ -20,7 +20,7 @@ namespace vcpkg::Paragraphs Parse::ParseExpected try_load_port(const Files::Filesystem& fs, const fs::path& control_path); - Expected try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec); + Expected try_load_cached_control_package(const VcpkgPaths& paths, const PackageSpec& spec); struct LoadResults { diff --git a/toolsrc/include/SourceParagraph.h b/toolsrc/include/SourceParagraph.h index 7ddf999cc..fee61c3e8 100644 --- a/toolsrc/include/SourceParagraph.h +++ b/toolsrc/include/SourceParagraph.h @@ -15,13 +15,24 @@ namespace vcpkg struct Triplet; - struct Dependency + struct Features { std::string name; + std::vector features; + }; + + Features parse_feature_list(const std::string& name); + + struct Dependency + { + Features depend; std::string qualifier; + + std::string name() const; + static Dependency parse_dependency(std::string name, std::string qualifier); }; - const std::string& to_string(const Dependency& dep); + const std::string to_string(const Dependency& dep); struct FeatureParagraph { diff --git a/toolsrc/include/StatusParagraphs.h b/toolsrc/include/StatusParagraphs.h index 2af177219..bf2ef2f3e 100644 --- a/toolsrc/include/StatusParagraphs.h +++ b/toolsrc/include/StatusParagraphs.h @@ -17,6 +17,9 @@ namespace vcpkg const_iterator find(const PackageSpec& spec) const { return find(spec.name(), spec.triplet()); } const_iterator find(const std::string& name, const Triplet& triplet) const; iterator find(const std::string& name, const Triplet& triplet); + std::vector*> StatusParagraphs::find_all(const std::string& name, + const Triplet& triplet); + iterator find(const std::string& name, const Triplet& triplet, const std::string& feature); const_iterator find_installed(const PackageSpec& spec) const { diff --git a/toolsrc/include/vcpkg_Commands.h b/toolsrc/include/vcpkg_Commands.h index 8348a64e4..d5f316d69 100644 --- a/toolsrc/include/vcpkg_Commands.h +++ b/toolsrc/include/vcpkg_Commands.h @@ -59,7 +59,7 @@ namespace vcpkg::Commands const fs::path& source_dir, const InstallDir& dirs); void install_package(const VcpkgPaths& paths, - const BinaryParagraph& binary_paragraph, + const BinaryControlFile& binary_paragraph, StatusParagraphs* status_db); void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); } diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h index e3af0fd28..3fee8ef33 100644 --- a/toolsrc/include/vcpkg_Dependencies.h +++ b/toolsrc/include/vcpkg_Dependencies.h @@ -90,6 +90,7 @@ namespace vcpkg::Dependencies InstallPlanAction(InstallPlanAction&&) = default; InstallPlanAction& operator=(const InstallPlanAction&) = delete; InstallPlanAction& operator=(InstallPlanAction&&) = default; + std::string displayname() const; PackageSpec spec; AnyParagraph any_paragraph; @@ -205,7 +206,9 @@ namespace vcpkg::Dependencies std::unordered_map& pkg_to_cluster, GraphPlan& graph_plan); void mark_minus(Cluster& cluster, std::unordered_map& pkg_to_cluster, GraphPlan& graph_plan); - + void mark_plus_default(Cluster& cluster, + std::unordered_map& pkg_to_cluster, + GraphPlan& graph_plan); std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db); diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index 49e9d58e5..9abd388b9 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -87,7 +87,17 @@ namespace vcpkg this->depends = filter_dependencies(fpgh.depends, triplet); } - std::string BinaryParagraph::displayname() const { return this->spec.to_string(); } + std::string BinaryParagraph::displayname() const + { + if (this->feature == "") + { + return this->spec.name() + "[core]:" + this->spec.triplet().to_string(); + } + else + { + return this->spec.name() + "[" + this->feature + "]:" + this->spec.triplet().to_string(); + } + } std::string BinaryParagraph::dir() const { return this->spec.dir(); } diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index 3749e919e..3a30f66a3 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -3,6 +3,7 @@ #include "ParagraphParseResult.h" #include "Paragraphs.h" #include "vcpkg_Files.h" +#include "vcpkg_Util.h" using namespace vcpkg::Parse; @@ -226,14 +227,21 @@ namespace vcpkg::Paragraphs return error_info; } - Expected try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec) + Expected try_load_cached_control_package(const VcpkgPaths& paths, const PackageSpec& spec) { - Expected> pghs = - get_single_paragraph(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL"); + Expected>> pghs = + get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL"); if (auto p = pghs.get()) { - return BinaryParagraph(*p); + BinaryControlFile bcf; + bcf.core_paragraph = BinaryParagraph(p->front()); + p->erase(p->begin()); + + bcf.features = + Util::fmap(*p, [&](auto&& raw_feature) -> BinaryParagraph { return BinaryParagraph(raw_feature); }); + + return bcf; } return pghs.error(); diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index a37567f3a..2aab7c572 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -152,18 +152,61 @@ namespace vcpkg return std::move(control_file); } + Features parse_feature_list(const std::string& name) + { + Features f; + int end = (int)name.find(']'); + if (end != std::string::npos) + { + int start = (int)name.find('['); + + auto feature_name_list = name.substr(start + 1, end - start - 1); + f.name = name.substr(0, start); + f.features = parse_comma_list(feature_name_list); + } + else + { + f.name = name; + } + return f; + } + + Dependency Dependency::parse_dependency(std::string name, std::string qualifier) + { + Dependency dep; + dep.qualifier = qualifier; + dep.depend = parse_feature_list(name); + return dep; + } + + std::string Dependency::name() const + { + std::string str = this->depend.name; + if (this->depend.features.empty()) return str; + + str += "["; + for (auto&& s : this->depend.features) + { + str += s + ","; + } + str.pop_back(); + str += "]"; + return str; + } + std::vector vcpkg::expand_qualified_dependencies(const std::vector& depends) { return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency { auto pos = depend_string.find(' '); - if (pos == std::string::npos) return {depend_string, ""}; + if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, ""); // expect of the form "\w+ \[\w+\]" Dependency dep; - dep.name = depend_string.substr(0, pos); + + dep.depend.name = depend_string.substr(0, pos); if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')') { // Error, but for now just slurp the entire string. - return {depend_string, ""}; + return Dependency::parse_dependency(depend_string, ""); } dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3); return dep; @@ -210,13 +253,17 @@ namespace vcpkg { if (dep.qualifier.empty() || t.canonical_name().find(dep.qualifier) != std::string::npos) { - ret.push_back(dep.name); + ret.emplace_back(dep.name()); } } return ret; } - const std::string& to_string(const Dependency& dep) { return dep.name; } + const std::string to_string(const Dependency& dep) + { + std::string name = dep.name(); + return name; + } ExpectedT> Supports::parse(const std::vector& strs) { diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp index 27f3c30a2..02ee61f75 100644 --- a/toolsrc/src/StatusParagraphs.cpp +++ b/toolsrc/src/StatusParagraphs.cpp @@ -27,6 +27,30 @@ namespace vcpkg }); } + std::vector*> StatusParagraphs::find_all(const std::string& name, + const Triplet& triplet) + { + std::vector*> spghs; + for (auto&& p : *this) + { + if (p->package.spec.name() == name && p->package.spec.triplet() == triplet) + { + spghs.emplace_back(&p); + } + } + return spghs; + } + + StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, + const Triplet& triplet, + const std::string& feature) + { + return std::find_if(begin(), end(), [&](const std::unique_ptr& pgh) { + const PackageSpec& spec = pgh->package.spec; + return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature; + }); + } + StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name, const Triplet& triplet) const { @@ -43,7 +67,7 @@ namespace vcpkg { Checks::check_exit(VCPKG_LINE_INFO, pgh != nullptr, "Inserted null paragraph"); const PackageSpec& spec = pgh->package.spec; - auto ptr = find(spec.name(), spec.triplet()); + auto ptr = find(spec.name(), spec.triplet(), pgh->package.feature); if (ptr == end()) { paragraphs.push_back(std::move(pgh)); diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index 2d1fb658b..b04af5282 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -46,7 +46,7 @@ namespace vcpkg::Commands::DependInfo for (auto&& source_control_file : source_control_files) { const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; - auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name; }); + auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name(); }); System::println("%s: %s", source_paragraph.name, s); } diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 2ce5b6c62..2965d9025 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -211,10 +211,10 @@ namespace vcpkg::Commands::Install } } - void install_package(const VcpkgPaths& paths, const BinaryParagraph& binary_paragraph, StatusParagraphs* status_db) + void install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db) { - const fs::path package_dir = paths.package_dir(binary_paragraph.spec); - const Triplet& triplet = binary_paragraph.spec.triplet(); + const fs::path package_dir = paths.package_dir(bcf.core_paragraph.spec); + const Triplet& triplet = bcf.core_paragraph.spec.triplet(); const std::vector pgh_and_files = get_installed_files(paths, *status_db); const SortedVector package_files = @@ -234,7 +234,7 @@ namespace vcpkg::Commands::Install System::println(System::Color::error, "The following files are already installed in %s and are in conflict with %s", triplet_install_path.generic_string(), - binary_paragraph.spec); + bcf.core_paragraph.spec); System::print("\n "); System::println(Strings::join("\n ", intersection)); System::println(""); @@ -242,27 +242,42 @@ namespace vcpkg::Commands::Install } StatusParagraph source_paragraph; - source_paragraph.package = binary_paragraph; + source_paragraph.package = bcf.core_paragraph; source_paragraph.want = Want::INSTALL; source_paragraph.state = InstallState::HALF_INSTALLED; - for (auto&& dep : source_paragraph.package.depends) - { - if (status_db->find_installed(dep, source_paragraph.package.spec.triplet()) == status_db->end()) - { - Checks::unreachable(VCPKG_LINE_INFO); - } - } + write_update(paths, source_paragraph); status_db->insert(std::make_unique(source_paragraph)); + std::vector features_spghs; + for (auto&& feature : bcf.features) + { + features_spghs.emplace_back(); + + StatusParagraph& feature_paragraph = features_spghs.back(); + feature_paragraph.package = feature; + feature_paragraph.want = Want::INSTALL; + feature_paragraph.state = InstallState::HALF_INSTALLED; + + write_update(paths, feature_paragraph); + status_db->insert(std::make_unique(feature_paragraph)); + } + const InstallDir install_dir = InstallDir::from_destination_root( - paths.installed, triplet.to_string(), paths.listfile_path(binary_paragraph)); + paths.installed, triplet.to_string(), paths.listfile_path(bcf.core_paragraph)); install_files_and_write_listfile(paths.get_filesystem(), package_dir, install_dir); source_paragraph.state = InstallState::INSTALLED; write_update(paths, source_paragraph); status_db->insert(std::make_unique(source_paragraph)); + + for (auto&& feature_paragraph : features_spghs) + { + feature_paragraph.state = InstallState::INSTALLED; + write_update(paths, feature_paragraph); + status_db->insert(std::make_unique(feature_paragraph)); + } } using Build::BuildResult; @@ -312,8 +327,8 @@ namespace vcpkg::Commands::Install } System::println("Building package %s... done", display_name); - const BinaryParagraph bpgh = - Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); + const BinaryControlFile bpgh = + Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); System::println("Installing package %s... ", display_name); install_package(paths, bpgh, &status_db); System::println(System::Color::success, "Installing package %s... done", display_name); @@ -322,10 +337,11 @@ namespace vcpkg::Commands::Install if (plan_type == InstallPlanType::BUILD_AND_INSTALL && g_feature_packages) { + const std::string display_name_feature = action.displayname(); if (use_head_version) - System::println("Building package %s from HEAD... ", display_name); + System::println("Building package %s from HEAD... ", display_name_feature); else - System::println("Building package %s... ", display_name); + System::println("Building package %s... ", display_name_feature); const Build::BuildPackageConfig build_config{ *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), @@ -339,13 +355,13 @@ namespace vcpkg::Commands::Install System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); return result.code; } - System::println("Building package %s... done", display_name); + System::println("Building package %s... done", display_name_feature); - const BinaryParagraph bpgh = - Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); - System::println("Installing package %s... ", display_name); - install_package(paths, bpgh, &status_db); - System::println(System::Color::success, "Installing package %s... done", display_name); + const BinaryControlFile bcf = + Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); + System::println("Installing package %s... ", display_name_feature); + install_package(paths, bcf, &status_db); + System::println(System::Color::success, "Installing package %s... done", display_name_feature); return BuildResult::SUCCEEDED; } @@ -357,7 +373,9 @@ namespace vcpkg::Commands::Install System::Color::warning, "Package %s is already built -- not building from HEAD", display_name); } System::println("Installing package %s... ", display_name); - install_package(paths, action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO), &status_db); + install_package(paths, + BinaryControlFile{action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO)}, + &status_db); System::println(System::Color::success, "Installing package %s... done", display_name); return BuildResult::SUCCEEDED; } @@ -365,11 +383,27 @@ namespace vcpkg::Commands::Install Checks::unreachable(VCPKG_LINE_INFO); } + static void print_plan(const std::vector rebuilt_plans, + const std::vector new_plans) + { + const std::string rebuilt_string = Strings::join("\n", rebuilt_plans, [](const InstallPlanAction* p) { + return Dependencies::to_output_string(p->request_type, p->displayname()); + }); + + const std::string new_string = Strings::join("\n", new_plans, [](const InstallPlanAction* p) { + return Dependencies::to_output_string(p->request_type, p->displayname()); + }); + + if (rebuilt_plans.size() > 0) System::println("The following packages will be rebuilt:\n%s", rebuilt_string); + if (new_plans.size() > 0) System::println("The following packages will be installed:\n%s", new_string); + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_USE_HEAD_VERSION = "--head"; static const std::string OPTION_NO_DOWNLOADS = "--no-downloads"; + static const std::string OPTION_RECURSE = "--recurse"; // input sanitization static const std::string example = @@ -383,14 +417,130 @@ namespace vcpkg::Commands::Install Input::check_triplet(spec.triplet(), paths); const std::unordered_set options = args.check_and_get_optional_command_arguments( - {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS}); + {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE}); const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend(); const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend(); const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); + const bool isRecursive = options.find(OPTION_RECURSE) != options.cend(); // create the plan StatusParagraphs status_db = database_load_check(paths); + if (g_feature_packages) + { + const std::vector full_specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + return Input::check_and_get_full_package_spec(arg, default_triplet, example); + }); + + std::unordered_map scf_map; + auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + for (auto&& port : all_ports.paragraphs) + { + auto pkg_spec = PackageSpec::from_name_and_triplet(port->core_paragraph->name, default_triplet) + .value_or_exit(VCPKG_LINE_INFO); + scf_map[pkg_spec] = std::move(*port); + } + std::vector action_plan = + Dependencies::create_feature_install_plan(scf_map, full_specs, status_db); + // install plan will be empty if it is already installed - need to change this at status paragraph part + Checks::check_exit( + VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty for feature packages"); + + const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), + Build::to_allow_downloads(!no_downloads)}; + + std::vector remove_plans; + + std::vector rebuilt_plans; + std::vector new_plans; + + // removal will happen before install + for (auto&& action : action_plan) + { + if (auto install_action = action.install_plan.get()) + { + auto it = Util::find_if( + remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); + if (it != remove_plans.end()) + { + rebuilt_plans.emplace_back(install_action); + } + else + { + new_plans.emplace_back(install_action); + } + } + else if (auto remove_action = action.remove_plan.get()) + { + remove_plans.emplace_back(remove_action); + } + } + + print_plan(rebuilt_plans, new_plans); + + if (remove_plans.size() > 0 && !isRecursive) + { + System::println(System::Color::warning, + "If you are sure you want to rebuild the above packages, run the command with the " + "--recurse option"); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + // execute the plan + for (const Dependencies::AnyAction& any_action : action_plan) + { + if (auto install_action = any_action.install_plan.get()) + { + const BuildResult result = + perform_install_plan_action(paths, *install_action, install_plan_options, status_db); + if (result != BuildResult::SUCCEEDED) + { + System::println(Build::create_user_troubleshooting_message(install_action->spec)); + Checks::exit_fail(VCPKG_LINE_INFO); + } + } + else if (auto remove_action = any_action.remove_plan.get()) + { + static const std::string OPTION_PURGE = "--purge"; + static const std::string OPTION_NO_PURGE = "--no-purge"; + + const bool alsoRemoveFolderFromPackages = options.find(OPTION_NO_PURGE) == options.end(); + if (options.find(OPTION_PURGE) != options.end() && !alsoRemoveFolderFromPackages) + { + // User specified --purge and --no-purge + System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); + System::print(example); + Checks::exit_fail(VCPKG_LINE_INFO); + } + const std::string display_name = remove_action->spec.to_string(); + switch (remove_action->plan_type) + { + case RemovePlanType::NOT_INSTALLED: + System::println(System::Color::success, "Package %s is not installed", display_name); + break; + case RemovePlanType::REMOVE: + System::println("Removing package %s... ", display_name); + Commands::Remove::remove_package(paths, remove_action->spec, &status_db); + System::println(System::Color::success, "Removing package %s... done", display_name); + break; + case RemovePlanType::UNKNOWN: + default: Checks::unreachable(VCPKG_LINE_INFO); + } + + if (alsoRemoveFolderFromPackages) + { + System::println("Purging package %s... ", display_name); + Files::Filesystem& fs = paths.get_filesystem(); + std::error_code ec; + fs.remove_all(paths.packages / remove_action->spec.dir(), ec); + System::println(System::Color::success, "Purging package %s... done", display_name); + } + } + } + + Checks::exit_success(VCPKG_LINE_INFO); + } + Dependencies::PathsPortFile paths_port_file(paths); std::vector install_plan = Dependencies::create_install_plan(paths_port_file, specs, status_db); diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index eabf2b9ae..e480f02dd 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -17,13 +17,19 @@ namespace vcpkg::Commands::Remove void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db) { auto& fs = paths.get_filesystem(); - StatusParagraph& pkg = **status_db->find(spec.name(), spec.triplet()); + auto spghs = status_db->find_all(spec.name(), spec.triplet()); + auto core_pkg = **status_db->find(spec.name(), spec.triplet(), ""); - pkg.want = Want::PURGE; - pkg.state = InstallState::HALF_INSTALLED; - write_update(paths, pkg); + for (auto&& spgh : spghs) + { + StatusParagraph& pkg = **spgh; + if (pkg.state != InstallState::INSTALLED) continue; + pkg.want = Want::PURGE; + pkg.state = InstallState::HALF_INSTALLED; + write_update(paths, pkg); + } - auto maybe_lines = fs.read_lines(paths.listfile_path(pkg.package)); + auto maybe_lines = fs.read_lines(paths.listfile_path(core_pkg.package)); if (auto lines = maybe_lines.get()) { @@ -80,11 +86,16 @@ namespace vcpkg::Commands::Remove } } - fs.remove(paths.listfile_path(pkg.package)); + fs.remove(paths.listfile_path(core_pkg.package)); } - pkg.state = InstallState::NOT_INSTALLED; - write_update(paths, pkg); + for (auto&& spgh : spghs) + { + StatusParagraph& pkg = **spgh; + if (pkg.state != InstallState::HALF_INSTALLED) continue; + pkg.state = InstallState::NOT_INSTALLED; + write_update(paths, pkg); + } } static void print_plan(const std::map>& group_by_plan_type) diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index fee99a5db..f12c25fb6 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -39,7 +39,7 @@ namespace vcpkg::Commands::Search s.append(Strings::format("%s;", name)); for (const Dependency& d : source_paragraph.depends) { - const std::string dependency_name = replace_dashes_with_underscore(d.name); + const std::string dependency_name = replace_dashes_with_underscore(d.name()); s.append(Strings::format("%s -> %s;", name, dependency_name)); } } diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index d02af5662..347998723 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -347,13 +347,13 @@ namespace UnitTest1 spec_map.get_package_spec( {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}}, {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[1]"}}, - {{"Feature", "2"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[2]"}}, - {{"Feature", "3"}, {"Description", "the first feature for a"}, {"Build-Depends", "a[2]"}}}), + {{"Feature", "2"}, {"Description", "the second feature for a"}, {"Build-Depends", "b[2]"}}, + {{"Feature", "3"}, {"Description", "the third feature for a"}, {"Build-Depends", "a[2]"}}}), {"3"}}; auto spec_b = FullPackageSpec{spec_map.get_package_spec({ {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, - {{"Feature", "2"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, + {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, })}; auto install_plan = Dependencies::create_feature_install_plan( @@ -434,7 +434,7 @@ namespace UnitTest1 {"1"}}; auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_b, spec_x}, StatusParagraphs(std::move(status_paragraphs))); + spec_map.map, {spec_b}, StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(5), install_plan.size()); remove_plan_check(&install_plan[0], "x"); @@ -523,5 +523,45 @@ namespace UnitTest1 features_check(&install_plan[6], "a", {"one", "core"}); features_check(&install_plan[7], "c", {"core"}); } + + TEST_METHOD(default_features_test) + { + using Pgh = std::unordered_map; + + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + + auto spec_a = FullPackageSpec{ + spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.3"}, {"Default-Features", "1, 2"}, {"Build-Depends", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[2]"}}, + {{"Feature", "2"}, {"Description", "the second feature for a"}, {"Build-Depends", ""}}, + {{"Feature", "3"}, {"Description", "the third feature for a"}, {"Build-Depends", ""}}}), + {""}}; + auto spec_b = FullPackageSpec{ + spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Default-Features", "1, 2"}, {"Build-Depends", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for b"}, {"Build-Depends", "c[1]"}}, + {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, + }), + {""}}; + + auto spec_c = FullPackageSpec{ + spec_map.get_package_spec({ + {{"Source", "c"}, {"Version", "1.3"}, {"Default-Features", "2"}, {"Build-Depends", ""}}, + {{"Feature", "1"}, {"Description", "the first feature for c"}, {"Build-Depends", ""}}, + {{"Feature", "2"}, {"Description", "the second feature for c"}, {"Build-Depends", ""}}, + }), + {""}}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(3), install_plan.size()); + features_check(&install_plan[0], "c", {"core", "1", "2"}); + features_check(&install_plan[1], "b", {"core", "1", "2"}); + features_check(&install_plan[2], "a", {"core", "1", "2"}); + } }; } \ No newline at end of file diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp index 7a49bdbd0..26cc1e22c 100644 --- a/toolsrc/src/tests_dependencies.cpp +++ b/toolsrc/src/tests_dependencies.cpp @@ -17,7 +17,7 @@ namespace UnitTest1 { auto v = expand_qualified_dependencies(parse_comma_list("libA (windows)")); Assert::AreEqual(size_t(1), v.size()); - Assert::AreEqual("libA", v[0].name.c_str()); + Assert::AreEqual("libA", v[0].depend.name.c_str()); Assert::AreEqual("windows", v[0].qualifier.c_str()); } diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index af4b55498..3f2760c22 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -60,7 +60,7 @@ namespace UnitTest1 Assert::AreEqual("m", pgh->core_paragraph->maintainer.c_str()); Assert::AreEqual("d", pgh->core_paragraph->description.c_str()); Assert::AreEqual(size_t(1), pgh->core_paragraph->depends.size()); - Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name.c_str()); + Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name().c_str()); Assert::AreEqual(size_t(1), pgh->core_paragraph->supports.size()); Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str()); } @@ -77,8 +77,8 @@ namespace UnitTest1 auto& pgh = *m_pgh.get(); Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); - Assert::AreEqual("z", pgh->core_paragraph->depends[0].name.c_str()); - Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name.c_str()); + Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str()); + Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str()); } TEST_METHOD(SourceParagraph_Three_Depends) @@ -93,9 +93,9 @@ namespace UnitTest1 auto& pgh = *m_pgh.get(); Assert::AreEqual(size_t(3), pgh->core_paragraph->depends.size()); - Assert::AreEqual("z", pgh->core_paragraph->depends[0].name.c_str()); - Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name.c_str()); - Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name.c_str()); + Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str()); + Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str()); + Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name().c_str()); } TEST_METHOD(SourceParagraph_Three_Supports) @@ -131,9 +131,9 @@ namespace UnitTest1 Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str()); Assert::AreEqual("", pgh->core_paragraph->description.c_str()); Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); - Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name.c_str()); + Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name().c_str()); Assert::AreEqual("windows", pgh->core_paragraph->depends[0].qualifier.c_str()); - Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name.c_str()); + Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name().c_str()); Assert::AreEqual("uwp", pgh->core_paragraph->depends[1].qualifier.c_str()); } @@ -411,6 +411,18 @@ namespace UnitTest1 Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); } + TEST_METHOD(package_spec_feature_parse_with_arch) + { + vcpkg::ExpectedT spec = + vcpkg::FullPackageSpec::from_string("zlib[feature]:x64-uwp", vcpkg::Triplet::X86_WINDOWS); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); + Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); + Assert::IsTrue(spec.get()->features.size() == 1); + Assert::AreEqual("feature", spec.get()->features.front().c_str()); + Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), + spec.get()->package_spec.triplet().canonical_name()); + } + TEST_METHOD(utf8_to_utf16) { auto str = vcpkg::Strings::to_utf16("abc"); diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index a0d690f37..124efb7f2 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -88,29 +88,37 @@ namespace vcpkg::Build return Strings::wformat(LR"("%s" %s %s %s 2>&1)", toolset.vcvarsall.native(), arch, target, tonull); } - static void create_binary_control_file(const VcpkgPaths& paths, - const SourceParagraph& source_paragraph, + static void create_binary_feature_control_file(const SourceParagraph& source_paragraph, + const FeatureParagraph& feature_paragraph, + const Triplet& triplet, + BinaryControlFile& bcf) + { + BinaryParagraph bpgh(source_paragraph, feature_paragraph, triplet); + bcf.features.emplace_back(std::move(bpgh)); + } + + static void create_binary_control_file(const SourceParagraph& source_paragraph, const Triplet& triplet, - const BuildInfo& build_info) + const BuildInfo& build_info, + BinaryControlFile& bcf) { - BinaryParagraph bpgh = BinaryParagraph(source_paragraph, triplet); + BinaryParagraph bpgh(source_paragraph, triplet); if (auto p_ver = build_info.version.get()) { bpgh.version = *p_ver; } - const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL"; - paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(bpgh)); + bcf.core_paragraph = std::move(bpgh); } - static void create_binary_feature_control_file(const VcpkgPaths& paths, - const SourceParagraph& source_paragraph, - const FeatureParagraph& feature_paragraph, - const Triplet& triplet, - const BuildInfo& build_info) + static void write_binary_control_file(const VcpkgPaths& paths, BinaryControlFile bcf) { - BinaryParagraph bpgh = BinaryParagraph(source_paragraph, feature_paragraph, triplet); - const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL"; - paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(bpgh)); + std::string start = Strings::serialize(bcf.core_paragraph); + for (auto&& feature : bcf.features) + { + start += "\n" + Strings::serialize(feature); + } + const fs::path binary_control_file = paths.packages / bcf.core_paragraph.dir() / "CONTROL"; + paths.get_filesystem().write_contents(binary_control_file, start); } ExtendedBuildResult build_package(const VcpkgPaths& paths, @@ -196,6 +204,10 @@ namespace vcpkg::Build auto build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); + BinaryControlFile bcf; + + create_binary_control_file(config.src, triplet, build_info, bcf); + if (error_count != 0) { return {BuildResult::POST_BUILD_CHECKS_FAILED, {}}; @@ -209,13 +221,13 @@ namespace vcpkg::Build for (auto&& f_pgh : config.scf->feature_paragraphs) { if (f_pgh->name == feature) - create_binary_feature_control_file( - paths, *config.scf->core_paragraph, *f_pgh, triplet, build_info); + create_binary_feature_control_file(*config.scf->core_paragraph, *f_pgh, triplet, bcf); } } } } - create_binary_control_file(paths, config.src, triplet, build_info); + + write_binary_control_file(paths, bcf); // const fs::path port_buildtrees_dir = paths.buildtrees / spec.name; // delete_directory(port_buildtrees_dir); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 820e51b33..c84ca73f3 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -101,6 +101,25 @@ namespace vcpkg::Dependencies this->plan_type = InstallPlanType::UNKNOWN; } + std::string InstallPlanAction::displayname() const + { + if (this->feature_list.empty()) + { + return this->spec.to_string(); + } + else + { + std::string features; + for (auto&& feature : this->feature_list) + { + features += feature + ","; + } + features.pop_back(); + + return this->spec.name() + "[" + features + "]:" + this->spec.triplet().to_string(); + } + } + bool InstallPlanAction::compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right) { return left->spec.name() < right->spec.name(); @@ -319,9 +338,9 @@ namespace vcpkg::Dependencies ? RequestType::USER_REQUESTED : RequestType::AUTO_SELECTED; - Expected maybe_bpgh = Paragraphs::try_load_cached_package(paths, spec); - if (auto bpgh = maybe_bpgh.get()) - return ExportPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type}; + Expected maybe_bpgh = Paragraphs::try_load_cached_control_package(paths, spec); + if (auto bcf = maybe_bpgh.get()) + return ExportPlanAction{spec, {nullopt, bcf->core_paragraph, nullopt}, request_type}; auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); if (auto scf = maybe_scf.get()) @@ -366,6 +385,20 @@ namespace vcpkg::Dependencies return f_specs; } + void mark_plus_default(Cluster& cluster, + std::unordered_map& pkg_to_cluster, + GraphPlan& graph_plan) + { + mark_plus("core", cluster, pkg_to_cluster, graph_plan); + if (auto scf = cluster.source_control_file.get()) + { + for (auto&& default_feature : (*scf)->core_paragraph->default_features) + { + mark_plus(default_feature, cluster, pkg_to_cluster, graph_plan); + } + } + } + bool mark_plus(const std::string& feature, Cluster& cluster, std::unordered_map& pkg_to_cluster, @@ -404,21 +437,12 @@ namespace vcpkg::Dependencies graph_plan.install_graph.add_vertex({&cluster}); auto& tracked = cluster.to_install_features; tracked.insert(updated_feature); - if (tracked.find("core") == tracked.end() && tracked.find("") == tracked.end()) - { - cluster.to_install_features.insert("core"); - for (auto&& depend : cluster.edges["core"].build_edges) - { - auto& depend_cluster = pkg_to_cluster[depend.spec]; - mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); - graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); - } - } for (auto&& depend : cluster.edges[updated_feature].build_edges) { auto& depend_cluster = pkg_to_cluster[depend.spec]; mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); + mark_plus_default(depend_cluster, pkg_to_cluster, graph_plan); if (&depend_cluster == &cluster) continue; graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); } @@ -448,6 +472,7 @@ namespace vcpkg::Dependencies mark_plus(original_feature, cluster, pkg_to_cluster, graph_plan); } } + std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db) @@ -515,6 +540,7 @@ namespace vcpkg::Dependencies for (auto&& spec : specs) { Cluster& spec_cluster = pkg_spec_to_package_node[spec.package_spec]; + mark_plus_default(spec_cluster, pkg_spec_to_package_node, graph_plan); for (auto&& feature : spec.features) { mark_plus(feature, spec_cluster, pkg_spec_to_package_node, graph_plan); diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 6b180b532..428ae090d 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -191,7 +191,7 @@ namespace vcpkg for (const std::unique_ptr& pgh : status_db) { - if (pgh->state != InstallState::INSTALLED) + if (pgh->state != InstallState::INSTALLED || pgh->package.feature != "") { continue; } -- cgit v1.2.3 From aab0173509c89746f8988b000854d2ed8c9115e7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 18 Aug 2017 16:22:52 -0700 Subject: [vcpkg] Fix rebase build. --- toolsrc/src/commands_depends.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index b04af5282..49e1c6c01 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -33,7 +33,7 @@ namespace vcpkg::Commands::DependInfo for (const Dependency& dependency : source_paragraph.depends) { - if (Strings::case_insensitive_ascii_contains(dependency.name, filter)) + if (Strings::case_insensitive_ascii_contains(dependency.name(), filter)) { return false; } -- cgit v1.2.3 From 4d34488649fe5d71b8a553706d960a3784c56bb1 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 18 Aug 2017 20:32:35 -0700 Subject: [vcpkg] Consolidate specifier parsing --- toolsrc/include/PackageSpec.h | 9 ++++ toolsrc/include/vcpkg_Checks.h | 7 ++- toolsrc/src/PackageSpec.cpp | 101 +++++++++++++++++++++---------------- toolsrc/src/SourceParagraph.cpp | 30 ++++++----- toolsrc/src/tests_paragraph.cpp | 61 +++++++++++++--------- toolsrc/src/vcpkg_Dependencies.cpp | 26 +++++----- 6 files changed, 139 insertions(+), 95 deletions(-) diff --git a/toolsrc/include/PackageSpec.h b/toolsrc/include/PackageSpec.h index 15b5e5b9b..77a14e90e 100644 --- a/toolsrc/include/PackageSpec.h +++ b/toolsrc/include/PackageSpec.h @@ -6,6 +6,15 @@ namespace vcpkg { + struct ParsedSpecifier + { + std::string name; + std::vector features; + std::string triplet; + + static ExpectedT from_string(const std::string& input); + }; + struct PackageSpec { static std::string to_string(const std::string& name, const Triplet& triplet); diff --git a/toolsrc/include/vcpkg_Checks.h b/toolsrc/include/vcpkg_Checks.h index 6d8ff5711..754b44f75 100644 --- a/toolsrc/include/vcpkg_Checks.h +++ b/toolsrc/include/vcpkg_Checks.h @@ -5,18 +5,23 @@ namespace vcpkg::Checks { + // Indicate that an internal error has occurred and exit the tool. This should be used when invariants have been + // broken. [[noreturn]] void unreachable(const LineInfo& line_info); [[noreturn]] void exit_with_code(const LineInfo& line_info, const int exit_code); + // Exit the tool without an error message. [[noreturn]] inline void exit_fail(const LineInfo& line_info) { exit_with_code(line_info, EXIT_FAILURE); } + // Exit the tool successfully. [[noreturn]] inline void exit_success(const LineInfo& line_info) { exit_with_code(line_info, EXIT_SUCCESS); } - // Part of the reason these exist is to not include extra headers in this one to avoid circular #includes. + // Display an error message to the user and exit the tool. [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView errorMessage); template + // Display an error message to the user and exit the tool. [[noreturn]] void exit_with_message(const LineInfo& line_info, const char* errorMessageTemplate, const Arg1 errorMessageArg1, diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index a7e5648cd..e243f4d89 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -13,52 +13,16 @@ namespace vcpkg ExpectedT FullPackageSpec::from_string(const std::string& spec_as_string, const Triplet& default_triplet) { - auto pos = spec_as_string.find(':'); - auto pos_l_bracket = spec_as_string.find('['); - auto pos_r_bracket = spec_as_string.find(']'); - - FullPackageSpec f; - if (pos == std::string::npos && pos_l_bracket == std::string::npos) - { - f.package_spec = - PackageSpec::from_name_and_triplet(spec_as_string, default_triplet).value_or_exit(VCPKG_LINE_INFO); - return f; - } - else if (pos == std::string::npos) - { - if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) - { - return PackageSpecParseResult::INVALID_CHARACTERS; - } - const std::string name = spec_as_string.substr(0, pos_l_bracket); - f.package_spec = PackageSpec::from_name_and_triplet(name, default_triplet).value_or_exit(VCPKG_LINE_INFO); - f.features = parse_comma_list(spec_as_string.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); - return f; - } - else if (pos_l_bracket == std::string::npos && pos_r_bracket == std::string::npos) - { - const std::string name = spec_as_string.substr(0, pos); - const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1)); - f.package_spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO); - } - else + auto res = ParsedSpecifier::from_string(spec_as_string); + if (auto p = res.get()) { - if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) - { - return PackageSpecParseResult::INVALID_CHARACTERS; - } - const std::string name = spec_as_string.substr(0, pos_l_bracket); - f.features = parse_comma_list(spec_as_string.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); - const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1)); - f.package_spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO); + FullPackageSpec fspec; + Triplet t = p->triplet.empty() ? default_triplet : Triplet::from_canonical_name(p->triplet); + fspec.package_spec = PackageSpec::from_name_and_triplet(p->name, t).value_or_exit(VCPKG_LINE_INFO); + fspec.features = std::move(p->features); + return fspec; } - - auto pos2 = spec_as_string.find(':', pos + 1); - if (pos2 != std::string::npos) - { - return PackageSpecParseResult::TOO_MANY_COLONS; - } - return f; + return res.error(); } ExpectedT PackageSpec::from_name_and_triplet(const std::string& name, @@ -93,4 +57,53 @@ namespace vcpkg } bool operator!=(const PackageSpec& left, const PackageSpec& right) { return !(left == right); } + + ExpectedT ParsedSpecifier::from_string(const std::string& input) + { + auto pos = input.find(':'); + auto pos_l_bracket = input.find('['); + auto pos_r_bracket = input.find(']'); + + ParsedSpecifier f; + if (pos == std::string::npos && pos_l_bracket == std::string::npos) + { + f.name = input; + return f; + } + else if (pos == std::string::npos) + { + if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) + { + return PackageSpecParseResult::INVALID_CHARACTERS; + } + const std::string name = input.substr(0, pos_l_bracket); + f.name = name; + f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); + return f; + } + else if (pos_l_bracket == std::string::npos && pos_r_bracket == std::string::npos) + { + const std::string name = input.substr(0, pos); + f.triplet = input.substr(pos + 1); + f.name = name; + } + else + { + if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) + { + return PackageSpecParseResult::INVALID_CHARACTERS; + } + const std::string name = input.substr(0, pos_l_bracket); + f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); + f.triplet = input.substr(pos + 1); + f.name = name; + } + + auto pos2 = input.find(':', pos + 1); + if (pos2 != std::string::npos) + { + return PackageSpecParseResult::TOO_MANY_COLONS; + } + return f; + } } diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 2aab7c572..f9ae6854a 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include "PackageSpec.h" #include "SourceParagraph.h" #include "Triplet.h" #include "vcpkg_Checks.h" @@ -28,7 +29,11 @@ namespace vcpkg static span get_list_of_valid_fields() { static const std::string valid_fields[] = { - Fields::SOURCE, Fields::VERSION, Fields::DESCRIPTION, Fields::MAINTAINER, Fields::BUILD_DEPENDS, + Fields::SOURCE, + Fields::VERSION, + Fields::DESCRIPTION, + Fields::MAINTAINER, + Fields::BUILD_DEPENDS, }; return valid_fields; @@ -154,21 +159,20 @@ namespace vcpkg Features parse_feature_list(const std::string& name) { - Features f; - int end = (int)name.find(']'); - if (end != std::string::npos) + auto maybe_spec = ParsedSpecifier::from_string(name); + if (auto spec = maybe_spec.get()) { - int start = (int)name.find('['); + Checks::check_exit( + VCPKG_LINE_INFO, spec->triplet.empty(), "error: triplet not allowed in specifier: %s", name); - auto feature_name_list = name.substr(start + 1, end - start - 1); - f.name = name.substr(0, start); - f.features = parse_comma_list(feature_name_list); + Features f; + f.name = spec->name; + f.features = spec->features; + return f; } - else - { - f.name = name; - } - return f; + + Checks::exit_with_message( + VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), name); } Dependency Dependency::parse_dependency(std::string name, std::string qualifier) diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index 3f2760c22..1fd950e19 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -385,42 +385,53 @@ namespace UnitTest1 Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str()); } - TEST_METHOD(package_spec_parse) + TEST_METHOD(parsed_specifier_from_string) { - vcpkg::ExpectedT spec = - vcpkg::FullPackageSpec::from_string("zlib", vcpkg::Triplet::X86_WINDOWS); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); - Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); - Assert::AreEqual(vcpkg::Triplet::X86_WINDOWS.canonical_name(), - spec.get()->package_spec.triplet().canonical_name()); + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::AreEqual(size_t(0), spec->features.size()); + Assert::AreEqual("", spec->triplet.c_str()); } - TEST_METHOD(package_spec_parse_with_arch) + TEST_METHOD(parsed_specifier_from_string_with_triplet) { - vcpkg::ExpectedT spec = - vcpkg::FullPackageSpec::from_string("zlib:x64-uwp", vcpkg::Triplet::X86_WINDOWS); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); - Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); - Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), - spec.get()->package_spec.triplet().canonical_name()); + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::AreEqual("x64-uwp", spec->triplet.c_str()); } - TEST_METHOD(package_spec_parse_with_multiple_colon) + TEST_METHOD(parsed_specifier_from_string_with_colons) { - auto ec = vcpkg::FullPackageSpec::from_string("zlib:x86-uwp:", vcpkg::Triplet::X86_WINDOWS).error(); + auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error(); Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); } - TEST_METHOD(package_spec_feature_parse_with_arch) + TEST_METHOD(parsed_specifier_from_string_with_feature) { - vcpkg::ExpectedT spec = - vcpkg::FullPackageSpec::from_string("zlib[feature]:x64-uwp", vcpkg::Triplet::X86_WINDOWS); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); - Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); - Assert::IsTrue(spec.get()->features.size() == 1); - Assert::AreEqual("feature", spec.get()->features.front().c_str()); - Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), - spec.get()->package_spec.triplet().canonical_name()); + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::IsTrue(spec->features.size() == 1); + Assert::AreEqual("feature", spec->features.front().c_str()); + Assert::AreEqual("x64-uwp", spec->triplet.c_str()); + } + + TEST_METHOD(parsed_specifier_from_string_with_many_features) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::IsTrue(spec->features.size() == 3); + Assert::AreEqual("0", spec->features[0].c_str()); + Assert::AreEqual("1", spec->features[1].c_str()); + Assert::AreEqual("2", spec->features[2].c_str()); + Assert::AreEqual("", spec->triplet.c_str()); } TEST_METHOD(utf8_to_utf16) diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index c84ca73f3..799bca439 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -363,23 +363,25 @@ namespace vcpkg::Dependencies std::vector f_specs; for (auto&& depend : depends) { - int end = (int)depend.find(']'); - if (end != std::string::npos) + auto maybe_spec = ParsedSpecifier::from_string(depend); + if (auto spec = maybe_spec.get()) { - int start = (int)depend.find('['); + Checks::check_exit(VCPKG_LINE_INFO, + spec->triplet.empty(), + "error: triplets cannot currently be specified in this context: %s", + depend); + PackageSpec pspec = + PackageSpec::from_name_and_triplet(spec->name, triplet).value_or_exit(VCPKG_LINE_INFO); - auto feature_name = depend.substr(start + 1, end - start - 1); - auto package_name = depend.substr(0, start); - auto p_spec = PackageSpec::from_name_and_triplet(package_name, triplet).value_or_exit(VCPKG_LINE_INFO); - auto feature_spec = FeatureSpec{p_spec, feature_name}; - f_specs.emplace_back(std::move(feature_spec)); + for (auto&& feature : spec->features) + f_specs.push_back(FeatureSpec{pspec, feature}); + + if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, ""}); } else { - auto p_spec = PackageSpec::from_name_and_triplet(depend, triplet).value_or_exit(VCPKG_LINE_INFO); - - auto feature_spec = FeatureSpec{p_spec, ""}; - f_specs.emplace_back(std::move(feature_spec)); + Checks::exit_with_message( + VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), depend); } } return f_specs; -- cgit v1.2.3 From f219ce0b8c3e84e5fc1df21ad2f2c8b13f0fe413 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 19 Aug 2017 19:27:34 -0700 Subject: [vcpkg] Reorganize some parsing functions. --- toolsrc/include/PackageSpec.h | 11 ++++++-- toolsrc/include/SourceParagraph.h | 12 +------- toolsrc/include/vcpkg_Parse.h | 2 ++ toolsrc/src/PackageSpec.cpp | 26 +++++++++++++---- toolsrc/src/SourceParagraph.cpp | 57 ++++---------------------------------- toolsrc/src/tests_dependencies.cpp | 15 ++++++++-- toolsrc/src/vcpkg_Parse.cpp | 33 ++++++++++++++++++++++ 7 files changed, 84 insertions(+), 72 deletions(-) diff --git a/toolsrc/include/PackageSpec.h b/toolsrc/include/PackageSpec.h index 77a14e90e..8e986b4d6 100644 --- a/toolsrc/include/PackageSpec.h +++ b/toolsrc/include/PackageSpec.h @@ -1,6 +1,6 @@ #pragma once + #include "PackageSpecParseResult.h" -#include "SourceParagraph.h" #include "Triplet.h" #include "vcpkg_expected.h" @@ -17,7 +17,6 @@ namespace vcpkg struct PackageSpec { - static std::string to_string(const std::string& name, const Triplet& triplet); static ExpectedT from_name_and_triplet(const std::string& name, const Triplet& triplet); @@ -43,6 +42,14 @@ namespace vcpkg const Triplet& default_triplet); }; + struct Features + { + std::string name; + std::vector features; + + static ExpectedT from_string(const std::string& input); + }; + bool operator==(const PackageSpec& left, const PackageSpec& right); bool operator!=(const PackageSpec& left, const PackageSpec& right); } diff --git a/toolsrc/include/SourceParagraph.h b/toolsrc/include/SourceParagraph.h index fee61c3e8..d938e2e3b 100644 --- a/toolsrc/include/SourceParagraph.h +++ b/toolsrc/include/SourceParagraph.h @@ -1,5 +1,6 @@ #pragma once +#include "PackageSpec.h" #include "Span.h" #include "vcpkg_Parse.h" #include "vcpkg_System.h" @@ -13,16 +14,6 @@ namespace vcpkg { extern bool g_feature_packages; - struct Triplet; - - struct Features - { - std::string name; - std::vector features; - }; - - Features parse_feature_list(const std::string& name); - struct Dependency { Features depend; @@ -73,7 +64,6 @@ namespace vcpkg // zlib[uwp] becomes Dependency{"zlib", "uwp"} std::vector expand_qualified_dependencies(const std::vector& depends); - std::vector parse_comma_list(const std::string& str); struct Supports { diff --git a/toolsrc/include/vcpkg_Parse.h b/toolsrc/include/vcpkg_Parse.h index a2eb152dc..e663448b9 100644 --- a/toolsrc/include/vcpkg_Parse.h +++ b/toolsrc/include/vcpkg_Parse.h @@ -33,4 +33,6 @@ namespace vcpkg::Parse RawParagraph&& fields; std::vector missing_fields; }; + + std::vector parse_comma_list(const std::string& str); } diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index e243f4d89..475b3e3f6 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -1,8 +1,11 @@ #include "pch.h" #include "PackageSpec.h" +#include "vcpkg_Parse.h" #include "vcpkg_Util.h" +using vcpkg::Parse::parse_comma_list; + namespace vcpkg { static bool is_valid_package_spec_char(char c) @@ -45,11 +48,7 @@ namespace vcpkg std::string PackageSpec::dir() const { return Strings::format("%s_%s", this->m_name, this->m_triplet); } - std::string PackageSpec::to_string(const std::string& name, const Triplet& triplet) - { - return Strings::format("%s:%s", name, triplet); - } - std::string PackageSpec::to_string() const { return to_string(this->name(), this->triplet()); } + std::string PackageSpec::to_string() const { return Strings::format("%s:%s", this->name(), this->triplet()); } bool operator==(const PackageSpec& left, const PackageSpec& right) { @@ -106,4 +105,21 @@ namespace vcpkg } return f; } + + ExpectedT Features::from_string(const std::string& name) + { + auto maybe_spec = ParsedSpecifier::from_string(name); + if (auto spec = maybe_spec.get()) + { + Checks::check_exit( + VCPKG_LINE_INFO, spec->triplet.empty(), "error: triplet not allowed in specifier: %s", name); + + Features f; + f.name = spec->name; + f.features = spec->features; + return f; + } + + return maybe_spec.error(); + } } diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index f9ae6854a..76c5a2004 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -157,29 +157,15 @@ namespace vcpkg return std::move(control_file); } - Features parse_feature_list(const std::string& name) - { - auto maybe_spec = ParsedSpecifier::from_string(name); - if (auto spec = maybe_spec.get()) - { - Checks::check_exit( - VCPKG_LINE_INFO, spec->triplet.empty(), "error: triplet not allowed in specifier: %s", name); - - Features f; - f.name = spec->name; - f.features = spec->features; - return f; - } - - Checks::exit_with_message( - VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), name); - } - Dependency Dependency::parse_dependency(std::string name, std::string qualifier) { Dependency dep; dep.qualifier = qualifier; - dep.depend = parse_feature_list(name); + if (auto maybe_features = Features::from_string(name)) + dep.depend = *maybe_features.get(); + else + Checks::exit_with_message( + VCPKG_LINE_INFO, "error while parsing dependency: %s: %s", to_string(maybe_features.error()), name); return dep; } @@ -217,39 +203,6 @@ namespace vcpkg }); } - std::vector parse_comma_list(const std::string& str) - { - if (str.empty()) - { - return {}; - } - - std::vector out; - - size_t cur = 0; - do - { - auto pos = str.find(',', cur); - if (pos == std::string::npos) - { - out.push_back(str.substr(cur)); - break; - } - out.push_back(str.substr(cur, pos - cur)); - - // skip comma and space - ++pos; - if (str[pos] == ' ') - { - ++pos; - } - - cur = pos; - } while (cur != std::string::npos); - - return out; - } - std::vector filter_dependencies(const std::vector& deps, const Triplet& t) { std::vector ret; diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp index 26cc1e22c..6a6981d73 100644 --- a/toolsrc/src/tests_dependencies.cpp +++ b/toolsrc/src/tests_dependencies.cpp @@ -8,6 +8,7 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace vcpkg; +using Parse::parse_comma_list; namespace UnitTest1 { @@ -41,7 +42,15 @@ namespace UnitTest1 TEST_METHOD(parse_supports_all) { auto v = Supports::parse({ - "x64", "x86", "arm", "windows", "uwp", "v140", "v141", "crt-static", "crt-dynamic", + "x64", + "x86", + "arm", + "windows", + "uwp", + "v140", + "v141", + "crt-static", + "crt-dynamic", }); Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); @@ -74,7 +83,9 @@ namespace UnitTest1 TEST_METHOD(parse_supports_some) { auto v = Supports::parse({ - "x64", "x86", "windows", + "x64", + "x86", + "windows", }); Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); diff --git a/toolsrc/src/vcpkg_Parse.cpp b/toolsrc/src/vcpkg_Parse.cpp index 659af2939..118cde900 100644 --- a/toolsrc/src/vcpkg_Parse.cpp +++ b/toolsrc/src/vcpkg_Parse.cpp @@ -44,4 +44,37 @@ namespace vcpkg::Parse } return nullptr; } + + std::vector parse_comma_list(const std::string& str) + { + if (str.empty()) + { + return {}; + } + + std::vector out; + + size_t cur = 0; + do + { + auto pos = str.find(',', cur); + if (pos == std::string::npos) + { + out.push_back(str.substr(cur)); + break; + } + out.push_back(str.substr(cur, pos - cur)); + + // skip comma and space + ++pos; + if (str[pos] == ' ') + { + ++pos; + } + + cur = pos; + } while (cur != std::string::npos); + + return out; + } } -- cgit v1.2.3 From bd222504abea410d77487e176649ae9b6989c4e0 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 20 Aug 2017 19:09:39 -0700 Subject: [vcpkg] Refactor parsing together and flatten featurespec usages --- toolsrc/include/PackageSpec.h | 20 +++++ toolsrc/include/vcpkg_Dependencies.h | 9 +-- toolsrc/src/PackageSpec.cpp | 42 ++++++++++ toolsrc/src/commands_install.cpp | 6 +- toolsrc/src/test_install_plan.cpp | 56 ++++++++----- toolsrc/src/tests_package_spec.cpp | 119 ++++++++++++++++++++++++++++ toolsrc/src/tests_paragraph.cpp | 63 --------------- toolsrc/src/vcpkg_Dependencies.cpp | 56 +++---------- toolsrc/vcpkgtest/vcpkgtest.vcxproj | 1 + toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters | 3 + 10 files changed, 237 insertions(+), 138 deletions(-) create mode 100644 toolsrc/src/tests_package_spec.cpp diff --git a/toolsrc/include/PackageSpec.h b/toolsrc/include/PackageSpec.h index 8e986b4d6..8b485316f 100644 --- a/toolsrc/include/PackageSpec.h +++ b/toolsrc/include/PackageSpec.h @@ -33,11 +33,31 @@ namespace vcpkg Triplet m_triplet; }; + struct FeatureSpec + { + FeatureSpec(const PackageSpec& spec, const std::string& feature) : m_spec(spec), m_feature(feature) {} + + const std::string& name() const { return m_spec.name(); } + const std::string& feature() const { return m_feature; } + const Triplet& triplet() const { return m_spec.triplet(); } + + const PackageSpec& spec() const { return m_spec; } + + static std::vector from_strings_and_triplet(const std::vector& depends, + const Triplet& t); + + private: + PackageSpec m_spec; + std::string m_feature; + }; + struct FullPackageSpec { PackageSpec package_spec; std::vector features; + static std::vector to_feature_specs(const std::vector& specs); + static ExpectedT from_string(const std::string& spec_as_string, const Triplet& default_triplet); }; diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h index 3fee8ef33..37d3a59e5 100644 --- a/toolsrc/include/vcpkg_Dependencies.h +++ b/toolsrc/include/vcpkg_Dependencies.h @@ -30,19 +30,12 @@ namespace vcpkg::Dependencies namespace vcpkg::Dependencies { - struct FeatureSpec - { - PackageSpec spec; - std::string feature_name; - }; - struct FeatureNodeEdges { std::vector remove_edges; std::vector build_edges; bool plus = false; }; - std::vector to_feature_specs(const std::vector& depends, const Triplet& t); struct Cluster { @@ -210,6 +203,6 @@ namespace vcpkg::Dependencies std::unordered_map& pkg_to_cluster, GraphPlan& graph_plan); std::vector create_feature_install_plan(const std::unordered_map& map, - const std::vector& specs, + const std::vector& specs, const StatusParagraphs& status_db); } diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index 475b3e3f6..a5d40e998 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -13,6 +13,48 @@ namespace vcpkg return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)) || (c == '[') || (c == ']'); } + std::vector FeatureSpec::from_strings_and_triplet(const std::vector& depends, + const Triplet& triplet) + { + std::vector f_specs; + for (auto&& depend : depends) + { + auto maybe_spec = ParsedSpecifier::from_string(depend); + if (auto spec = maybe_spec.get()) + { + Checks::check_exit(VCPKG_LINE_INFO, + spec->triplet.empty(), + "error: triplets cannot currently be specified in this context: %s", + depend); + PackageSpec pspec = + PackageSpec::from_name_and_triplet(spec->name, triplet).value_or_exit(VCPKG_LINE_INFO); + + for (auto&& feature : spec->features) + f_specs.push_back(FeatureSpec{pspec, feature}); + + if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, ""}); + } + else + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), depend); + } + } + return f_specs; + } + + std::vector FullPackageSpec::to_feature_specs(const std::vector& specs) + { + std::vector ret; + for (auto&& spec : specs) + { + ret.emplace_back(spec.package_spec, ""); + for (auto&& feature : spec.features) + ret.emplace_back(spec.package_spec, feature); + } + return ret; + } + ExpectedT FullPackageSpec::from_string(const std::string& spec_as_string, const Triplet& default_triplet) { diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 2965d9025..3fc0e2563 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -14,10 +14,10 @@ namespace vcpkg::Commands::Install { using Dependencies::InstallPlanAction; - using Dependencies::RequestType; using Dependencies::InstallPlanType; using Dependencies::RemovePlanAction; using Dependencies::RemovePlanType; + using Dependencies::RequestType; InstallDir InstallDir::from_destination_root(const fs::path& destination_root, const std::string& destination_subdirectory, @@ -440,8 +440,8 @@ namespace vcpkg::Commands::Install .value_or_exit(VCPKG_LINE_INFO); scf_map[pkg_spec] = std::move(*port); } - std::vector action_plan = - Dependencies::create_feature_install_plan(scf_map, full_specs, status_db); + std::vector action_plan = Dependencies::create_feature_install_plan( + scf_map, FullPackageSpec::to_feature_specs(full_specs), status_db); // install plan will be empty if it is already installed - need to change this at status paragraph part Checks::check_exit( VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty for feature packages"); diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 347998723..e7c62813e 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -214,8 +214,10 @@ namespace UnitTest1 {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}}, })}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(4), install_plan.size()); remove_plan_check(&install_plan[0], "a"); @@ -248,8 +250,10 @@ namespace UnitTest1 {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}}, })}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(2), install_plan.size()); features_check(&install_plan[0], "b", {"beefeatureone", "beefeaturetwo", "core"}); @@ -284,8 +288,10 @@ namespace UnitTest1 }), {"core"}}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_c, spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_c, spec_a}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(4), install_plan.size()); remove_plan_check(&install_plan[0], "a"); @@ -328,8 +334,10 @@ namespace UnitTest1 }), {"core"}}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_c}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_c}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(1), install_plan.size()); features_check(&install_plan[0], "c", {"core"}); @@ -356,8 +364,10 @@ namespace UnitTest1 {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, })}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(2), install_plan.size()); features_check(&install_plan[0], "b", {"core", "2"}); @@ -389,8 +399,10 @@ namespace UnitTest1 }), {"1"}}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_a, spec_b}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a, spec_b}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(3), install_plan.size()); remove_plan_check(&install_plan[0], "b"); @@ -433,8 +445,10 @@ namespace UnitTest1 }), {"1"}}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_b}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_b}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(5), install_plan.size()); remove_plan_check(&install_plan[0], "x"); @@ -495,10 +509,10 @@ namespace UnitTest1 }), {"core"}}; - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - {spec_c_64, spec_a_86, spec_a_64, spec_c_86}, - StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({spec_c_64, spec_a_86, spec_a_64, spec_c_86}), + StatusParagraphs(std::move(status_paragraphs))); /*Assert::AreEqual(size_t(8), install_plan.size()); auto iterator_pos = [&](const PackageSpec& spec, size_t start) -> int { @@ -555,8 +569,10 @@ namespace UnitTest1 }), {""}}; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(3), install_plan.size()); features_check(&install_plan[0], "c", {"core", "1", "2"}); diff --git a/toolsrc/src/tests_package_spec.cpp b/toolsrc/src/tests_package_spec.cpp new file mode 100644 index 000000000..fa201b372 --- /dev/null +++ b/toolsrc/src/tests_package_spec.cpp @@ -0,0 +1,119 @@ +#include "BinaryParagraph.h" +#include "CppUnitTest.h" +#include "Paragraphs.h" +#include "vcpkg_Strings.h" + +#pragma comment(lib, "version") +#pragma comment(lib, "winhttp") + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace Microsoft::VisualStudio::CppUnitTestFramework +{ + template<> + inline std::wstring ToString(const vcpkg::PackageSpecParseResult& t) + { + return ToString(static_cast(t)); + } + + template<> + inline std::wstring ToString(const vcpkg::PackageSpec& t) + { + return ToString(t.to_string()); + } +} + +namespace Strings = vcpkg::Strings; + +namespace UnitTest1 +{ + using namespace vcpkg; + + class SpecifierConversion : public TestClass + { + TEST_METHOD(full_package_spec_to_feature_specs) + { + auto a_spec = PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + auto b_spec = PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + auto fspecs = FullPackageSpec::to_feature_specs({{a_spec, {"0", "1"}}, {b_spec, {"2", "3"}}}); + + Assert::AreEqual(size_t(6), fspecs.size()); + + std::array features = {"", "0", "1", "", "2", "3"}; + std::array specs = {&a_spec, &a_spec, &a_spec, &b_spec, &b_spec, &b_spec}; + + for (int i = 0; i < features.size(); ++i) + { + Assert::AreEqual(features[i], fspecs[i].feature().c_str()); + Assert::AreEqual(*specs[i], fspecs[i].spec()); + } + } + }; + + class SpecifierParsing : public TestClass + { + TEST_METHOD(parsed_specifier_from_string) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::AreEqual(size_t(0), spec->features.size()); + Assert::AreEqual("", spec->triplet.c_str()); + } + + TEST_METHOD(parsed_specifier_from_string_with_triplet) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::AreEqual("x64-uwp", spec->triplet.c_str()); + } + + TEST_METHOD(parsed_specifier_from_string_with_colons) + { + auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error(); + Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); + } + + TEST_METHOD(parsed_specifier_from_string_with_feature) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::IsTrue(spec->features.size() == 1); + Assert::AreEqual("feature", spec->features.front().c_str()); + Assert::AreEqual("x64-uwp", spec->triplet.c_str()); + } + + TEST_METHOD(parsed_specifier_from_string_with_many_features) + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]"); + Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); + auto spec = maybe_spec.get(); + Assert::AreEqual("zlib", spec->name.c_str()); + Assert::IsTrue(spec->features.size() == 3); + Assert::AreEqual("0", spec->features[0].c_str()); + Assert::AreEqual("1", spec->features[1].c_str()); + Assert::AreEqual("2", spec->features[2].c_str()); + Assert::AreEqual("", spec->triplet.c_str()); + } + + TEST_METHOD(utf8_to_utf16) + { + auto str = vcpkg::Strings::to_utf16("abc"); + Assert::AreEqual(L"abc", str.c_str()); + } + + TEST_METHOD(utf8_to_utf16_with_whitespace) + { + auto str = vcpkg::Strings::to_utf16("abc -x86-windows"); + Assert::AreEqual(L"abc -x86-windows", str.c_str()); + } + }; + + TEST_CLASS(Metrics){}; +} diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index 1fd950e19..47a07e12d 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -384,68 +384,5 @@ namespace UnitTest1 Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str()); } - - TEST_METHOD(parsed_specifier_from_string) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::AreEqual(size_t(0), spec->features.size()); - Assert::AreEqual("", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_triplet) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::AreEqual("x64-uwp", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_colons) - { - auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error(); - Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); - } - - TEST_METHOD(parsed_specifier_from_string_with_feature) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::IsTrue(spec->features.size() == 1); - Assert::AreEqual("feature", spec->features.front().c_str()); - Assert::AreEqual("x64-uwp", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_many_features) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::IsTrue(spec->features.size() == 3); - Assert::AreEqual("0", spec->features[0].c_str()); - Assert::AreEqual("1", spec->features[1].c_str()); - Assert::AreEqual("2", spec->features[2].c_str()); - Assert::AreEqual("", spec->triplet.c_str()); - } - - TEST_METHOD(utf8_to_utf16) - { - auto str = vcpkg::Strings::to_utf16("abc"); - Assert::AreEqual(L"abc", str.c_str()); - } - - TEST_METHOD(utf8_to_utf16_with_whitespace) - { - auto str = vcpkg::Strings::to_utf16("abc -x86-windows"); - Assert::AreEqual(L"abc -x86-windows", str.c_str()); - } }; - - TEST_CLASS(Metrics){}; } diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 799bca439..5226fac24 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -358,35 +358,6 @@ namespace vcpkg::Dependencies return toposort; } - std::vector to_feature_specs(const std::vector& depends, const Triplet& triplet) - { - std::vector f_specs; - for (auto&& depend : depends) - { - auto maybe_spec = ParsedSpecifier::from_string(depend); - if (auto spec = maybe_spec.get()) - { - Checks::check_exit(VCPKG_LINE_INFO, - spec->triplet.empty(), - "error: triplets cannot currently be specified in this context: %s", - depend); - PackageSpec pspec = - PackageSpec::from_name_and_triplet(spec->name, triplet).value_or_exit(VCPKG_LINE_INFO); - - for (auto&& feature : spec->features) - f_specs.push_back(FeatureSpec{pspec, feature}); - - if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, ""}); - } - else - { - Checks::exit_with_message( - VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), depend); - } - } - return f_specs; - } - void mark_plus_default(Cluster& cluster, std::unordered_map& pkg_to_cluster, GraphPlan& graph_plan) @@ -442,8 +413,8 @@ namespace vcpkg::Dependencies for (auto&& depend : cluster.edges[updated_feature].build_edges) { - auto& depend_cluster = pkg_to_cluster[depend.spec]; - mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); + auto& depend_cluster = pkg_to_cluster[depend.spec()]; + mark_plus(depend.feature(), depend_cluster, pkg_to_cluster, graph_plan); mark_plus_default(depend_cluster, pkg_to_cluster, graph_plan); if (&depend_cluster == &cluster) continue; graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); @@ -462,7 +433,7 @@ namespace vcpkg::Dependencies auto& remove_edges_edges = pair.second.remove_edges; for (auto&& depend : remove_edges_edges) { - auto& depend_cluster = pkg_to_cluster[depend.spec]; + auto& depend_cluster = pkg_to_cluster[depend.spec()]; graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); depend_cluster.transient_uninstalled = true; mark_minus(depend_cluster, pkg_to_cluster, graph_plan); @@ -476,7 +447,7 @@ namespace vcpkg::Dependencies } std::vector create_feature_install_plan(const std::unordered_map& map, - const std::vector& specs, + const std::vector& specs, const StatusParagraphs& status_db) { std::unordered_map pkg_spec_to_package_node; @@ -488,14 +459,14 @@ namespace vcpkg::Dependencies node.spec = it.first; FeatureNodeEdges core_dependencies; auto core_depends = filter_dependencies(it.second.core_paragraph->depends, node.spec.triplet()); - core_dependencies.build_edges = to_feature_specs(core_depends, node.spec.triplet()); + core_dependencies.build_edges = FeatureSpec::from_strings_and_triplet(core_depends, node.spec.triplet()); node.edges["core"] = std::move(core_dependencies); for (const auto& feature : it.second.feature_paragraphs) { FeatureNodeEdges added_edges; auto depends = filter_dependencies(feature->depends, node.spec.triplet()); - added_edges.build_edges = to_feature_specs(depends, node.spec.triplet()); + added_edges.build_edges = FeatureSpec::from_strings_and_triplet(depends, node.spec.triplet()); node.edges.emplace(feature->name, std::move(added_edges)); } node.source_control_file = &it.second; @@ -508,13 +479,13 @@ namespace vcpkg::Dependencies Cluster& cluster = pkg_spec_to_package_node[spec]; cluster.transient_uninstalled = false; - auto reverse_edges = - to_feature_specs(status_paragraph->package.depends, status_paragraph->package.spec.triplet()); + auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, + status_paragraph->package.spec.triplet()); for (auto&& dependency : reverse_edges) { - auto pkg_node = pkg_spec_to_package_node.find(dependency.spec); - auto depends_name = dependency.feature_name; + auto pkg_node = pkg_spec_to_package_node.find(dependency.spec()); + auto depends_name = dependency.feature(); if (depends_name == "") { for (auto&& default_feature : status_paragraph->package.default_features) @@ -541,12 +512,9 @@ namespace vcpkg::Dependencies GraphPlan graph_plan; for (auto&& spec : specs) { - Cluster& spec_cluster = pkg_spec_to_package_node[spec.package_spec]; + Cluster& spec_cluster = pkg_spec_to_package_node[spec.spec()]; mark_plus_default(spec_cluster, pkg_spec_to_package_node, graph_plan); - for (auto&& feature : spec.features) - { - mark_plus(feature, spec_cluster, pkg_spec_to_package_node, graph_plan); - } + mark_plus(spec.feature(), spec_cluster, pkg_spec_to_package_node, graph_plan); } Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); diff --git a/toolsrc/vcpkgtest/vcpkgtest.vcxproj b/toolsrc/vcpkgtest/vcpkgtest.vcxproj index ca66260d4..041e74d31 100644 --- a/toolsrc/vcpkgtest/vcpkgtest.vcxproj +++ b/toolsrc/vcpkgtest/vcpkgtest.vcxproj @@ -21,6 +21,7 @@ + diff --git a/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters b/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters index e376e59f4..b31dbd951 100644 --- a/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters +++ b/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters @@ -27,5 +27,8 @@ Source Files + + Source Files + \ No newline at end of file -- cgit v1.2.3 From 1ba7cef1f07e8fd8c0053694b306dcc3960f720e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 20 Aug 2017 19:36:43 -0700 Subject: [vcpkg] Remove incomplete default features implementation --- toolsrc/include/SourceParagraph.h | 11 ++-- toolsrc/include/vcpkg_Dependencies.h | 8 --- toolsrc/src/SourceParagraph.cpp | 5 ++ toolsrc/src/test_install_plan.cpp | 42 ------------- toolsrc/src/vcpkg_Dependencies.cpp | 114 +++++++++++++++++++---------------- 5 files changed, 74 insertions(+), 106 deletions(-) diff --git a/toolsrc/include/SourceParagraph.h b/toolsrc/include/SourceParagraph.h index d938e2e3b..05f18f940 100644 --- a/toolsrc/include/SourceParagraph.h +++ b/toolsrc/include/SourceParagraph.h @@ -23,6 +23,12 @@ namespace vcpkg static Dependency parse_dependency(std::string name, std::string qualifier); }; + std::vector filter_dependencies(const std::vector& deps, const Triplet& t); + std::vector filter_dependencies_to_specs(const std::vector& deps, const Triplet& t); + + // zlib[uwp] becomes Dependency{"zlib", "uwp"} + std::vector expand_qualified_dependencies(const std::vector& depends); + const std::string to_string(const Dependency& dep); struct FeatureParagraph @@ -60,11 +66,6 @@ namespace vcpkg return print_error_message({&error_info_list, 1}); } - std::vector filter_dependencies(const std::vector& deps, const Triplet& t); - - // zlib[uwp] becomes Dependency{"zlib", "uwp"} - std::vector expand_qualified_dependencies(const std::vector& depends); - struct Supports { static ExpectedT> parse(const std::vector& strs); diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h index 37d3a59e5..3a81cf27b 100644 --- a/toolsrc/include/vcpkg_Dependencies.h +++ b/toolsrc/include/vcpkg_Dependencies.h @@ -194,14 +194,6 @@ namespace vcpkg::Dependencies Graphs::Graph remove_graph; Graphs::Graph install_graph; }; - bool mark_plus(const std::string& feature, - Cluster& cluster, - std::unordered_map& pkg_to_cluster, - GraphPlan& graph_plan); - void mark_minus(Cluster& cluster, std::unordered_map& pkg_to_cluster, GraphPlan& graph_plan); - void mark_plus_default(Cluster& cluster, - std::unordered_map& pkg_to_cluster, - GraphPlan& graph_plan); std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db); diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 76c5a2004..54f34cbd3 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -216,6 +216,11 @@ namespace vcpkg return ret; } + std::vector filter_dependencies_to_specs(const std::vector& deps, const Triplet& t) + { + return FeatureSpec::from_strings_and_triplet(filter_dependencies(deps, t), t); + } + const std::string to_string(const Dependency& dep) { std::string name = dep.name(); diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index e7c62813e..f0884c063 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -537,47 +537,5 @@ namespace UnitTest1 features_check(&install_plan[6], "a", {"one", "core"}); features_check(&install_plan[7], "c", {"core"}); } - - TEST_METHOD(default_features_test) - { - using Pgh = std::unordered_map; - - std::vector> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X86_WINDOWS); - - auto spec_a = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Default-Features", "1, 2"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[2]"}}, - {{"Feature", "2"}, {"Description", "the second feature for a"}, {"Build-Depends", ""}}, - {{"Feature", "3"}, {"Description", "the third feature for a"}, {"Build-Depends", ""}}}), - {""}}; - auto spec_b = FullPackageSpec{ - spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Default-Features", "1, 2"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for b"}, {"Build-Depends", "c[1]"}}, - {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, - }), - {""}}; - - auto spec_c = FullPackageSpec{ - spec_map.get_package_spec({ - {{"Source", "c"}, {"Version", "1.3"}, {"Default-Features", "2"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for c"}, {"Build-Depends", ""}}, - {{"Feature", "2"}, {"Description", "the second feature for c"}, {"Build-Depends", ""}}, - }), - {""}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(3), install_plan.size()); - features_check(&install_plan[0], "c", {"core", "1", "2"}); - features_check(&install_plan[1], "b", {"core", "1", "2"}); - features_check(&install_plan[2], "a", {"core", "1", "2"}); - } }; } \ No newline at end of file diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 5226fac24..fa4876bd7 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -12,6 +12,10 @@ namespace vcpkg::Dependencies { + struct ClusterGraph; + void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } std::vector AnyParagraph::dependencies(const Triplet& triplet) const @@ -358,71 +362,74 @@ namespace vcpkg::Dependencies return toposort; } - void mark_plus_default(Cluster& cluster, - std::unordered_map& pkg_to_cluster, - GraphPlan& graph_plan) + struct ClusterGraph { - mark_plus("core", cluster, pkg_to_cluster, graph_plan); - if (auto scf = cluster.source_control_file.get()) + explicit ClusterGraph(std::unordered_map&& graph) : m_graph(std::move(graph)) {} + ClusterGraph(ClusterGraph&&) = default; + + Cluster& get(const PackageSpec& spec) { - for (auto&& default_feature : (*scf)->core_paragraph->default_features) - { - mark_plus(default_feature, cluster, pkg_to_cluster, graph_plan); - } + auto it = m_graph.find(spec); + if (it == m_graph.end()) Checks::unreachable(VCPKG_LINE_INFO); + return it->second; } - } - bool mark_plus(const std::string& feature, - Cluster& cluster, - std::unordered_map& pkg_to_cluster, - GraphPlan& graph_plan) + private: + ClusterGraph(const ClusterGraph&) = delete; + std::unordered_map m_graph; + }; + + void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { - auto it = cluster.edges.find(feature); - std::string updated_feature = feature; - if (updated_feature == "") + if (feature == "") { - updated_feature = "core"; - it = cluster.edges.find("core"); + // Indicates that core was not specified in the reference + return mark_plus("core", cluster, graph, graph_plan); } + auto it = cluster.edges.find(feature); if (it == cluster.edges.end()) { Checks::unreachable(VCPKG_LINE_INFO); } - if (cluster.edges[updated_feature].plus) return true; + if (cluster.edges[feature].plus) return; - if (cluster.original_features.find(updated_feature) == cluster.original_features.end()) + if (cluster.original_features.find(feature) == cluster.original_features.end()) { cluster.transient_uninstalled = true; } if (!cluster.transient_uninstalled) { - return false; + return; } - cluster.edges[updated_feature].plus = true; + cluster.edges[feature].plus = true; if (!cluster.original_features.empty()) { - mark_minus(cluster, pkg_to_cluster, graph_plan); + mark_minus(cluster, graph, graph_plan); } graph_plan.install_graph.add_vertex({&cluster}); auto& tracked = cluster.to_install_features; - tracked.insert(updated_feature); + tracked.insert(feature); + + if (feature != "core") + { + // All features implicitly depend on core + mark_plus("core", cluster, graph, graph_plan); + } - for (auto&& depend : cluster.edges[updated_feature].build_edges) + for (auto&& depend : cluster.edges[feature].build_edges) { - auto& depend_cluster = pkg_to_cluster[depend.spec()]; - mark_plus(depend.feature(), depend_cluster, pkg_to_cluster, graph_plan); - mark_plus_default(depend_cluster, pkg_to_cluster, graph_plan); + auto& depend_cluster = graph.get(depend.spec()); + mark_plus(depend.feature(), depend_cluster, graph, graph_plan); if (&depend_cluster == &cluster) continue; graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); } - return true; } - void mark_minus(Cluster& cluster, std::unordered_map& pkg_to_cluster, GraphPlan& graph_plan) + void mark_minus(Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { if (cluster.will_remove) return; cluster.will_remove = true; @@ -433,40 +440,38 @@ namespace vcpkg::Dependencies auto& remove_edges_edges = pair.second.remove_edges; for (auto&& depend : remove_edges_edges) { - auto& depend_cluster = pkg_to_cluster[depend.spec()]; + auto& depend_cluster = graph.get(depend.spec()); graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); - depend_cluster.transient_uninstalled = true; - mark_minus(depend_cluster, pkg_to_cluster, graph_plan); + mark_minus(depend_cluster, graph, graph_plan); } } + + cluster.transient_uninstalled = true; for (auto&& original_feature : cluster.original_features) { - cluster.transient_uninstalled = true; - mark_plus(original_feature, cluster, pkg_to_cluster, graph_plan); + mark_plus(original_feature, cluster, graph, graph_plan); } } - std::vector create_feature_install_plan(const std::unordered_map& map, - const std::vector& specs, - const StatusParagraphs& status_db) + static ClusterGraph create_feature_install_graph(const std::unordered_map& map, + const StatusParagraphs& status_db) { - std::unordered_map pkg_spec_to_package_node; + std::unordered_map graph; for (const auto& it : map) { - Cluster& node = pkg_spec_to_package_node[it.first]; + Cluster& node = graph[it.first]; node.spec = it.first; FeatureNodeEdges core_dependencies; - auto core_depends = filter_dependencies(it.second.core_paragraph->depends, node.spec.triplet()); - core_dependencies.build_edges = FeatureSpec::from_strings_and_triplet(core_depends, node.spec.triplet()); - node.edges["core"] = std::move(core_dependencies); + core_dependencies.build_edges = + filter_dependencies_to_specs(it.second.core_paragraph->depends, node.spec.triplet()); + node.edges.emplace("core", std::move(core_dependencies)); for (const auto& feature : it.second.feature_paragraphs) { FeatureNodeEdges added_edges; - auto depends = filter_dependencies(feature->depends, node.spec.triplet()); - added_edges.build_edges = FeatureSpec::from_strings_and_triplet(depends, node.spec.triplet()); + added_edges.build_edges = filter_dependencies_to_specs(feature->depends, node.spec.triplet()); node.edges.emplace(feature->name, std::move(added_edges)); } node.source_control_file = &it.second; @@ -476,7 +481,7 @@ namespace vcpkg::Dependencies { auto& spec = status_paragraph->package.spec; auto& status_paragraph_feature = status_paragraph->package.feature; - Cluster& cluster = pkg_spec_to_package_node[spec]; + Cluster& cluster = graph[spec]; cluster.transient_uninstalled = false; auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, @@ -484,7 +489,7 @@ namespace vcpkg::Dependencies for (auto&& dependency : reverse_edges) { - auto pkg_node = pkg_spec_to_package_node.find(dependency.spec()); + auto pkg_node = graph.find(dependency.spec()); auto depends_name = dependency.feature(); if (depends_name == "") { @@ -508,13 +513,20 @@ namespace vcpkg::Dependencies cluster.original_features.insert(status_paragraph_feature); } } + return ClusterGraph(std::move(graph)); + } + + std::vector create_feature_install_plan(const std::unordered_map& map, + const std::vector& specs, + const StatusParagraphs& status_db) + { + ClusterGraph graph = create_feature_install_graph(map, status_db); GraphPlan graph_plan; for (auto&& spec : specs) { - Cluster& spec_cluster = pkg_spec_to_package_node[spec.spec()]; - mark_plus_default(spec_cluster, pkg_spec_to_package_node, graph_plan); - mark_plus(spec.feature(), spec_cluster, pkg_spec_to_package_node, graph_plan); + Cluster& spec_cluster = graph.get(spec.spec()); + mark_plus(spec.feature(), spec_cluster, graph, graph_plan); } Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); -- cgit v1.2.3 From c7de717cbc2b6ab89dc8056984c0a4685e9cf56e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 20 Aug 2017 20:06:21 -0700 Subject: [vcpkg] Refactor features implementation. Improve error handling. --- toolsrc/include/vcpkg_Dependencies.h | 48 ------------ toolsrc/src/vcpkg_Dependencies.cpp | 140 ++++++++++++++++++++++++----------- 2 files changed, 98 insertions(+), 90 deletions(-) diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h index 3a81cf27b..9ac52490e 100644 --- a/toolsrc/include/vcpkg_Dependencies.h +++ b/toolsrc/include/vcpkg_Dependencies.h @@ -30,37 +30,6 @@ namespace vcpkg::Dependencies namespace vcpkg::Dependencies { - struct FeatureNodeEdges - { - std::vector remove_edges; - std::vector build_edges; - bool plus = false; - }; - - struct Cluster - { - std::vector status_paragraphs; - Optional source_control_file; - PackageSpec spec; - std::unordered_map edges; - std::unordered_set to_install_features; - std::unordered_set original_features; - bool will_remove = false; - bool transient_uninstalled = true; - Cluster() = default; - - private: - Cluster(const Cluster&) = delete; - Cluster& operator=(const Cluster&) = delete; - }; - - struct ClusterPtr - { - Cluster* ptr; - }; - - bool operator==(const ClusterPtr& l, const ClusterPtr& r); - enum class InstallPlanType { UNKNOWN, @@ -176,24 +145,7 @@ namespace vcpkg::Dependencies std::vector create_export_plan(const VcpkgPaths& paths, const std::vector& specs, const StatusParagraphs& status_db); -} -template<> -struct std::hash -{ - size_t operator()(const vcpkg::Dependencies::ClusterPtr& value) const - { - return std::hash()(value.ptr->spec); - } -}; - -namespace vcpkg::Dependencies -{ - struct GraphPlan - { - Graphs::Graph remove_graph; - Graphs::Graph install_graph; - }; std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index fa4876bd7..8f92179b5 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -12,11 +12,76 @@ namespace vcpkg::Dependencies { - struct ClusterGraph; - void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); - void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + struct FeatureNodeEdges + { + std::vector remove_edges; + std::vector build_edges; + bool plus = false; + }; + + struct Cluster + { + std::vector status_paragraphs; + Optional source_control_file; + PackageSpec spec; + std::unordered_map edges; + std::unordered_set to_install_features; + std::unordered_set original_features; + bool will_remove = false; + bool transient_uninstalled = true; + Cluster() = default; + + private: + Cluster(const Cluster&) = delete; + Cluster& operator=(const Cluster&) = delete; + }; + + struct ClusterPtr + { + Cluster* ptr; + }; bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } +} + +template<> +struct std::hash +{ + size_t operator()(const vcpkg::Dependencies::ClusterPtr& value) const + { + return std::hash()(value.ptr->spec); + } +}; + +namespace vcpkg::Dependencies +{ + struct GraphPlan + { + Graphs::Graph remove_graph; + Graphs::Graph install_graph; + }; + + struct ClusterGraph + { + explicit ClusterGraph(std::unordered_map&& graph) : m_graph(std::move(graph)) {} + ClusterGraph(ClusterGraph&&) = default; + + Cluster& get(const PackageSpec& spec) + { + if (auto p = try_get(spec)) return *p; + Checks::exit_with_message(VCPKG_LINE_INFO, "error: reference to missing package: %s", spec); + } + Cluster* try_get(const PackageSpec& spec) + { + auto it = m_graph.find(spec); + if (it == m_graph.end()) return nullptr; + return &it->second; + } + + private: + ClusterGraph(const ClusterGraph&) = delete; + std::unordered_map m_graph; + }; std::vector AnyParagraph::dependencies(const Triplet& triplet) const { @@ -362,22 +427,8 @@ namespace vcpkg::Dependencies return toposort; } - struct ClusterGraph - { - explicit ClusterGraph(std::unordered_map&& graph) : m_graph(std::move(graph)) {} - ClusterGraph(ClusterGraph&&) = default; - - Cluster& get(const PackageSpec& spec) - { - auto it = m_graph.find(spec); - if (it == m_graph.end()) Checks::unreachable(VCPKG_LINE_INFO); - return it->second; - } - - private: - ClusterGraph(const ClusterGraph&) = delete; - std::unordered_map m_graph; - }; + void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { @@ -477,33 +528,18 @@ namespace vcpkg::Dependencies node.source_control_file = &it.second; } - for (auto&& status_paragraph : get_installed_ports(status_db)) + auto installed_ports = get_installed_ports(status_db); + + for (auto&& status_paragraph : installed_ports) { - auto& spec = status_paragraph->package.spec; - auto& status_paragraph_feature = status_paragraph->package.feature; - Cluster& cluster = graph[spec]; + Cluster& cluster = graph[status_paragraph->package.spec]; cluster.transient_uninstalled = false; - auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, - status_paragraph->package.spec.triplet()); - for (auto&& dependency : reverse_edges) - { - auto pkg_node = graph.find(dependency.spec()); - auto depends_name = dependency.feature(); - if (depends_name == "") - { - for (auto&& default_feature : status_paragraph->package.default_features) - { - auto& target_node = pkg_node->second.edges[default_feature]; - target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); - } - depends_name = "core"; - } - auto& target_node = pkg_node->second.edges[depends_name]; - target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); - } - cluster.status_paragraphs.emplace_back(*status_paragraph); + cluster.status_paragraphs.emplace_back(status_paragraph); + + auto& status_paragraph_feature = status_paragraph->package.feature; + // In this case, empty string indicates the "core" paragraph for a package. if (status_paragraph_feature == "") { cluster.original_features.insert("core"); @@ -513,6 +549,26 @@ namespace vcpkg::Dependencies cluster.original_features.insert(status_paragraph_feature); } } + + for (auto&& status_paragraph : installed_ports) + { + auto& spec = status_paragraph->package.spec; + auto& status_paragraph_feature = status_paragraph->package.feature; + auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends, + status_paragraph->package.spec.triplet()); + + for (auto&& dependency : reverse_edges) + { + auto dep_cluster = graph.find(dependency.spec()); + if (dep_cluster == graph.end()) Checks::unreachable(VCPKG_LINE_INFO); + + auto depends_name = dependency.feature(); + if (depends_name == "") depends_name = "core"; + + auto& target_node = dep_cluster->second.edges[depends_name]; + target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); + } + } return ClusterGraph(std::move(graph)); } -- cgit v1.2.3 From 27be8b5c7489ea52156669f8e556ad3db1fd11d1 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 21 Aug 2017 17:16:14 -0700 Subject: [vcpkg] Fix feature packages for non-default triplets. Reduce duplication between normal installs and feature installs. --- toolsrc/include/VcpkgPaths.h | 1 + toolsrc/include/vcpkg_Dependencies.h | 17 ++- toolsrc/include/vcpkg_Util.h | 6 +- toolsrc/src/VcpkgPaths.cpp | 1 + toolsrc/src/commands_install.cpp | 269 ++++++++++++++++------------------- toolsrc/src/test_install_plan.cpp | 4 +- toolsrc/src/vcpkg_Dependencies.cpp | 118 ++++++++------- 7 files changed, 207 insertions(+), 209 deletions(-) diff --git a/toolsrc/include/VcpkgPaths.h b/toolsrc/include/VcpkgPaths.h index 95cd4bc28..e4e7ba83d 100644 --- a/toolsrc/include/VcpkgPaths.h +++ b/toolsrc/include/VcpkgPaths.h @@ -21,6 +21,7 @@ namespace vcpkg fs::path package_dir(const PackageSpec& spec) const; fs::path port_dir(const PackageSpec& spec) const; + fs::path port_dir(const std::string& name) const; fs::path build_info_file_path(const PackageSpec& spec) const; fs::path listfile_path(const BinaryParagraph& pgh) const; diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h index 9ac52490e..e6c3c55c9 100644 --- a/toolsrc/include/vcpkg_Dependencies.h +++ b/toolsrc/include/vcpkg_Dependencies.h @@ -86,6 +86,9 @@ namespace vcpkg::Dependencies struct AnyAction { + AnyAction(InstallPlanAction&& iplan) : install_plan(std::move(iplan)) {} + AnyAction(RemovePlanAction&& rplan) : remove_plan(std::move(rplan)) {} + Optional install_plan; Optional remove_plan; }; @@ -114,21 +117,21 @@ namespace vcpkg::Dependencies RequestType request_type; }; - __interface PortFileProvider { virtual const SourceControlFile& get_control_file(const PackageSpec& spec) const; }; + __interface PortFileProvider { virtual const SourceControlFile& get_control_file(const std::string& spec) const; }; struct MapPortFile : PortFileProvider { - const std::unordered_map& ports; - explicit MapPortFile(const std::unordered_map& map); - const SourceControlFile& get_control_file(const PackageSpec& spec) const override; + const std::unordered_map& ports; + explicit MapPortFile(const std::unordered_map& map); + const SourceControlFile& get_control_file(const std::string& spec) const override; }; struct PathsPortFile : PortFileProvider { const VcpkgPaths& ports; - mutable std::unordered_map cache; + mutable std::unordered_map cache; explicit PathsPortFile(const VcpkgPaths& paths); - const SourceControlFile& get_control_file(const PackageSpec& spec) const override; + const SourceControlFile& get_control_file(const std::string& spec) const override; private: PathsPortFile(const PathsPortFile&) = delete; @@ -146,7 +149,7 @@ namespace vcpkg::Dependencies const std::vector& specs, const StatusParagraphs& status_db); - std::vector create_feature_install_plan(const std::unordered_map& map, + std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db); } diff --git a/toolsrc/include/vcpkg_Util.h b/toolsrc/include/vcpkg_Util.h index 671997e7e..a62b48d54 100644 --- a/toolsrc/include/vcpkg_Util.h +++ b/toolsrc/include/vcpkg_Util.h @@ -7,12 +7,12 @@ namespace vcpkg::Util { template - using FmapOut = decltype(std::declval()(std::declval()[0])); + using FmapOut = decltype(std::declval()(*begin(std::declval()))); template> - std::vector fmap(const Cont& xs, Func&& f) + std::vector fmap(Cont&& xs, Func&& f) { - using O = decltype(f(xs[0])); + using O = decltype(f(*begin(xs))); std::vector ret; ret.reserve(xs.size()); diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 60204bcdd..4be636650 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -214,6 +214,7 @@ namespace vcpkg fs::path VcpkgPaths::package_dir(const PackageSpec& spec) const { return this->packages / spec.dir(); } fs::path VcpkgPaths::port_dir(const PackageSpec& spec) const { return this->ports / spec.name(); } + fs::path VcpkgPaths::port_dir(const std::string& name) const { return this->ports / name; } fs::path VcpkgPaths::build_info_file_path(const PackageSpec& spec) const { diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 3fc0e2563..9e37dc057 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -13,11 +13,7 @@ namespace vcpkg::Commands::Install { - using Dependencies::InstallPlanAction; - using Dependencies::InstallPlanType; - using Dependencies::RemovePlanAction; - using Dependencies::RemovePlanType; - using Dependencies::RequestType; + using namespace Dependencies; InstallDir InstallDir::from_destination_root(const fs::path& destination_root, const std::string& destination_subdirectory, @@ -176,41 +172,6 @@ namespace vcpkg::Commands::Install return SortedVector(std::move(installed_files)); } - static void print_plan(const std::map>& group_by_plan_type) - { - static constexpr std::array order = { - InstallPlanType::ALREADY_INSTALLED, InstallPlanType::BUILD_AND_INSTALL, InstallPlanType::INSTALL}; - - for (const InstallPlanType plan_type : order) - { - auto it = group_by_plan_type.find(plan_type); - if (it == group_by_plan_type.cend()) - { - continue; - } - - std::vector cont = it->second; - std::sort(cont.begin(), cont.end(), &InstallPlanAction::compare_by_name); - const std::string as_string = Strings::join("\n", cont, [](const InstallPlanAction* p) { - return Dependencies::to_output_string(p->request_type, p->spec.to_string()); - }); - - switch (plan_type) - { - case InstallPlanType::ALREADY_INSTALLED: - System::println("The following packages are already installed:\n%s", as_string); - continue; - case InstallPlanType::BUILD_AND_INSTALL: - System::println("The following packages will be built and installed:\n%s", as_string); - continue; - case InstallPlanType::INSTALL: - System::println("The following packages will be installed:\n%s", as_string); - continue; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - } - void install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db) { const fs::path package_dir = paths.package_dir(bcf.core_paragraph.spec); @@ -383,19 +344,78 @@ namespace vcpkg::Commands::Install Checks::unreachable(VCPKG_LINE_INFO); } - static void print_plan(const std::vector rebuilt_plans, - const std::vector new_plans) + static void print_plan(const std::vector& action_plan, bool is_recursive) { + std::vector remove_plans; + std::vector rebuilt_plans; + std::vector only_install_plans; + std::vector new_plans; + + const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool { + if (auto iplan = package.install_plan.get()) + return iplan->request_type != RequestType::USER_REQUESTED; + else + return false; + }) != action_plan.cend(); + + for (auto&& action : action_plan) + { + if (auto install_action = action.install_plan.get()) + { + // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at + // all. + auto it = Util::find_if( + remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); + if (it != remove_plans.end()) + { + rebuilt_plans.emplace_back(install_action); + } + else + { + if (install_action->plan_type == InstallPlanType::INSTALL) + only_install_plans.emplace_back(install_action); + else + new_plans.emplace_back(install_action); + } + } + else if (auto remove_action = action.remove_plan.get()) + { + remove_plans.emplace_back(remove_action); + } + } + + std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name); + std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name); + std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name); + const std::string rebuilt_string = Strings::join("\n", rebuilt_plans, [](const InstallPlanAction* p) { - return Dependencies::to_output_string(p->request_type, p->displayname()); + return to_output_string(p->request_type, p->displayname()); }); + if (rebuilt_plans.size() > 0) System::println("The following packages will be rebuilt:\n%s", rebuilt_string); const std::string new_string = Strings::join("\n", new_plans, [](const InstallPlanAction* p) { - return Dependencies::to_output_string(p->request_type, p->displayname()); + return to_output_string(p->request_type, p->displayname()); }); + if (new_plans.size() > 0) + System::println("The following packages will be built and installed:\n%s", new_string); - if (rebuilt_plans.size() > 0) System::println("The following packages will be rebuilt:\n%s", rebuilt_string); - if (new_plans.size() > 0) System::println("The following packages will be installed:\n%s", new_string); + const std::string only_install_string = Strings::join("\n", only_install_plans, [](const InstallPlanAction* p) { + return to_output_string(p->request_type, p->displayname()); + }); + if (only_install_plans.size() > 0) + System::println("The following packages will be directly installed:\n%s", only_install_string); + + if (has_non_user_requested_packages) + System::println("Additional packages (*) will be installed to complete this operation."); + + if (remove_plans.size() > 0 && !is_recursive) + { + System::println(System::Color::warning, + "If you are sure you want to rebuild the above packages, run the command with the " + "--recurse option"); + Checks::exit_fail(VCPKG_LINE_INFO); + } } void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) @@ -410,86 +430,81 @@ namespace vcpkg::Commands::Install Commands::Help::create_example_string("install zlib zlib:x64-windows curl boost"); args.check_min_arg_count(1, example); - const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, example); + const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + return Input::check_and_get_full_package_spec(arg, default_triplet, example); }); + for (auto&& spec : specs) - Input::check_triplet(spec.triplet(), paths); + { + Input::check_triplet(spec.package_spec.triplet(), paths); + if (!spec.features.empty() && !g_feature_packages) + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "Feature packages are experimentally available under the --featurepackages flag."); + } + } const std::unordered_set options = args.check_and_get_optional_command_arguments( {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE}); const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend(); const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend(); const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); - const bool isRecursive = options.find(OPTION_RECURSE) != options.cend(); + const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); // create the plan StatusParagraphs status_db = database_load_check(paths); + const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), + Build::to_allow_downloads(!no_downloads)}; + + std::vector action_plan; + if (g_feature_packages) { - const std::vector full_specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_full_package_spec(arg, default_triplet, example); - }); - - std::unordered_map scf_map; + std::unordered_map scf_map; auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); for (auto&& port : all_ports.paragraphs) { - auto pkg_spec = PackageSpec::from_name_and_triplet(port->core_paragraph->name, default_triplet) - .value_or_exit(VCPKG_LINE_INFO); - scf_map[pkg_spec] = std::move(*port); + scf_map[port->core_paragraph->name] = std::move(*port); } - std::vector action_plan = Dependencies::create_feature_install_plan( - scf_map, FullPackageSpec::to_feature_specs(full_specs), status_db); - // install plan will be empty if it is already installed - need to change this at status paragraph part - Checks::check_exit( - VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty for feature packages"); - - const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), - Build::to_allow_downloads(!no_downloads)}; + action_plan = create_feature_install_plan(scf_map, FullPackageSpec::to_feature_specs(specs), status_db); + } + else + { + Dependencies::PathsPortFile paths_port_file(paths); + auto install_plan = Dependencies::create_install_plan( + paths_port_file, Util::fmap(specs, [](auto&& spec) { return spec.package_spec; }), status_db); - std::vector remove_plans; + action_plan = Util::fmap( + install_plan, [](InstallPlanAction& install_action) { return AnyAction(std::move(install_action)); }); + } - std::vector rebuilt_plans; - std::vector new_plans; + // install plan will be empty if it is already installed - need to change this at status paragraph part + Checks::check_exit(VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty"); - // removal will happen before install - for (auto&& action : action_plan) - { - if (auto install_action = action.install_plan.get()) - { - auto it = Util::find_if( - remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; }); - if (it != remove_plans.end()) - { - rebuilt_plans.emplace_back(install_action); - } - else - { - new_plans.emplace_back(install_action); - } - } - else if (auto remove_action = action.remove_plan.get()) - { - remove_plans.emplace_back(remove_action); - } - } + // log the plan + const std::string specs_string = Strings::join(",", action_plan, [](const AnyAction& action) { + if (auto iaction = action.install_plan.get()) + return iaction->spec.to_string(); + else if (auto raction = action.remove_plan.get()) + return "R$" + raction->spec.to_string(); + Checks::unreachable(VCPKG_LINE_INFO); + }); + Metrics::track_property("installplan", specs_string); - print_plan(rebuilt_plans, new_plans); + print_plan(action_plan, is_recursive); - if (remove_plans.size() > 0 && !isRecursive) - { - System::println(System::Color::warning, - "If you are sure you want to rebuild the above packages, run the command with the " - "--recurse option"); - Checks::exit_fail(VCPKG_LINE_INFO); - } + if (dryRun) + { + Checks::exit_success(VCPKG_LINE_INFO); + } - // execute the plan - for (const Dependencies::AnyAction& any_action : action_plan) + // execute the plan + if (g_feature_packages) + { + for (const auto& action : action_plan) { - if (auto install_action = any_action.install_plan.get()) + if (auto install_action = action.install_plan.get()) { const BuildResult result = perform_install_plan_action(paths, *install_action, install_plan_options, status_db); @@ -499,7 +514,7 @@ namespace vcpkg::Commands::Install Checks::exit_fail(VCPKG_LINE_INFO); } } - else if (auto remove_action = any_action.remove_plan.get()) + else if (auto remove_action = action.remove_plan.get()) { static const std::string OPTION_PURGE = "--purge"; static const std::string OPTION_NO_PURGE = "--no-purge"; @@ -537,50 +552,18 @@ namespace vcpkg::Commands::Install } } } - - Checks::exit_success(VCPKG_LINE_INFO); - } - - Dependencies::PathsPortFile paths_port_file(paths); - std::vector install_plan = - Dependencies::create_install_plan(paths_port_file, specs, status_db); - Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); - - // log the plan - const std::string specs_string = - Strings::join(",", install_plan, [](const InstallPlanAction& plan) { return plan.spec.to_string(); }); - Metrics::track_property("installplan", specs_string); - - std::map> group_by_plan_type; - Util::group_by(install_plan, &group_by_plan_type, [](const InstallPlanAction& p) { return p.plan_type; }); - print_plan(group_by_plan_type); - - const bool has_non_user_requested_packages = - Util::find_if(install_plan, [](const InstallPlanAction& package) -> bool { - return package.request_type != RequestType::USER_REQUESTED; - }) != install_plan.cend(); - - if (has_non_user_requested_packages) - { - System::println("Additional packages (*) will be installed to complete this operation."); } - - if (dryRun) + else { - Checks::exit_success(VCPKG_LINE_INFO); - } - - const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version), - Build::to_allow_downloads(!no_downloads)}; - - // execute the plan - for (const InstallPlanAction& action : install_plan) - { - const BuildResult result = perform_install_plan_action(paths, action, install_plan_options, status_db); - if (result != BuildResult::SUCCEEDED) + for (const auto& action : action_plan) { - System::println(Build::create_user_troubleshooting_message(action.spec)); - Checks::exit_fail(VCPKG_LINE_INFO); + const auto& iaction = action.install_plan.value_or_exit(VCPKG_LINE_INFO); + const BuildResult result = perform_install_plan_action(paths, iaction, install_plan_options, status_db); + if (result != BuildResult::SUCCEEDED) + { + System::println(Build::create_user_troubleshooting_message(iaction.spec)); + Checks::exit_fail(VCPKG_LINE_INFO); + } } } diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index f0884c063..939351872 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -12,7 +12,7 @@ namespace UnitTest1 { struct PackageSpecMap { - std::unordered_map map; + std::unordered_map map; Triplet triplet; PackageSpecMap(const Triplet& t) { triplet = t; } @@ -24,7 +24,7 @@ namespace UnitTest1 auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, triplet); Assert::IsTrue(spec.has_value()); - map.emplace(*spec.get(), std::move(*scf.get())); + map.emplace(scf->core_paragraph->name, std::move(*scf.get())); return PackageSpec{*spec.get()}; } PackageSpec set_package_map(std::string source, std::string version, std::string build_depends) diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 8f92179b5..abab359bb 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -63,24 +63,51 @@ namespace vcpkg::Dependencies struct ClusterGraph { - explicit ClusterGraph(std::unordered_map&& graph) : m_graph(std::move(graph)) {} + explicit ClusterGraph(std::unordered_map&& ports) + : m_ports(std::move(ports)) + { + } ClusterGraph(ClusterGraph&&) = default; Cluster& get(const PackageSpec& spec) - { - if (auto p = try_get(spec)) return *p; - Checks::exit_with_message(VCPKG_LINE_INFO, "error: reference to missing package: %s", spec); - } - Cluster* try_get(const PackageSpec& spec) { auto it = m_graph.find(spec); - if (it == m_graph.end()) return nullptr; - return &it->second; + if (it == m_graph.end()) + { + // Load on-demand from m_ports + auto it_ports = m_ports.find(spec.name()); + if (it_ports != m_ports.end()) + { + auto& clust = m_graph[spec]; + clust.spec = spec; + cluster_from_scf(*it_ports->second, clust); + return clust; + } + return m_graph[spec]; + } + return it->second; } private: + void cluster_from_scf(const SourceControlFile& scf, Cluster& out_cluster) + { + FeatureNodeEdges core_dependencies; + core_dependencies.build_edges = + filter_dependencies_to_specs(scf.core_paragraph->depends, out_cluster.spec.triplet()); + out_cluster.edges.emplace("core", std::move(core_dependencies)); + + for (const auto& feature : scf.feature_paragraphs) + { + FeatureNodeEdges added_edges; + added_edges.build_edges = filter_dependencies_to_specs(feature->depends, out_cluster.spec.triplet()); + out_cluster.edges.emplace(feature->name, std::move(added_edges)); + } + out_cluster.source_control_file = &scf; + } + ClusterGraph(const ClusterGraph&) = delete; std::unordered_map m_graph; + std::unordered_map m_ports; }; std::vector AnyParagraph::dependencies(const Triplet& triplet) const @@ -243,9 +270,9 @@ namespace vcpkg::Dependencies return left->spec.name() < right->spec.name(); } - MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map) {} + MapPortFile::MapPortFile(const std::unordered_map& map) : ports(map) {} - const SourceControlFile& MapPortFile::get_control_file(const PackageSpec& spec) const + const SourceControlFile& MapPortFile::get_control_file(const std::string& spec) const { auto scf = ports.find(spec); if (scf == ports.end()) @@ -257,9 +284,9 @@ namespace vcpkg::Dependencies PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths) {} - const SourceControlFile& PathsPortFile::get_control_file(const PackageSpec& spec) const + const SourceControlFile& PathsPortFile::get_control_file(const std::string& spec) const { - std::unordered_map::iterator cache_it = cache.find(spec); + auto cache_it = cache.find(spec); if (cache_it != cache.end()) { return cache_it->second; @@ -307,7 +334,9 @@ namespace vcpkg::Dependencies auto it = status_db.find_installed(spec); if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type}; return InstallPlanAction{ - spec, {nullopt, nullopt, *port_file_provider.get_control_file(spec).core_paragraph}, request_type}; + spec, + {nullopt, nullopt, *port_file_provider.get_control_file(spec.name()).core_paragraph}, + request_type}; } }; @@ -504,35 +533,19 @@ namespace vcpkg::Dependencies } } - static ClusterGraph create_feature_install_graph(const std::unordered_map& map, + static ClusterGraph create_feature_install_graph(const std::unordered_map& map, const StatusParagraphs& status_db) { - std::unordered_map graph; - - for (const auto& it : map) - { - Cluster& node = graph[it.first]; - - node.spec = it.first; - FeatureNodeEdges core_dependencies; - core_dependencies.build_edges = - filter_dependencies_to_specs(it.second.core_paragraph->depends, node.spec.triplet()); - node.edges.emplace("core", std::move(core_dependencies)); - - for (const auto& feature : it.second.feature_paragraphs) - { - FeatureNodeEdges added_edges; - added_edges.build_edges = filter_dependencies_to_specs(feature->depends, node.spec.triplet()); - node.edges.emplace(feature->name, std::move(added_edges)); - } - node.source_control_file = &it.second; - } + std::unordered_map ptr_map; + for (auto&& p : map) + ptr_map.emplace(p.first, &p.second); + ClusterGraph graph(std::move(ptr_map)); auto installed_ports = get_installed_ports(status_db); for (auto&& status_paragraph : installed_ports) { - Cluster& cluster = graph[status_paragraph->package.spec]; + Cluster& cluster = graph.get(status_paragraph->package.spec); cluster.transient_uninstalled = false; @@ -559,20 +572,19 @@ namespace vcpkg::Dependencies for (auto&& dependency : reverse_edges) { - auto dep_cluster = graph.find(dependency.spec()); - if (dep_cluster == graph.end()) Checks::unreachable(VCPKG_LINE_INFO); + auto& dep_cluster = graph.get(dependency.spec()); auto depends_name = dependency.feature(); if (depends_name == "") depends_name = "core"; - auto& target_node = dep_cluster->second.edges[depends_name]; + auto& target_node = dep_cluster.edges[depends_name]; target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); } } - return ClusterGraph(std::move(graph)); + return graph; } - std::vector create_feature_install_plan(const std::unordered_map& map, + std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db) { @@ -598,15 +610,13 @@ namespace vcpkg::Dependencies for (auto&& like_cluster : remove_toposort) { auto scf = *like_cluster.ptr->source_control_file.get(); - - AnyAction any_plan; - any_plan.remove_plan = RemovePlanAction{ - PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) - .value_or_exit(VCPKG_LINE_INFO), + auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) + .value_or_exit(VCPKG_LINE_INFO); + install_plan.emplace_back(RemovePlanAction{ + std::move(spec), RemovePlanType::REMOVE, - RequestType::AUTO_SELECTED}; - - install_plan.emplace_back(std::move(any_plan)); + RequestType::AUTO_SELECTED, + }); } for (auto&& like_cluster : insert_toposort) @@ -617,12 +627,12 @@ namespace vcpkg::Dependencies auto pkg_spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) .value_or_exit(VCPKG_LINE_INFO); - auto action = - InstallPlanAction{pkg_spec, *scf, like_cluster.ptr->to_install_features, RequestType::AUTO_SELECTED}; - - AnyAction any_plan; - any_plan.install_plan = std::move(action); - install_plan.emplace_back(std::move(any_plan)); + install_plan.emplace_back(InstallPlanAction{ + pkg_spec, + *scf, + like_cluster.ptr->to_install_features, + RequestType::AUTO_SELECTED, + }); } return install_plan; -- cgit v1.2.3 From d708484077ef891c5a69e4d9211613dbcfacb91e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 21 Aug 2017 20:06:47 -0700 Subject: [vcpkg] Feature packages now include user requested packages even if they are already installed. --- toolsrc/include/vcpkg_Dependencies.h | 12 +++--- toolsrc/include/vcpkg_Util.h | 10 +++++ toolsrc/src/test_install_plan.cpp | 82 ++++++++++++++++++++++++++++++++++++ toolsrc/src/vcpkg_Dependencies.cpp | 81 +++++++++++++++++++---------------- 4 files changed, 144 insertions(+), 41 deletions(-) diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h index e6c3c55c9..bfb452596 100644 --- a/toolsrc/include/vcpkg_Dependencies.h +++ b/toolsrc/include/vcpkg_Dependencies.h @@ -3,6 +3,7 @@ #include "StatusParagraphs.h" #include "VcpkgPaths.h" #include "vcpkg_Graphs.h" +#include "vcpkg_Util.h" #include "vcpkg_optional.h" #include @@ -38,20 +39,21 @@ namespace vcpkg::Dependencies ALREADY_INSTALLED }; - struct InstallPlanAction + struct InstallPlanAction : Util::MoveOnlyBase { static bool compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right); InstallPlanAction(); + + InstallPlanAction::InstallPlanAction(const PackageSpec& spec, + const std::unordered_set& features, + const RequestType& request_type); InstallPlanAction(const PackageSpec& spec, const AnyParagraph& any_paragraph, const RequestType& request_type); InstallPlanAction(const PackageSpec& spec, const SourceControlFile& any_paragraph, const std::unordered_set& features, const RequestType& request_type); - InstallPlanAction(const InstallPlanAction&) = delete; - InstallPlanAction(InstallPlanAction&&) = default; - InstallPlanAction& operator=(const InstallPlanAction&) = delete; - InstallPlanAction& operator=(InstallPlanAction&&) = default; + std::string displayname() const; PackageSpec spec; diff --git a/toolsrc/include/vcpkg_Util.h b/toolsrc/include/vcpkg_Util.h index a62b48d54..da2f8eb69 100644 --- a/toolsrc/include/vcpkg_Util.h +++ b/toolsrc/include/vcpkg_Util.h @@ -62,4 +62,14 @@ namespace vcpkg::Util (*output)[key].push_back(&element); } } + + struct MoveOnlyBase + { + MoveOnlyBase() = default; + MoveOnlyBase(const MoveOnlyBase&) = delete; + MoveOnlyBase(MoveOnlyBase&&) = default; + + MoveOnlyBase& operator=(const MoveOnlyBase&) = delete; + MoveOnlyBase& operator=(MoveOnlyBase&&) = default; + }; } \ No newline at end of file diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 939351872..d7a5014a9 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -6,6 +6,34 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace vcpkg; +namespace Microsoft::VisualStudio::CppUnitTestFramework +{ + template<> + inline std::wstring ToString(const vcpkg::Dependencies::InstallPlanType& t) + { + switch (t) + { + case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; + case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; + case Dependencies::InstallPlanType::INSTALL: return L"INSTALL"; + case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; + default: return ToString((int)t); + } + } + + template<> + inline std::wstring ToString(const vcpkg::Dependencies::RequestType& t) + { + switch (t) + { + case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED"; + case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED"; + case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN"; + default: return ToString((int)t); + } + } +} + namespace UnitTest1 { class InstallPlanTests : public TestClass @@ -127,6 +155,60 @@ namespace UnitTest1 Assert::IsTrue(e_pos > g_pos); } + TEST_METHOD(existing_package_scheme) + { + using Pgh = std::unordered_map; + std::vector> status_paragraphs; + status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, + {"Version", "1"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Status", "install ok installed"}})); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.set_package_map("a", "1", ""), {""}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(1), install_plan.size()); + auto p = install_plan[0].install_plan.get(); + Assert::IsNotNull(p); + Assert::AreEqual("a", p->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type); + Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p->request_type); + } + + TEST_METHOD(user_requested_package_scheme) + { + using Pgh = std::unordered_map; + std::vector> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.set_package_map("a", "1", "b"), {""}}; + auto spec_b = FullPackageSpec{spec_map.set_package_map("b", "1", ""), {""}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::AreEqual(size_t(2), install_plan.size()); + auto p = install_plan[0].install_plan.get(); + Assert::IsNotNull(p); + Assert::AreEqual("b", p->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type); + Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type); + + auto p2 = install_plan[1].install_plan.get(); + Assert::IsNotNull(p2); + Assert::AreEqual("a", p2->spec.name().c_str()); + Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type); + Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p2->request_type); + } + TEST_METHOD(long_install_scheme) { using Pgh = std::unordered_map; diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index abab359bb..8741e520f 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -29,6 +29,7 @@ namespace vcpkg::Dependencies std::unordered_set original_features; bool will_remove = false; bool transient_uninstalled = true; + RequestType request_type = RequestType::AUTO_SELECTED; Cluster() = default; private: @@ -39,6 +40,8 @@ namespace vcpkg::Dependencies struct ClusterPtr { Cluster* ptr; + + Cluster* operator->() { return ptr; } }; bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } @@ -147,50 +150,44 @@ namespace vcpkg::Dependencies } } - InstallPlanAction::InstallPlanAction() - : spec(), any_paragraph(), plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) - { - } + InstallPlanAction::InstallPlanAction() : plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {} InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const SourceControlFile& any_paragraph, const std::unordered_set& features, const RequestType& request_type) - : InstallPlanAction() + : spec(spec), plan_type(InstallPlanType::BUILD_AND_INSTALL), request_type(request_type), feature_list(features) { - this->spec = spec; - this->request_type = request_type; - - this->plan_type = InstallPlanType::BUILD_AND_INSTALL; this->any_paragraph.source_control_file = &any_paragraph; - this->feature_list = features; + } + + InstallPlanAction::InstallPlanAction(const PackageSpec& spec, + const std::unordered_set& features, + const RequestType& request_type) + : spec(spec), plan_type(InstallPlanType::ALREADY_INSTALLED), request_type(request_type), feature_list(features) + { } InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const AnyParagraph& any_paragraph, const RequestType& request_type) - : InstallPlanAction() + : spec(spec), request_type(request_type), any_paragraph(any_paragraph) { - this->spec = spec; - this->request_type = request_type; if (auto p = any_paragraph.status_paragraph.get()) { this->plan_type = InstallPlanType::ALREADY_INSTALLED; - this->any_paragraph.status_paragraph = *p; return; } if (auto p = any_paragraph.binary_paragraph.get()) { this->plan_type = InstallPlanType::INSTALL; - this->any_paragraph.binary_paragraph = *p; return; } if (auto p = any_paragraph.source_paragraph.get()) { this->plan_type = InstallPlanType::BUILD_AND_INSTALL; - this->any_paragraph.source_paragraph = *p; return; } @@ -594,7 +591,9 @@ namespace vcpkg::Dependencies for (auto&& spec : specs) { Cluster& spec_cluster = graph.get(spec.spec()); + spec_cluster.request_type = RequestType::USER_REQUESTED; mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster}); } Graphs::GraphAdjacencyProvider adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); @@ -605,36 +604,46 @@ namespace vcpkg::Dependencies auto insert_vertex_list = graph_plan.install_graph.vertex_list(); auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph); - std::vector install_plan; + std::vector plan; - for (auto&& like_cluster : remove_toposort) + for (auto&& p_cluster : remove_toposort) { - auto scf = *like_cluster.ptr->source_control_file.get(); - auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) + auto scf = *p_cluster->source_control_file.get(); + auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, p_cluster->spec.triplet()) .value_or_exit(VCPKG_LINE_INFO); - install_plan.emplace_back(RemovePlanAction{ + plan.emplace_back(RemovePlanAction{ std::move(spec), RemovePlanType::REMOVE, - RequestType::AUTO_SELECTED, + p_cluster->request_type, }); } - for (auto&& like_cluster : insert_toposort) + for (auto&& p_cluster : insert_toposort) { - if (!like_cluster.ptr->transient_uninstalled) continue; - - auto scf = *like_cluster.ptr->source_control_file.get(); - auto pkg_spec = - PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) - .value_or_exit(VCPKG_LINE_INFO); - install_plan.emplace_back(InstallPlanAction{ - pkg_spec, - *scf, - like_cluster.ptr->to_install_features, - RequestType::AUTO_SELECTED, - }); + if (p_cluster->transient_uninstalled) + { + // If it will be transiently uninstalled, we need to issue a full installation command + auto pscf = p_cluster->source_control_file.value_or_exit(VCPKG_LINE_INFO); + Checks::check_exit(VCPKG_LINE_INFO, pscf != nullptr); + plan.emplace_back(InstallPlanAction{ + p_cluster->spec, + *pscf, + p_cluster->to_install_features, + p_cluster->request_type, + }); + } + else + { + // If the package isn't transitively installed, still include it if the user explicitly requested it + if (p_cluster->request_type != RequestType::USER_REQUESTED) continue; + plan.emplace_back(InstallPlanAction{ + p_cluster->spec, + p_cluster->original_features, + p_cluster->request_type, + }); + } } - return install_plan; + return plan; } } -- cgit v1.2.3 From 6784704638f46d89d01458b1004e588f535958aa Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 21 Aug 2017 21:08:43 -0700 Subject: [vcpkg] Improve error messages when a feature is requested that doesn't exist. --- toolsrc/include/PackageSpec.h | 2 ++ toolsrc/src/PackageSpec.cpp | 12 +++++++-- toolsrc/src/test_install_plan.cpp | 6 ++--- toolsrc/src/vcpkg_Dependencies.cpp | 53 +++++++++++++++++++++++++++++--------- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/toolsrc/include/PackageSpec.h b/toolsrc/include/PackageSpec.h index 8b485316f..c5ce767f9 100644 --- a/toolsrc/include/PackageSpec.h +++ b/toolsrc/include/PackageSpec.h @@ -43,6 +43,8 @@ namespace vcpkg const PackageSpec& spec() const { return m_spec; } + std::string to_string() const; + static std::vector from_strings_and_triplet(const std::vector& depends, const Triplet& t); diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index a5d40e998..a43bc5ff5 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -13,6 +13,12 @@ namespace vcpkg return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)) || (c == '[') || (c == ']'); } + std::string FeatureSpec::to_string() const + { + if (feature().empty()) return spec().to_string(); + return Strings::format("%s[%s]:%s", name(), feature(), triplet()); + } + std::vector FeatureSpec::from_strings_and_triplet(const std::vector& depends, const Triplet& triplet) { @@ -36,8 +42,10 @@ namespace vcpkg } else { - Checks::exit_with_message( - VCPKG_LINE_INFO, "error while parsing feature list: %s: %s", to_string(maybe_spec.error()), depend); + Checks::exit_with_message(VCPKG_LINE_INFO, + "error while parsing feature list: %s: %s", + vcpkg::to_string(maybe_spec.error()), + depend); } } return f_specs; diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index d7a5014a9..1c415f273 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -537,9 +537,9 @@ namespace UnitTest1 remove_plan_check(&install_plan[1], "b"); // TODO: order here may change but A < X, and B anywhere - features_check(&install_plan[2], "a", {"core"}); - features_check(&install_plan[3], "x", {"core"}); - features_check(&install_plan[4], "b", {"core", "1"}); + features_check(&install_plan[2], "b", {"core", "1"}); + features_check(&install_plan[3], "a", {"core"}); + features_check(&install_plan[4], "x", {"core"}); } TEST_METHOD(basic_feature_test_8) diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 8741e520f..512e65e28 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -453,23 +453,30 @@ namespace vcpkg::Dependencies return toposort; } - void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); + enum class MarkPlusResult + { + FEATURE_NOT_FOUND, + SUCCESS, + }; + + MarkPlusResult mark_plus(const std::string& feature, + Cluster& cluster, + ClusterGraph& pkg_to_cluster, + GraphPlan& graph_plan); void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan); - void mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) + MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { if (feature == "") { // Indicates that core was not specified in the reference return mark_plus("core", cluster, graph, graph_plan); } + auto it = cluster.edges.find(feature); - if (it == cluster.edges.end()) - { - Checks::unreachable(VCPKG_LINE_INFO); - } + if (it == cluster.edges.end()) return MarkPlusResult::FEATURE_NOT_FOUND; - if (cluster.edges[feature].plus) return; + if (cluster.edges[feature].plus) return MarkPlusResult::SUCCESS; if (cluster.original_features.find(feature) == cluster.original_features.end()) { @@ -478,7 +485,7 @@ namespace vcpkg::Dependencies if (!cluster.transient_uninstalled) { - return; + return MarkPlusResult::SUCCESS; } cluster.edges[feature].plus = true; @@ -494,16 +501,28 @@ namespace vcpkg::Dependencies if (feature != "core") { // All features implicitly depend on core - mark_plus("core", cluster, graph, graph_plan); + auto res = mark_plus("core", cluster, graph, graph_plan); + + // Should be impossible for "core" to not exist + Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS); } for (auto&& depend : cluster.edges[feature].build_edges) { auto& depend_cluster = graph.get(depend.spec()); - mark_plus(depend.feature(), depend_cluster, graph, graph_plan); + auto res = mark_plus(depend.feature(), depend_cluster, graph, graph_plan); + + Checks::check_exit(VCPKG_LINE_INFO, + res == MarkPlusResult::SUCCESS, + "Error: Unable to satisfy dependency %s of %s", + depend, + FeatureSpec(cluster.spec, feature)); + if (&depend_cluster == &cluster) continue; graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); } + + return MarkPlusResult::SUCCESS; } void mark_minus(Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) @@ -526,7 +545,13 @@ namespace vcpkg::Dependencies cluster.transient_uninstalled = true; for (auto&& original_feature : cluster.original_features) { - mark_plus(original_feature, cluster, graph, graph_plan); + auto res = mark_plus(original_feature, cluster, graph, graph_plan); + if (res != MarkPlusResult::SUCCESS) + { + System::println(System::Color::warning, + "Warning: could not reinstall feature %s", + FeatureSpec{cluster.spec, original_feature}); + } } } @@ -592,7 +617,11 @@ namespace vcpkg::Dependencies { Cluster& spec_cluster = graph.get(spec.spec()); spec_cluster.request_type = RequestType::USER_REQUESTED; - mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + auto res = mark_plus(spec.feature(), spec_cluster, graph, graph_plan); + + Checks::check_exit( + VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec); + graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster}); } -- cgit v1.2.3 From bee29497f9e210c2b8d33edccba0d1d95188d852 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 22 Aug 2017 15:03:42 -0700 Subject: [vcpkg] Compact tests for improved maintainability. --- toolsrc/src/test_install_plan.cpp | 421 +++++++++++++------------------------- 1 file changed, 142 insertions(+), 279 deletions(-) diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 1c415f273..836ff09ae 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -38,28 +38,30 @@ namespace UnitTest1 { class InstallPlanTests : public TestClass { - struct PackageSpecMap + static std::unique_ptr make_control_file( + const char* name, + const char* depends, + const std::vector>& features = {}) { - std::unordered_map map; - Triplet triplet; - PackageSpecMap(const Triplet& t) { triplet = t; } - - PackageSpec get_package_spec(std::vector>&& fields) - { - auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(fields)); - Assert::IsTrue(m_pgh.has_value()); - auto& scf = *m_pgh.get(); - - auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, triplet); - Assert::IsTrue(spec.has_value()); - map.emplace(scf->core_paragraph->name, std::move(*scf.get())); - return PackageSpec{*spec.get()}; - } - PackageSpec set_package_map(std::string source, std::string version, std::string build_depends) + using Pgh = std::unordered_map; + std::vector scf_pghs; + scf_pghs.push_back(Pgh{ + {"Source", name}, + {"Version", "0"}, + {"Build-Depends", depends}, + }); + for (auto&& feature : features) { - return get_package_spec({{{"Source", source}, {"Version", version}, {"Build-Depends", build_depends}}}); + scf_pghs.push_back(Pgh{ + {"Feature", feature.first}, + {"Description", "feature"}, + {"Build-Depends", feature.second}, + }); } - }; + auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(scf_pghs)); + Assert::IsTrue(m_pgh.has_value()); + return std::move(*m_pgh.get()); + } static void features_check(Dependencies::AnyAction* install_action, std::string pkg_name, @@ -96,14 +98,58 @@ namespace UnitTest1 Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); } + static std::unique_ptr make_status_pgh(const char* name, const char* depends = "") + { + using Pgh = std::unordered_map; + return std::make_unique(Pgh{{"Package", name}, + {"Version", "1"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Status", "install ok installed"}}); + } + static std::unique_ptr make_status_feature_pgh(const char* name, + const char* feature, + const char* depends = "") + { + using Pgh = std::unordered_map; + return std::make_unique(Pgh{{"Package", name}, + {"Version", "1"}, + {"Feature", feature}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Status", "install ok installed"}}); + } + struct PackageSpecMap + { + std::unordered_map map; + Triplet triplet; + PackageSpecMap(const Triplet& t) { triplet = t; } + + PackageSpec emplace(const char* name, + const char* depends = "", + const std::vector>& features = {}) + { + return emplace(std::move(*make_control_file(name, depends, features))); + } + PackageSpec emplace(vcpkg::SourceControlFile&& scf) + { + auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph->name, triplet); + Assert::IsTrue(spec.has_value()); + map.emplace(scf.core_paragraph->name, std::move(scf)); + return PackageSpec{*spec.get()}; + } + }; + TEST_METHOD(basic_install_scheme) { std::vector> status_paragraphs; PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.set_package_map("a", "1.2.8", "b"); - auto spec_b = spec_map.set_package_map("b", "1.3", "c"); - auto spec_c = spec_map.set_package_map("c", "2.5.3", ""); + auto spec_a = spec_map.emplace("a", "b"); + auto spec_b = spec_map.emplace("b", "c"); + auto spec_c = spec_map.emplace("c"); auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = @@ -120,14 +166,14 @@ namespace UnitTest1 std::vector> status_paragraphs; PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.set_package_map("a", "1.2.8", "d"); - auto spec_b = spec_map.set_package_map("b", "1.3", "d, e"); - auto spec_c = spec_map.set_package_map("c", "2.5.3", "e, h"); - auto spec_d = spec_map.set_package_map("d", "4.0", "f, g, h"); - auto spec_e = spec_map.set_package_map("e", "1.0", "g"); - auto spec_f = spec_map.set_package_map("f", "1.0", ""); - auto spec_g = spec_map.set_package_map("g", "1.0", ""); - auto spec_h = spec_map.set_package_map("h", "1.0", ""); + auto spec_a = spec_map.emplace("a", "d"); + auto spec_b = spec_map.emplace("b", "d, e"); + auto spec_c = spec_map.emplace("c", "e, h"); + auto spec_d = spec_map.emplace("d", "f, g, h"); + auto spec_e = spec_map.emplace("e", "g"); + auto spec_f = spec_map.emplace("f"); + auto spec_g = spec_map.emplace("g"); + auto spec_h = spec_map.emplace("h"); auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = Dependencies::create_install_plan( @@ -157,16 +203,11 @@ namespace UnitTest1 TEST_METHOD(existing_package_scheme) { - using Pgh = std::unordered_map; std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Version", "1"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("a")); PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.set_package_map("a", "1", ""), {""}}; + auto spec_a = FullPackageSpec{spec_map.emplace("a")}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -183,12 +224,11 @@ namespace UnitTest1 TEST_METHOD(user_requested_package_scheme) { - using Pgh = std::unordered_map; std::vector> status_paragraphs; PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.set_package_map("a", "1", "b"), {""}}; - auto spec_b = FullPackageSpec{spec_map.set_package_map("b", "1", ""), {""}}; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b")}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -211,33 +251,22 @@ namespace UnitTest1 TEST_METHOD(long_install_scheme) { - using Pgh = std::unordered_map; std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "j"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "k"}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "k"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("j", "k")); + status_paragraphs.push_back(make_status_pgh("k")); PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = spec_map.set_package_map("a", "1.2.8", "b, c, d, e, f, g, h, j, k"); - auto spec_b = spec_map.set_package_map("b", "1.2.8", "c, d, e, f, g, h, j, k"); - auto spec_c = spec_map.set_package_map("c", "1.2.8", "d, e, f, g, h, j, k"); - auto spec_d = spec_map.set_package_map("d", "1.2.8", "e, f, g, h, j, k"); - auto spec_e = spec_map.set_package_map("e", "1.2.8", "f, g, h, j, k"); - auto spec_f = spec_map.set_package_map("f", "1.2.8", "g, h, j, k"); - auto spec_g = spec_map.set_package_map("g", "1.2.8", "h, j, k"); - auto spec_h = spec_map.set_package_map("h", "1.2.8", "j, k"); - auto spec_j = spec_map.set_package_map("j", "1.2.8", "k"); - auto spec_k = spec_map.set_package_map("k", "1.2.8", ""); + auto spec_a = spec_map.emplace("a", "b, c, d, e, f, g, h, j, k"); + auto spec_b = spec_map.emplace("b", "c, d, e, f, g, h, j, k"); + auto spec_c = spec_map.emplace("c", "d, e, f, g, h, j, k"); + auto spec_d = spec_map.emplace("d", "e, f, g, h, j, k"); + auto spec_e = spec_map.emplace("e", "f, g, h, j, k"); + auto spec_f = spec_map.emplace("f", "g, h, j, k"); + auto spec_g = spec_map.emplace("g", "h, j, k"); + auto spec_h = spec_map.emplace("h", "j, k"); + auto spec_j = spec_map.emplace("j", "k"); + auto spec_k = spec_map.emplace("k"); auto map_port = Dependencies::MapPortFile(spec_map.map); auto install_plan = @@ -256,45 +285,14 @@ namespace UnitTest1 TEST_METHOD(basic_feature_test_1) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Default-Features", ""}, - {"Version", "1.3.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "b, b[beefeatureone]"}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, - {"Feature", "beefeatureone"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, - {"Default-Features", "beefeatureone"}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("a", "b, b[b1]")); + status_paragraphs.push_back(make_status_pgh("b")); + status_paragraphs.push_back(make_status_feature_pgh("b", "b1")); PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = - FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b, b[beefeatureone]"}}, - {{"Feature", "featureone"}, - {"Description", "the first feature for a"}, - {"Build-Depends", "b[beefeaturetwo]"}}, - }), - {"featureone"}}; - auto spec_b = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}}, - })}; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -304,33 +302,18 @@ namespace UnitTest1 Assert::AreEqual(size_t(4), install_plan.size()); remove_plan_check(&install_plan[0], "a"); remove_plan_check(&install_plan[1], "b"); - features_check(&install_plan[2], "b", {"beefeatureone", "core", "beefeatureone"}); - features_check(&install_plan[3], "a", {"featureone", "core"}); + features_check(&install_plan[2], "b", {"b1", "core", "b1"}); + features_check(&install_plan[3], "a", {"a1", "core"}); } TEST_METHOD(basic_feature_test_2) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = - FullPackageSpec{spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b[beefeatureone]"}}, - {{"Feature", "featureone"}, - {"Description", "the first feature for a"}, - {"Build-Depends", "b[beefeaturetwo]"}} - - }), - {"featureone"}}; - auto spec_b = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}}, - })}; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -338,37 +321,20 @@ namespace UnitTest1 StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(2), install_plan.size()); - features_check(&install_plan[0], "b", {"beefeatureone", "beefeaturetwo", "core"}); - features_check(&install_plan[1], "a", {"featureone", "core"}); + features_check(&install_plan[0], "b", {"b1", "b2", "core"}); + features_check(&install_plan[1], "a", {"a1", "core"}); } TEST_METHOD(basic_feature_test_3) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("a")); PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, - {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), - {"core"}}; - auto spec_b = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - })}; - auto spec_c = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, - }), - {"core"}}; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -378,43 +344,21 @@ namespace UnitTest1 Assert::AreEqual(size_t(4), install_plan.size()); remove_plan_check(&install_plan[0], "a"); features_check(&install_plan[1], "b", {"core"}); - features_check(&install_plan[2], "a", {"one", "core"}); + features_check(&install_plan[2], "a", {"a1", "core"}); features_check(&install_plan[3], "c", {"core"}); } TEST_METHOD(basic_feature_test_4) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Feature", "one"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.push_back(make_status_feature_pgh("a", "a1", "")); PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, - {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), - }; - auto spec_b = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - })}; - auto spec_c = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, - }), - {"core"}}; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}})}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -427,24 +371,13 @@ namespace UnitTest1 TEST_METHOD(basic_feature_test_5) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[1]"}}, - {{"Feature", "2"}, {"Description", "the second feature for a"}, {"Build-Depends", "b[2]"}}, - {{"Feature", "3"}, {"Description", "the third feature for a"}, {"Build-Depends", "a[2]"}}}), - {"3"}}; - auto spec_b = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}}, - {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}}, - })}; + auto spec_a = + FullPackageSpec{spec_map.emplace("a", "", {{"a1", "b[b1]"}, {"a2", "b[b2]"}, {"a3", "a[a2]"}}), {"a3"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}})}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -452,34 +385,18 @@ namespace UnitTest1 StatusParagraphs(std::move(status_paragraphs))); Assert::AreEqual(size_t(2), install_plan.size()); - features_check(&install_plan[0], "b", {"core", "2"}); - features_check(&install_plan[1], "a", {"core", "3", "2"}); + features_check(&install_plan[0], "b", {"core", "b2"}); + features_check(&install_plan[1], "a", {"core", "a3", "a2"}); } TEST_METHOD(basic_feature_test_6) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); - PackageSpecMap spec_map(Triplet::X86_WINDOWS); + status_paragraphs.push_back(make_status_pgh("b")); - auto spec_a = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b[core]"}}, - }), - {"core"}}; - auto spec_b = FullPackageSpec{ - spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, - }), - {"1"}}; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[core]"), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -488,44 +405,21 @@ namespace UnitTest1 Assert::AreEqual(size_t(3), install_plan.size()); remove_plan_check(&install_plan[0], "b"); - features_check(&install_plan[1], "b", {"core", "1"}); + features_check(&install_plan[1], "b", {"core", "b1"}); features_check(&install_plan[2], "a", {"core"}); } TEST_METHOD(basic_feature_test_7) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "x"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "b"}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "b"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("x", "b")); + status_paragraphs.push_back(make_status_pgh("b")); + PackageSpecMap spec_map(Triplet::X86_WINDOWS); - auto spec_a = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - })}; - auto spec_x = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "x"}, {"Version", "1.3"}, {"Build-Depends", "a"}}, - }), - {"core"}}; - auto spec_b = FullPackageSpec{ - spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}, {"Default-Features", ""}}, - {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}, - }), - {"1"}}; + auto spec_a = FullPackageSpec{spec_map.emplace("a")}; + auto spec_x = FullPackageSpec{spec_map.emplace("x", "a"), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, @@ -537,59 +431,28 @@ namespace UnitTest1 remove_plan_check(&install_plan[1], "b"); // TODO: order here may change but A < X, and B anywhere - features_check(&install_plan[2], "b", {"core", "1"}); + features_check(&install_plan[2], "b", {"core", "b1"}); features_check(&install_plan[3], "a", {"core"}); features_check(&install_plan[4], "x", {"core"}); } TEST_METHOD(basic_feature_test_8) { - using Pgh = std::unordered_map; - std::vector> status_paragraphs; - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x64-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); - status_paragraphs.push_back(std::make_unique(Pgh{{"Package", "a"}, - {"Default-Features", ""}, - {"Version", "1.3"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", ""}, - {"Status", "install ok installed"}})); + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.spec = + PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); PackageSpecMap spec_map(Triplet::X64_WINDOWS); - - auto spec_a_64 = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, - {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), - {"core"}}; - auto spec_b_64 = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - })}; - auto spec_c_64 = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, - }), - {"core"}}; + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; spec_map.triplet = Triplet::X86_WINDOWS; - auto spec_a_86 = FullPackageSpec{ - spec_map.get_package_spec( - {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, - {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), - {"core"}}; - auto spec_b_86 = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, - })}; - auto spec_c_86 = FullPackageSpec{spec_map.get_package_spec({ - {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, - }), - {"core"}}; + auto spec_a_86 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b_86 = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c_86 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; auto install_plan = Dependencies::create_feature_install_plan( spec_map.map, @@ -613,10 +476,10 @@ namespace UnitTest1 remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); remove_plan_check(&install_plan[1], "a"); features_check(&install_plan[2], "b", {"core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[3], "a", {"one", "core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[3], "a", {"a1", "core"}, Triplet::X64_WINDOWS); features_check(&install_plan[4], "c", {"core"}, Triplet::X64_WINDOWS); features_check(&install_plan[5], "b", {"core"}); - features_check(&install_plan[6], "a", {"one", "core"}); + features_check(&install_plan[6], "a", {"a1", "core"}); features_check(&install_plan[7], "c", {"core"}); } }; -- cgit v1.2.3 From 92dd1b77ed043da376c86874aacc1233270fedae Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 22 Aug 2017 15:14:15 -0700 Subject: [vcpkg] Add Util::ResourceBase, use MoveOnlyBase --- toolsrc/include/vcpkg_Dependencies.h | 20 ++++---------------- toolsrc/include/vcpkg_Util.h | 10 ++++++++++ toolsrc/src/test_install_plan.cpp | 6 +++--- toolsrc/src/vcpkg_Dependencies.cpp | 11 ++--------- 4 files changed, 19 insertions(+), 28 deletions(-) diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h index bfb452596..93719efe9 100644 --- a/toolsrc/include/vcpkg_Dependencies.h +++ b/toolsrc/include/vcpkg_Dependencies.h @@ -70,16 +70,12 @@ namespace vcpkg::Dependencies REMOVE }; - struct RemovePlanAction + struct RemovePlanAction : Util::MoveOnlyBase { static bool compare_by_name(const RemovePlanAction* left, const RemovePlanAction* right); RemovePlanAction(); RemovePlanAction(const PackageSpec& spec, const RemovePlanType& plan_type, const RequestType& request_type); - RemovePlanAction(const RemovePlanAction&) = delete; - RemovePlanAction(RemovePlanAction&&) = default; - RemovePlanAction& operator=(const RemovePlanAction&) = delete; - RemovePlanAction& operator=(RemovePlanAction&&) = default; PackageSpec spec; RemovePlanType plan_type; @@ -102,16 +98,12 @@ namespace vcpkg::Dependencies ALREADY_BUILT }; - struct ExportPlanAction + struct ExportPlanAction : Util::MoveOnlyBase { static bool compare_by_name(const ExportPlanAction* left, const ExportPlanAction* right); ExportPlanAction(); ExportPlanAction(const PackageSpec& spec, const AnyParagraph& any_paragraph, const RequestType& request_type); - ExportPlanAction(const ExportPlanAction&) = delete; - ExportPlanAction(ExportPlanAction&&) = default; - ExportPlanAction& operator=(const ExportPlanAction&) = delete; - ExportPlanAction& operator=(ExportPlanAction&&) = default; PackageSpec spec; AnyParagraph any_paragraph; @@ -121,23 +113,19 @@ namespace vcpkg::Dependencies __interface PortFileProvider { virtual const SourceControlFile& get_control_file(const std::string& spec) const; }; - struct MapPortFile : PortFileProvider + struct MapPortFile : Util::ResourceBase, PortFileProvider { const std::unordered_map& ports; explicit MapPortFile(const std::unordered_map& map); const SourceControlFile& get_control_file(const std::string& spec) const override; }; - struct PathsPortFile : PortFileProvider + struct PathsPortFile : Util::ResourceBase, PortFileProvider { const VcpkgPaths& ports; mutable std::unordered_map cache; explicit PathsPortFile(const VcpkgPaths& paths); const SourceControlFile& get_control_file(const std::string& spec) const override; - - private: - PathsPortFile(const PathsPortFile&) = delete; - PathsPortFile& operator=(const PathsPortFile&) = delete; }; std::vector create_install_plan(const PortFileProvider& port_file_provider, diff --git a/toolsrc/include/vcpkg_Util.h b/toolsrc/include/vcpkg_Util.h index da2f8eb69..4f45cd2c7 100644 --- a/toolsrc/include/vcpkg_Util.h +++ b/toolsrc/include/vcpkg_Util.h @@ -72,4 +72,14 @@ namespace vcpkg::Util MoveOnlyBase& operator=(const MoveOnlyBase&) = delete; MoveOnlyBase& operator=(MoveOnlyBase&&) = default; }; + + struct ResourceBase + { + ResourceBase() = default; + ResourceBase(const ResourceBase&) = delete; + ResourceBase(ResourceBase&&) = delete; + + ResourceBase& operator=(const ResourceBase&) = delete; + ResourceBase& operator=(ResourceBase&&) = delete; + }; } \ No newline at end of file diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 836ff09ae..6c9311264 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -151,7 +151,7 @@ namespace UnitTest1 auto spec_b = spec_map.emplace("b", "c"); auto spec_c = spec_map.emplace("c"); - auto map_port = Dependencies::MapPortFile(spec_map.map); + Dependencies::MapPortFile map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); @@ -175,7 +175,7 @@ namespace UnitTest1 auto spec_g = spec_map.emplace("g"); auto spec_h = spec_map.emplace("h"); - auto map_port = Dependencies::MapPortFile(spec_map.map); + Dependencies::MapPortFile map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan( map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs))); @@ -268,7 +268,7 @@ namespace UnitTest1 auto spec_j = spec_map.emplace("j", "k"); auto spec_k = spec_map.emplace("k"); - auto map_port = Dependencies::MapPortFile(spec_map.map); + Dependencies::MapPortFile map_port(spec_map.map); auto install_plan = Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs))); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 512e65e28..188b0f444 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -19,7 +19,7 @@ namespace vcpkg::Dependencies bool plus = false; }; - struct Cluster + struct Cluster : Util::MoveOnlyBase { std::vector status_paragraphs; Optional source_control_file; @@ -30,11 +30,6 @@ namespace vcpkg::Dependencies bool will_remove = false; bool transient_uninstalled = true; RequestType request_type = RequestType::AUTO_SELECTED; - Cluster() = default; - - private: - Cluster(const Cluster&) = delete; - Cluster& operator=(const Cluster&) = delete; }; struct ClusterPtr @@ -64,13 +59,12 @@ namespace vcpkg::Dependencies Graphs::Graph install_graph; }; - struct ClusterGraph + struct ClusterGraph : Util::MoveOnlyBase { explicit ClusterGraph(std::unordered_map&& ports) : m_ports(std::move(ports)) { } - ClusterGraph(ClusterGraph&&) = default; Cluster& get(const PackageSpec& spec) { @@ -108,7 +102,6 @@ namespace vcpkg::Dependencies out_cluster.source_control_file = &scf; } - ClusterGraph(const ClusterGraph&) = delete; std::unordered_map m_graph; std::unordered_map m_ports; }; -- cgit v1.2.3