[vcpkg] Fix feature packages for non-default triplets. Reduce duplication between normal installs and feature installs.
MODIFY
include/VcpkgPaths.h
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;

MODIFY
include/vcpkg_Dependencies.h
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<InstallPlanAction> install_plan;
Optional<RemovePlanAction> 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<PackageSpec, SourceControlFile>& ports;
- explicit MapPortFile(const std::unordered_map<PackageSpec, SourceControlFile>& map);
- const SourceControlFile& get_control_file(const PackageSpec& spec) const override;
+ const std::unordered_map<std::string, SourceControlFile>& ports;
+ explicit MapPortFile(const std::unordered_map<std::string, SourceControlFile>& map);
+ const SourceControlFile& get_control_file(const std::string& spec) const override;
};
struct PathsPortFile : PortFileProvider
{
const VcpkgPaths& ports;
- mutable std::unordered_map<PackageSpec, SourceControlFile> cache;
+ mutable std::unordered_map<std::string, SourceControlFile> 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<PackageSpec>& specs,
const StatusParagraphs& status_db);
- std::vector<AnyAction> create_feature_install_plan(const std::unordered_map<PackageSpec, SourceControlFile>& map,
+ std::vector<AnyAction> create_feature_install_plan(const std::unordered_map<std::string, SourceControlFile>& map,
const std::vector<FeatureSpec>& specs,
const StatusParagraphs& status_db);
}

MODIFY
include/vcpkg_Util.h
include/vcpkg_Util.h
namespace vcpkg::Util
{
template<class Cont, class Func>
- using FmapOut = decltype(std::declval<Func>()(std::declval<Cont>()[0]));
+ using FmapOut = decltype(std::declval<Func>()(*begin(std::declval<Cont>())));
template<class Cont, class Func, class Out = FmapOut<Cont, Func>>
- std::vector<Out> fmap(const Cont& xs, Func&& f)
+ std::vector<Out> fmap(Cont&& xs, Func&& f)
{
- using O = decltype(f(xs[0]));
+ using O = decltype(f(*begin(xs)));
std::vector<O> ret;
ret.reserve(xs.size());

MODIFY
src/VcpkgPaths.cpp
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
{

MODIFY
src/commands_install.cpp
src/commands_install.cpp
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::string>(std::move(installed_files));
}
- static void print_plan(const std::map<InstallPlanType, std::vector<const InstallPlanAction*>>& group_by_plan_type)
- {
- static constexpr std::array<InstallPlanType, 3> 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<const InstallPlanAction*> 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<const InstallPlanAction*> rebuilt_plans,
- const std::vector<const InstallPlanAction*> new_plans)
+ static void print_plan(const std::vector<AnyAction>& action_plan, bool is_recursive)
+ {
+ std::vector<const RemovePlanAction*> remove_plans;
+ std::vector<const InstallPlanAction*> rebuilt_plans;
+ std::vector<const InstallPlanAction*> only_install_plans;
+ std::vector<const InstallPlanAction*> new_plans;
+
+ 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<PackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_package_spec(arg, default_triplet, example);
+ const std::vector<FullPackageSpec> 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<std::string> 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);
- if (g_feature_packages)
- {
- const std::vector<FullPackageSpec> full_specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_full_package_spec(arg, default_triplet, example);
- });
-
- std::unordered_map<PackageSpec, SourceControlFile> 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<Dependencies::AnyAction> 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)};
- std::vector<const RemovePlanAction*> remove_plans;
-
- std::vector<const InstallPlanAction*> rebuilt_plans;
- std::vector<const InstallPlanAction*> new_plans;
+ std::vector<AnyAction> action_plan;
- // 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())
+ if (g_feature_packages)
{
- rebuilt_plans.emplace_back(install_action);
- }
- else
+ std::unordered_map<std::string, SourceControlFile> scf_map;
+ auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports);
+ for (auto&& port : all_ports.paragraphs)
{
- new_plans.emplace_back(install_action);
+ scf_map[port->core_paragraph->name] = std::move(*port);
}
+ action_plan = create_feature_install_plan(scf_map, FullPackageSpec::to_feature_specs(specs), status_db);
}
- else if (auto remove_action = action.remove_plan.get())
+ else
{
- remove_plans.emplace_back(remove_action);
- }
+ Dependencies::PathsPortFile paths_port_file(paths);
+ auto install_plan = Dependencies::create_install_plan(
+ paths_port_file, Util::fmap(specs, [](auto&& spec) { return spec.package_spec; }), status_db);
+
+ action_plan = Util::fmap(
+ install_plan, [](InstallPlanAction& install_action) { return AnyAction(std::move(install_action)); });
}
- print_plan(rebuilt_plans, 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");
+
+ // 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(action_plan, is_recursive);
- if (remove_plans.size() > 0 && !isRecursive)
+ if (dryRun)
{
- 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);
+ Checks::exit_success(VCPKG_LINE_INFO);
}
// execute the plan
- for (const Dependencies::AnyAction& any_action : action_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,52 +552,20 @@ namespace vcpkg::Commands::Install
}
}
}
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- Dependencies::PathsPortFile paths_port_file(paths);
- std::vector<InstallPlanAction> 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<InstallPlanType, std::vector<const InstallPlanAction*>> 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)
+ for (const auto& action : action_plan)
{
- const BuildResult result = perform_install_plan_action(paths, action, install_plan_options, status_db);
+ 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(action.spec));
+ System::println(Build::create_user_troubleshooting_message(iaction.spec));
Checks::exit_fail(VCPKG_LINE_INFO);
}
}
+ }
Checks::exit_success(VCPKG_LINE_INFO);
}

MODIFY
src/test_install_plan.cpp
src/test_install_plan.cpp
@@ -12,7 +12,7 @@ namespace UnitTest1
{
struct PackageSpecMap
{
- std::unordered_map<PackageSpec, SourceControlFile> map;
+ std::unordered_map<std::string, SourceControlFile> 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)

MODIFY
src/vcpkg_Dependencies.cpp
src/vcpkg_Dependencies.cpp
@@ -63,24 +63,51 @@ namespace vcpkg::Dependencies
struct ClusterGraph
{
- explicit ClusterGraph(std::unordered_map<PackageSpec, Cluster>&& graph) : m_graph(std::move(graph)) {}
+ explicit ClusterGraph(std::unordered_map<std::string, const SourceControlFile*>&& 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<PackageSpec, Cluster> m_graph;
+ std::unordered_map<std::string, const SourceControlFile*> m_ports;
};
std::vector<PackageSpec> 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<PackageSpec, SourceControlFile>& map) : ports(map) {}
+ MapPortFile::MapPortFile(const std::unordered_map<std::string, SourceControlFile>& 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<PackageSpec, SourceControlFile>::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<PackageSpec, SourceControlFile>& map,
+ static ClusterGraph create_feature_install_graph(const std::unordered_map<std::string, SourceControlFile>& map,
const StatusParagraphs& status_db)
{
- std::unordered_map<PackageSpec, Cluster> 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<std::string, const SourceControlFile*> 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<AnyAction> create_feature_install_plan(const std::unordered_map<PackageSpec, SourceControlFile>& map,
+ std::vector<AnyAction> create_feature_install_plan(const std::unordered_map<std::string, SourceControlFile>& map,
const std::vector<FeatureSpec>& 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;

[vcpkg] Fix feature packages for non-default triplets. Reduce duplication between normal installs and feature installs.