#include "pch.h" #include #include #include #include #include #include #include #include #include namespace vcpkg::Commands::Upgrade { using Install::KeepGoing; using Install::to_keep_going; static const std::string OPTION_NO_DRY_RUN = "--no-dry-run"; static const std::string OPTION_KEEP_GOING = "--keep-going"; static const std::array INSTALL_SWITCHES = {{ {OPTION_NO_DRY_RUN, "Actually upgrade"}, {OPTION_KEEP_GOING, "Continue installing packages on failure"}, }}; const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("upgrade --no-dry-run"), 0, SIZE_MAX, {INSTALL_SWITCHES, {}}, nullptr, }; void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const bool no_dry_run = Util::Sets::contains(options.switches, OPTION_NO_DRY_RUN); const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING)); StatusParagraphs status_db = database_load_check(paths); Dependencies::PathsPortFileProvider provider(paths); Dependencies::PackageGraph graph(provider, status_db); // input sanitization const std::vector specs = Util::fmap(args.command_arguments, [&](auto&& arg) { return Input::check_and_get_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text); }); for (auto&& spec : specs) { Input::check_triplet(spec.triplet(), paths); } if (specs.empty()) { // If no packages specified, upgrade all outdated packages. auto outdated_packages = Update::find_outdated_packages(provider, status_db); if (outdated_packages.empty()) { System::println("All installed packages are up-to-date with the local portfiles."); Checks::exit_success(VCPKG_LINE_INFO); } for (auto&& outdated_package : outdated_packages) graph.upgrade(outdated_package.spec); } else { std::vector not_installed; std::vector no_portfile; std::vector to_upgrade; std::vector up_to_date; for (auto&& spec : specs) { auto it = status_db.find_installed(spec); if (it == status_db.end()) { not_installed.push_back(spec); } auto maybe_scf = provider.get_control_file(spec.name()); if (auto p_scf = maybe_scf.get()) { if (it != status_db.end()) { if (p_scf->core_paragraph->version != (*it)->package.version) { to_upgrade.push_back(spec); } else { up_to_date.push_back(spec); } } } else { no_portfile.push_back(spec); } } Util::sort(not_installed); Util::sort(no_portfile); Util::sort(up_to_date); Util::sort(to_upgrade); if (!up_to_date.empty()) { System::println(System::Color::success, "The following packages are up-to-date:"); System::println(Strings::join( "", up_to_date, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); } if (!not_installed.empty()) { System::println(System::Color::error, "The following packages are not installed:"); System::println(Strings::join( "", not_installed, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); } if (!no_portfile.empty()) { System::println(System::Color::error, "The following packages do not have a valid portfile:"); System::println(Strings::join( "", no_portfile, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; })); } Checks::check_exit(VCPKG_LINE_INFO, not_installed.empty() && no_portfile.empty()); if (to_upgrade.empty()) Checks::exit_success(VCPKG_LINE_INFO); for (auto&& spec : to_upgrade) graph.upgrade(spec); } auto plan = graph.serialize(); Checks::check_exit(VCPKG_LINE_INFO, !plan.empty()); const Build::BuildPackageOptions install_plan_options = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, Build::CleanBuildtrees::NO, }; // Set build settings for all install actions for (auto&& action : plan) { if (auto p_install = action.install_action.get()) { p_install->build_options = install_plan_options; } } Dependencies::print_plan(plan, true); if (!no_dry_run) { System::println(System::Color::warning, "If you are sure you want to rebuild the above packages, run this command with the " "--no-dry-run option."); Checks::exit_fail(VCPKG_LINE_INFO); } const Install::InstallSummary summary = Install::perform(plan, keep_going, paths, status_db); System::println("\nTotal elapsed time: %s\n", summary.total_elapsed_time); if (keep_going == KeepGoing::YES) { summary.print(); } Checks::exit_success(VCPKG_LINE_INFO); } }