mirror of
https://github.com/microsoft/vcpkg.git
synced 2024-12-31 05:03:22 +08:00
[vcpkg] Fix feature packages for non-default triplets. Reduce duplication between normal installs and feature installs.
This commit is contained in:
parent
c7de717cbc
commit
27be8b5c74
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -7,12 +7,12 @@
|
||||
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());
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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::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);
|
||||
|
||||
const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version),
|
||||
Build::to_allow_downloads(!no_downloads)};
|
||||
|
||||
std::vector<AnyAction> action_plan;
|
||||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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<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");
|
||||
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);
|
||||
|
||||
const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version),
|
||||
Build::to_allow_downloads(!no_downloads)};
|
||||
action_plan = Util::fmap(
|
||||
install_plan, [](InstallPlanAction& install_action) { return AnyAction(std::move(install_action)); });
|
||||
}
|
||||
|
||||
std::vector<const RemovePlanAction*> remove_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");
|
||||
|
||||
std::vector<const InstallPlanAction*> rebuilt_plans;
|
||||
std::vector<const InstallPlanAction*> new_plans;
|
||||
// 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);
|
||||
|
||||
// removal will happen before install
|
||||
for (auto&& action : action_plan)
|
||||
print_plan(action_plan, is_recursive);
|
||||
|
||||
if (dryRun)
|
||||
{
|
||||
Checks::exit_success(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
// execute the plan
|
||||
if (g_feature_packages)
|
||||
{
|
||||
for (const 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);
|
||||
@ -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<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)
|
||||
else
|
||||
{
|
||||
System::println("Additional packages (*) will be installed to complete this operation.");
|
||||
}
|
||||
|
||||
if (dryRun)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user