diff options
| author | Robert Schumacher <roschuma@microsoft.com> | 2017-04-12 22:57:23 -0700 |
|---|---|---|
| committer | Robert Schumacher <roschuma@microsoft.com> | 2017-04-12 22:57:23 -0700 |
| commit | c3b54a2e7bd0a07068b6a12c29b00b8f57bdb3f1 (patch) | |
| tree | 65f0fbf52220f8f5225da13a69afa415c0c0ff09 /toolsrc/src | |
| parent | 7069fbbebc750a7c8a64adc8c30269527cbec9bd (diff) | |
| parent | 3739e8e0b998b14c0f320c21618057e50698c51d (diff) | |
| download | vcpkg-c3b54a2e7bd0a07068b6a12c29b00b8f57bdb3f1.tar.gz vcpkg-c3b54a2e7bd0a07068b6a12c29b00b8f57bdb3f1.zip | |
Merge from master
Diffstat (limited to 'toolsrc/src')
| -rw-r--r-- | toolsrc/src/PackageSpec.cpp | 5 | ||||
| -rw-r--r-- | toolsrc/src/StatusParagraphs.cpp | 2 | ||||
| -rw-r--r-- | toolsrc/src/commands_build.cpp | 17 | ||||
| -rw-r--r-- | toolsrc/src/commands_ci.cpp | 12 | ||||
| -rw-r--r-- | toolsrc/src/commands_hash.cpp | 3 | ||||
| -rw-r--r-- | toolsrc/src/commands_install.cpp | 36 | ||||
| -rw-r--r-- | toolsrc/src/commands_integrate.cpp | 9 | ||||
| -rw-r--r-- | toolsrc/src/commands_remove.cpp | 28 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg_Dependencies.cpp | 260 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg_Strings.cpp | 9 | ||||
| -rw-r--r-- | toolsrc/src/vcpkglib.cpp | 11 |
11 files changed, 211 insertions, 181 deletions
diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index bf1c7380c..2a7f4506c 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -64,4 +64,9 @@ namespace vcpkg { return left.name() == right.name() && left.triplet() == right.triplet(); } + + bool operator!=(const PackageSpec& left, const PackageSpec& right) + { + return !(left == right); + } } diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp index 132b7d5d4..f41630132 100644 --- a/toolsrc/src/StatusParagraphs.cpp +++ b/toolsrc/src/StatusParagraphs.cpp @@ -2,8 +2,6 @@ #include "StatusParagraphs.h" #include "vcpkg_Checks.h" #include <algorithm> -#include <algorithm> -#include <algorithm> namespace vcpkg { diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index 8d91ce813..9110e1fd0 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -10,10 +10,11 @@ #include "metrics.h" #include "vcpkg_Enums.h" #include "Paragraphs.h" +#include "vcpkg_Util.h" namespace vcpkg::Commands::Build { - using Dependencies::PackageSpecWithInstallPlan; + using Dependencies::InstallPlanAction; using Dependencies::InstallPlanType; static const std::string OPTION_CHECKS_ONLY = "--checks-only"; @@ -148,19 +149,17 @@ namespace vcpkg::Commands::Build const BuildResult result = build_package(spgh, spec, paths, paths.port_dir(spec), status_db); if (result == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES) { - std::vector<PackageSpecWithInstallPlan> unmet_dependencies = Dependencies::create_install_plan(paths, { spec }, status_db); - unmet_dependencies.erase( - std::remove_if(unmet_dependencies.begin(), unmet_dependencies.end(), [&spec](const PackageSpecWithInstallPlan& p) - { - return (p.spec == spec) || (p.plan.plan_type == InstallPlanType::ALREADY_INSTALLED); - }), - unmet_dependencies.end()); + std::vector<InstallPlanAction> unmet_dependencies = Dependencies::create_install_plan(paths, { spec }, status_db); + Util::keep_if(unmet_dependencies, [&spec](const InstallPlanAction& p) + { + return (p.spec != spec) && (p.plan_type != InstallPlanType::ALREADY_INSTALLED); + }); Checks::check_exit(VCPKG_LINE_INFO, !unmet_dependencies.empty()); System::println(System::Color::error, "The build command requires all dependencies to be already installed."); System::println("The following dependencies are missing:"); System::println(""); - for (const PackageSpecWithInstallPlan& p : unmet_dependencies) + for (const InstallPlanAction& p : unmet_dependencies) { System::println(" %s", p.spec); } diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index d4b2865a6..a40a7ed32 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -10,7 +10,7 @@ namespace vcpkg::Commands::CI { - using Dependencies::PackageSpecWithInstallPlan; + using Dependencies::InstallPlanAction; using Dependencies::InstallPlanType; using Build::BuildResult; @@ -36,7 +36,7 @@ namespace vcpkg::Commands::CI const std::vector<PackageSpec> specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet); StatusParagraphs status_db = database_load_check(paths); - const std::vector<PackageSpecWithInstallPlan> install_plan = Dependencies::create_install_plan(paths, specs, status_db); + const std::vector<InstallPlanAction> install_plan = Dependencies::create_install_plan(paths, specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); std::vector<BuildResult> results; @@ -44,7 +44,7 @@ namespace vcpkg::Commands::CI const ElapsedTime timer = ElapsedTime::create_started(); size_t counter = 0; const size_t package_count = install_plan.size(); - for (const PackageSpecWithInstallPlan& action : install_plan) + for (const InstallPlanAction& action : install_plan) { const ElapsedTime build_timer = ElapsedTime::create_started(); counter++; @@ -56,7 +56,7 @@ namespace vcpkg::Commands::CI try { - switch (action.plan.plan_type) + switch (action.plan_type) { case InstallPlanType::ALREADY_INSTALLED: results.back() = BuildResult::SUCCEEDED; @@ -65,7 +65,7 @@ namespace vcpkg::Commands::CI case InstallPlanType::BUILD_AND_INSTALL: { System::println("Building package %s... ", display_name); - const BuildResult result = Commands::Build::build_package(action.plan.source_pgh.value_or_exit(VCPKG_LINE_INFO), + const BuildResult result = Commands::Build::build_package(action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO), action.spec, paths, paths.port_dir(action.spec), @@ -88,7 +88,7 @@ namespace vcpkg::Commands::CI case InstallPlanType::INSTALL: results.back() = BuildResult::SUCCEEDED; System::println("Installing package %s... ", display_name); - Install::install_package(paths, action.plan.binary_pgh.value_or_exit(VCPKG_LINE_INFO), &status_db); + Install::install_package(paths, action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO), &status_db); System::println(System::Color::success, "Installing package %s... done", display_name); break; default: diff --git a/toolsrc/src/commands_hash.cpp b/toolsrc/src/commands_hash.cpp index 2ffa3a9aa..a9024d9e7 100644 --- a/toolsrc/src/commands_hash.cpp +++ b/toolsrc/src/commands_hash.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "vcpkg_Commands.h" #include "vcpkg_System.h" +#include "vcpkg_Util.h" namespace vcpkg::Commands::Hash { @@ -20,7 +21,7 @@ namespace vcpkg::Commands::Hash Checks::check_exit(VCPKG_LINE_INFO, end != std::string::npos, "Unexpected output format from command: %s", Strings::utf16_to_utf8(cmd_line)); auto hash = output.substr(start, end - start); - hash.erase(std::remove_if(hash.begin(), hash.end(), isspace), hash.end()); + Util::keep_if(hash, [](char c) {return !isspace(c); }); System::println(hash); } diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 15aab4845..32460b807 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -11,7 +11,7 @@ namespace vcpkg::Commands::Install { - using Dependencies::PackageSpecWithInstallPlan; + using Dependencies::InstallPlanAction; using Dependencies::RequestType; using Dependencies::InstallPlanType; @@ -140,15 +140,15 @@ namespace vcpkg::Commands::Install return SortedVector<std::string>(std::move(installed_files)); } - static void print_plan(const std::vector<PackageSpecWithInstallPlan>& plan) + static void print_plan(const std::vector<InstallPlanAction>& plan) { - std::vector<const PackageSpecWithInstallPlan*> already_installed; - std::vector<const PackageSpecWithInstallPlan*> build_and_install; - std::vector<const PackageSpecWithInstallPlan*> install; + std::vector<const InstallPlanAction*> already_installed; + std::vector<const InstallPlanAction*> build_and_install; + std::vector<const InstallPlanAction*> install; - for (const PackageSpecWithInstallPlan& i : plan) + for (const InstallPlanAction& i : plan) { - switch (i.plan.plan_type) + switch (i.plan_type) { case InstallPlanType::ALREADY_INSTALLED: already_installed.push_back(&i); @@ -164,23 +164,23 @@ namespace vcpkg::Commands::Install } } - auto print_lambda = [](const PackageSpecWithInstallPlan* p) { return to_output_string(p->plan.request_type, p->spec.to_string()); }; + auto print_lambda = [](const InstallPlanAction* p) { return Dependencies::to_output_string(p->request_type, p->spec.to_string()); }; if (!already_installed.empty()) { - std::sort(already_installed.begin(), already_installed.end(), &PackageSpecWithInstallPlan::compare_by_name); + std::sort(already_installed.begin(), already_installed.end(), &InstallPlanAction::compare_by_name); System::println("The following packages are already installed:\n%s", Strings::join("\n", already_installed, print_lambda)); } if (!build_and_install.empty()) { - std::sort(build_and_install.begin(), build_and_install.end(), &PackageSpecWithInstallPlan::compare_by_name); + std::sort(build_and_install.begin(), build_and_install.end(), &InstallPlanAction::compare_by_name); System::println("The following packages will be built and installed:\n%s", Strings::join("\n", build_and_install, print_lambda)); } if (!install.empty()) { - std::sort(install.begin(), install.end(), &PackageSpecWithInstallPlan::compare_by_name); + std::sort(install.begin(), install.end(), &InstallPlanAction::compare_by_name); System::println("The following packages will be installed:\n%s", Strings::join("\n", install, print_lambda)); } } @@ -252,7 +252,7 @@ namespace vcpkg::Commands::Install // create the plan StatusParagraphs status_db = database_load_check(paths); - std::vector<PackageSpecWithInstallPlan> install_plan = Dependencies::create_install_plan(paths, specs, status_db); + std::vector<InstallPlanAction> install_plan = Dependencies::create_install_plan(paths, specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); // log the plan @@ -266,9 +266,9 @@ namespace vcpkg::Commands::Install print_plan(install_plan); - const bool has_non_user_requested_packages = std::find_if(install_plan.cbegin(), install_plan.cend(), [](const PackageSpecWithInstallPlan& package)-> bool + const bool has_non_user_requested_packages = std::find_if(install_plan.cbegin(), install_plan.cend(), [](const InstallPlanAction& package)-> bool { - return package.plan.request_type != RequestType::USER_REQUESTED; + return package.request_type != RequestType::USER_REQUESTED; }) != install_plan.cend(); if (has_non_user_requested_packages) @@ -282,13 +282,13 @@ namespace vcpkg::Commands::Install } // execute the plan - for (const PackageSpecWithInstallPlan& action : install_plan) + for (const InstallPlanAction& action : install_plan) { const std::string display_name = action.spec.to_string(); try { - switch (action.plan.plan_type) + switch (action.plan_type) { case InstallPlanType::ALREADY_INSTALLED: System::println(System::Color::success, "Package %s is already installed", display_name); @@ -296,7 +296,7 @@ namespace vcpkg::Commands::Install case InstallPlanType::BUILD_AND_INSTALL: { System::println("Building package %s... ", display_name); - const Build::BuildResult result = Commands::Build::build_package(action.plan.source_pgh.value_or_exit(VCPKG_LINE_INFO), + const Build::BuildResult result = Commands::Build::build_package(action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO), action.spec, paths, paths.port_dir(action.spec), @@ -317,7 +317,7 @@ namespace vcpkg::Commands::Install } case InstallPlanType::INSTALL: System::println("Installing package %s... ", display_name); - install_package(paths, action.plan.binary_pgh.value_or_exit(VCPKG_LINE_INFO), &status_db); + install_package(paths, action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO), &status_db); System::println(System::Color::success, "Installing package %s... done", display_name); break; case InstallPlanType::UNKNOWN: diff --git a/toolsrc/src/commands_integrate.cpp b/toolsrc/src/commands_integrate.cpp index 8569fdd79..819c29082 100644 --- a/toolsrc/src/commands_integrate.cpp +++ b/toolsrc/src/commands_integrate.cpp @@ -3,6 +3,7 @@ #include "vcpkg_Checks.h" #include "vcpkg_System.h" #include "vcpkg_Files.h" +#include "vcpkg_Util.h" namespace vcpkg::Commands::Integrate { @@ -66,10 +67,10 @@ namespace vcpkg::Commands::Integrate dir_id.erase(1, 1); // Erasing the ":" // NuGet id cannot have invalid characters. We will only use alphanumeric and dot. - dir_id.erase(std::remove_if(dir_id.begin(), dir_id.end(), [](char c) - { - return !isalnum(c) && (c != '.'); - }), dir_id.end()); + Util::keep_if(dir_id, [](char c) + { + return isalnum(c) || (c == '.'); + }); const std::string nuget_id = "vcpkg." + dir_id; return nuget_id; diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index 9ce4adb75..a61435b5d 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -8,7 +8,7 @@ namespace vcpkg::Commands::Remove { - using Dependencies::PackageSpecWithRemovePlan; + using Dependencies::RemovePlanAction; using Dependencies::RemovePlanType; using Dependencies::RequestType; using Update::OutdatedPackage; @@ -101,14 +101,14 @@ namespace vcpkg::Commands::Remove write_update(paths, pkg); } - static void print_plan(const std::vector<PackageSpecWithRemovePlan>& plan) + static void print_plan(const std::vector<RemovePlanAction>& plan) { - std::vector<const PackageSpecWithRemovePlan*> not_installed; - std::vector<const PackageSpecWithRemovePlan*> remove; + std::vector<const RemovePlanAction*> not_installed; + std::vector<const RemovePlanAction*> remove; - for (const PackageSpecWithRemovePlan& i : plan) + for (const RemovePlanAction& i : plan) { - switch (i.plan.plan_type) + switch (i.plan_type) { case RemovePlanType::NOT_INSTALLED: not_installed.push_back(&i); @@ -121,17 +121,17 @@ namespace vcpkg::Commands::Remove } } - auto print_lambda = [](const PackageSpecWithRemovePlan* p) { return to_output_string(p->plan.request_type, p->spec.to_string()); }; + auto print_lambda = [](const RemovePlanAction* p) { return Dependencies::to_output_string(p->request_type, p->spec.to_string()); }; if (!not_installed.empty()) { - std::sort(not_installed.begin(), not_installed.end(), &PackageSpecWithRemovePlan::compare_by_name); + std::sort(not_installed.begin(), not_installed.end(), &RemovePlanAction::compare_by_name); System::println("The following packages are not installed, so not removed:\n%s", Strings::join("\n", not_installed, print_lambda)); } if (!remove.empty()) { - std::sort(remove.begin(), remove.end(), &PackageSpecWithRemovePlan::compare_by_name); + std::sort(remove.begin(), remove.end(), &RemovePlanAction::compare_by_name); System::println("The following packages will be removed:\n%s", Strings::join("\n", remove, print_lambda)); } } @@ -172,14 +172,14 @@ namespace vcpkg::Commands::Remove const bool isRecursive = options.find(OPTION_RECURSE) != options.cend(); const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend(); - const std::vector<PackageSpecWithRemovePlan> remove_plan = Dependencies::create_remove_plan(specs, status_db); + const std::vector<RemovePlanAction> remove_plan = Dependencies::create_remove_plan(specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !remove_plan.empty(), "Remove plan cannot be empty"); print_plan(remove_plan); - const bool has_non_user_requested_packages = std::find_if(remove_plan.cbegin(), remove_plan.cend(), [](const PackageSpecWithRemovePlan& package)-> bool + const bool has_non_user_requested_packages = std::find_if(remove_plan.cbegin(), remove_plan.cend(), [](const RemovePlanAction& package)-> bool { - return package.plan.request_type != RequestType::USER_REQUESTED; + return package.request_type != RequestType::USER_REQUESTED; }) != remove_plan.cend(); if (has_non_user_requested_packages) @@ -198,11 +198,11 @@ namespace vcpkg::Commands::Remove Checks::exit_success(VCPKG_LINE_INFO); } - for (const PackageSpecWithRemovePlan& action : remove_plan) + for (const RemovePlanAction& action : remove_plan) { const std::string display_name = action.spec.to_string(); - switch (action.plan.plan_type) + switch (action.plan_type) { case RemovePlanType::NOT_INSTALLED: System::println(System::Color::success, "Package %s is not installed", display_name); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 3e3f502b5..03e3c2aeb 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -5,10 +5,40 @@ #include "PackageSpec.h" #include "StatusParagraphs.h" #include "vcpkg_Files.h" +#include "vcpkg_Util.h" +#include "vcpkglib.h" #include "Paragraphs.h" namespace vcpkg::Dependencies { + std::vector<PackageSpec> AnyParagraph::dependencies(const Triplet& triplet) const + { + auto to_package_specs = [&](const std::vector<std::string>& dependencies_as_string) + { + return Util::fmap(dependencies_as_string, [&](const std::string s) + { + return PackageSpec::from_name_and_triplet(s, triplet).value_or_exit(VCPKG_LINE_INFO); + }); + }; + + if (auto p = this->status_paragraph.get()) + { + return to_package_specs(p->package.depends); + } + + if (auto p = this->binary_paragraph.get()) + { + return to_package_specs(p->depends); + } + + if (auto p = this->source_paragraph.get()) + { + return to_package_specs(filter_dependencies(p->depends, triplet)); + } + + Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot get dependencies because there was none of: source/binary/status paragraphs"); + } + std::string to_output_string(RequestType request_type, const CStringView s) { switch (request_type) @@ -22,160 +52,156 @@ namespace vcpkg::Dependencies } } - InstallPlanAction::InstallPlanAction() : plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN), binary_pgh(nullopt), source_pgh(nullopt) { } - - InstallPlanAction::InstallPlanAction(const InstallPlanType& plan_type, const RequestType& request_type, Optional<BinaryParagraph> binary_pgh, Optional<SourceParagraph> source_pgh) - : plan_type(std::move(plan_type)), request_type(request_type), binary_pgh(std::move(binary_pgh)), source_pgh(std::move(source_pgh)) { } + InstallPlanAction::InstallPlanAction() : spec() + , any_paragraph() + , plan_type(InstallPlanType::UNKNOWN) + , request_type(RequestType::UNKNOWN) { } - bool PackageSpecWithInstallPlan::compare_by_name(const PackageSpecWithInstallPlan* left, const PackageSpecWithInstallPlan* right) + InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const AnyParagraph& any_paragraph, const RequestType& request_type) : InstallPlanAction() { - return left->spec.name() < right->spec.name(); - } + 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; + } - PackageSpecWithInstallPlan::PackageSpecWithInstallPlan(const PackageSpec& spec, InstallPlanAction&& plan) : spec(spec), plan(std::move(plan)) { } + if (auto p = any_paragraph.binary_paragraph.get()) + { + this->plan_type = InstallPlanType::INSTALL; + this->any_paragraph.binary_paragraph = *p; + return; + } - RemovePlanAction::RemovePlanAction() : plan_type(RemovePlanType::UNKNOWN), request_type(RequestType::UNKNOWN) { } + if (auto p = any_paragraph.source_paragraph.get()) + { + this->plan_type = InstallPlanType::BUILD_AND_INSTALL; + this->any_paragraph.source_paragraph = *p; + return; + } - RemovePlanAction::RemovePlanAction(const RemovePlanType& plan_type, const Dependencies::RequestType& request_type) : plan_type(plan_type), request_type(request_type) { } + this->plan_type = InstallPlanType::UNKNOWN; + } - bool PackageSpecWithRemovePlan::compare_by_name(const PackageSpecWithRemovePlan* left, const PackageSpecWithRemovePlan* right) + bool InstallPlanAction::compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right) { return left->spec.name() < right->spec.name(); } - PackageSpecWithRemovePlan::PackageSpecWithRemovePlan(const PackageSpec& spec, RemovePlanAction&& plan) - : spec(spec), plan(std::move(plan)) { } + RemovePlanAction::RemovePlanAction() : plan_type(RemovePlanType::UNKNOWN) + , request_type(RequestType::UNKNOWN) { } - std::vector<PackageSpecWithInstallPlan> create_install_plan(const VcpkgPaths& paths, const std::vector<PackageSpec>& specs, const StatusParagraphs& status_db) - { - std::unordered_set<PackageSpec> specs_as_set(specs.cbegin(), specs.cend()); + RemovePlanAction::RemovePlanAction(const PackageSpec& spec, const RemovePlanType& plan_type, const RequestType& request_type) + : spec(spec) + , plan_type(plan_type) + , request_type(request_type) { } - std::unordered_map<PackageSpec, InstallPlanAction> was_examined; // Examine = we have checked its immediate (non-recursive) dependencies - Graphs::Graph<PackageSpec> graph; - graph.add_vertices(specs); + bool RemovePlanAction::compare_by_name(const RemovePlanAction* left, const RemovePlanAction* right) + { + return left->spec.name() < right->spec.name(); + } - std::vector<PackageSpec> examine_stack(specs); - while (!examine_stack.empty()) + std::vector<InstallPlanAction> create_install_plan(const VcpkgPaths& paths, const std::vector<PackageSpec>& specs, const StatusParagraphs& status_db) + { + struct InstallAdjacencyProvider final : Graphs::AdjacencyProvider<PackageSpec, InstallPlanAction> { - const PackageSpec spec = examine_stack.back(); - examine_stack.pop_back(); + const VcpkgPaths& paths; + const StatusParagraphs& status_db; + const std::unordered_set<PackageSpec>& specs_as_set; - if (was_examined.find(spec) != was_examined.end()) - { - continue; - } + InstallAdjacencyProvider(const VcpkgPaths& p, const StatusParagraphs& s, const std::unordered_set<PackageSpec>& specs_as_set) : paths(p) + , status_db(s) + , specs_as_set(specs_as_set) {} - auto process_dependencies = [&](const std::vector<std::string>& dependencies_as_string) - { - for (const std::string& dep_as_string : dependencies_as_string) - { - const PackageSpec current_dep = PackageSpec::from_name_and_triplet(dep_as_string, spec.triplet()).value_or_exit(VCPKG_LINE_INFO); - auto it = status_db.find_installed(current_dep); - if (it != status_db.end()) - { - continue; - } - - graph.add_edge(spec, current_dep); - if (was_examined.find(current_dep) == was_examined.end()) - { - examine_stack.push_back(std::move(current_dep)); - } - } - }; - - const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() ? RequestType::USER_REQUESTED : RequestType::AUTO_SELECTED; - auto it = status_db.find_installed(spec); - if (it != status_db.end()) + std::vector<PackageSpec> adjacency_list(const InstallPlanAction& p) const override { - was_examined.emplace(spec, InstallPlanAction{ InstallPlanType::ALREADY_INSTALLED, request_type, nullopt, nullopt }); - continue; + if (p.any_paragraph.status_paragraph.get()) + return std::vector<PackageSpec>{}; + return p.any_paragraph.dependencies(p.spec.triplet()); } - Expected<BinaryParagraph> maybe_bpgh = Paragraphs::try_load_cached_package(paths, spec); - if (BinaryParagraph* bpgh = maybe_bpgh.get()) + InstallPlanAction load_vertex_data(const PackageSpec& spec) const override { - process_dependencies(bpgh->depends); - was_examined.emplace(spec, InstallPlanAction{ InstallPlanType::INSTALL, request_type, std::move(*bpgh), nullopt }); - continue; - } + const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() ? RequestType::USER_REQUESTED : RequestType::AUTO_SELECTED; + auto it = status_db.find_installed(spec); + if (it != status_db.end()) + return InstallPlanAction{ spec, { *it->get(), nullopt, nullopt }, request_type }; - Expected<SourceParagraph> maybe_spgh = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); - if (auto spgh = maybe_spgh.get()) - { - process_dependencies(filter_dependencies(spgh->depends, spec.triplet())); - was_examined.emplace(spec, InstallPlanAction{ InstallPlanType::BUILD_AND_INSTALL, request_type, nullopt, std::move(*spgh) }); - } - else - { - Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot find package %s", spec.name()); + Expected<BinaryParagraph> maybe_bpgh = Paragraphs::try_load_cached_package(paths, spec); + if (auto bpgh = maybe_bpgh.get()) + return InstallPlanAction{ spec, { nullopt, *bpgh, nullopt }, request_type }; + + Expected<SourceParagraph> maybe_spgh = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); + if (auto spgh = maybe_spgh.get()) + return InstallPlanAction{ spec, { nullopt, nullopt, *spgh }, request_type }; + + return InstallPlanAction{ spec , { nullopt, nullopt, nullopt }, request_type }; } - } + }; - std::vector<PackageSpecWithInstallPlan> ret; + const std::unordered_set<PackageSpec> specs_as_set(specs.cbegin(), specs.cend()); + std::vector<InstallPlanAction> toposort = Graphs::topological_sort(specs, InstallAdjacencyProvider{ paths, status_db, specs_as_set }); + Util::keep_if(toposort, [](const InstallPlanAction& p) + { + return !(p.request_type == RequestType::AUTO_SELECTED && p.plan_type == InstallPlanType::ALREADY_INSTALLED); + }); - const std::vector<PackageSpec> pkgs = graph.find_topological_sort(); - for (const PackageSpec& pkg : pkgs) - { - ret.push_back(PackageSpecWithInstallPlan(pkg, std::move(was_examined[pkg]))); - } - return ret; + return toposort; } - std::vector<PackageSpecWithRemovePlan> create_remove_plan(const std::vector<PackageSpec>& specs, const StatusParagraphs& status_db) + std::vector<RemovePlanAction> create_remove_plan(const std::vector<PackageSpec>& specs, const StatusParagraphs& status_db) { - std::unordered_set<PackageSpec> specs_as_set(specs.cbegin(), specs.cend()); - - std::unordered_map<PackageSpec, RemovePlanAction> was_examined; // Examine = we have checked its immediate (non-recursive) dependencies - Graphs::Graph<PackageSpec> graph; - graph.add_vertices(specs); - - std::vector<PackageSpec> examine_stack(specs); - while (!examine_stack.empty()) + struct RemoveAdjacencyProvider final : Graphs::AdjacencyProvider<PackageSpec, RemovePlanAction> { - const PackageSpec spec = examine_stack.back(); - examine_stack.pop_back(); - - if (was_examined.find(spec) != was_examined.end()) - { - continue; - } + const StatusParagraphs& status_db; + const std::vector<StatusParagraph*>& installed_ports; + const std::unordered_set<PackageSpec>& specs_as_set; - const StatusParagraphs::const_iterator it = status_db.find(spec); - if (it == status_db.end() || (*it)->state == InstallState::NOT_INSTALLED) - { - was_examined.emplace(spec, RemovePlanAction(RemovePlanType::NOT_INSTALLED, RequestType::USER_REQUESTED)); - continue; - } + RemoveAdjacencyProvider(const StatusParagraphs& status_db, const std::vector<StatusParagraph*>& installed_ports, const std::unordered_set<PackageSpec>& specs_as_set) + : status_db(status_db) + , installed_ports(installed_ports) + , specs_as_set(specs_as_set) { } - for (const std::unique_ptr<StatusParagraph>& an_installed_package : status_db) + std::vector<PackageSpec> adjacency_list(const RemovePlanAction& p) const override { - if (an_installed_package->want != Want::INSTALL) - continue; - if (an_installed_package->package.spec.triplet() != spec.triplet()) - continue; + if (p.plan_type == RemovePlanType::NOT_INSTALLED) + { + return {}; + } - const std::vector<std::string>& deps = an_installed_package->package.depends; - if (std::find(deps.begin(), deps.end(), spec.name()) == deps.end()) + const PackageSpec& spec = p.spec; + std::vector<PackageSpec> dependents; + for (const StatusParagraph* an_installed_package : installed_ports) { - continue; + if (an_installed_package->package.spec.triplet() != spec.triplet()) + continue; + + const std::vector<std::string>& deps = an_installed_package->package.depends; + if (std::find(deps.begin(), deps.end(), spec.name()) == deps.end()) + continue; + + dependents.push_back(an_installed_package->package.spec); } - graph.add_edge(spec, an_installed_package.get()->package.spec); - examine_stack.push_back(an_installed_package.get()->package.spec); + return dependents; } - const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() ? RequestType::USER_REQUESTED : RequestType::AUTO_SELECTED; - was_examined.emplace(spec, RemovePlanAction(RemovePlanType::REMOVE, request_type)); - } - - std::vector<PackageSpecWithRemovePlan> ret; + RemovePlanAction load_vertex_data(const PackageSpec& spec) const override + { + const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end() ? RequestType::USER_REQUESTED : RequestType::AUTO_SELECTED; + const StatusParagraphs::const_iterator it = status_db.find_installed(spec); + if (it == status_db.end()) + { + return RemovePlanAction{ spec, RemovePlanType::NOT_INSTALLED, request_type }; + } + return RemovePlanAction{ spec, RemovePlanType::REMOVE, request_type }; + } + }; - const std::vector<PackageSpec> pkgs = graph.find_topological_sort(); - for (const PackageSpec& pkg : pkgs) - { - ret.push_back(PackageSpecWithRemovePlan(pkg, std::move(was_examined[pkg]))); - } - return ret; + const std::vector<StatusParagraph*>& installed_ports = get_installed_ports(status_db); + const std::unordered_set<PackageSpec> specs_as_set(specs.cbegin(), specs.cend()); + return Graphs::topological_sort(specs, RemoveAdjacencyProvider{ status_db, installed_ports, specs_as_set }); } } diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 26dc6388b..3d9895436 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include "vcpkg_Strings.h" +#include "vcpkg_Util.h" namespace vcpkg::Strings::details { @@ -98,10 +99,10 @@ namespace vcpkg::Strings trim(&s); } - strings->erase(std::remove_if(strings->begin(), strings->end(), [](const std::string& s)-> bool - { - return s == ""; - }), strings->end()); + Util::keep_if(*strings, [](const std::string& s)-> bool + { + return s != ""; + }); } std::vector<std::string> split(const std::string& s, const std::string& delimiter) diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index cc70b86b0..6cfc741e1 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -5,6 +5,7 @@ #include "metrics.h" #include "vcpkg_Util.h" #include "vcpkg_Strings.h" +#include "vcpkg_Util.h" namespace vcpkg { @@ -200,12 +201,10 @@ namespace vcpkg upgrade_to_slash_terminated_sorted_format(fs, &installed_files_of_current_pgh, listfile_path); // Remove the directories - installed_files_of_current_pgh.erase( - std::remove_if(installed_files_of_current_pgh.begin(), installed_files_of_current_pgh.end(), [](const std::string& file) -> bool - { - return file.back() == '/'; - } - ), installed_files_of_current_pgh.end()); + Util::keep_if(installed_files_of_current_pgh, [](const std::string& file) -> bool + { + return file.back() != '/'; + }); StatusParagraphAndAssociatedFiles pgh_and_files = { *pgh, SortedVector<std::string>(std::move(installed_files_of_current_pgh)) }; installed_files.push_back(std::move(pgh_and_files)); |
