Exemple #1
0
/** Warns the user about unresolved dependencies and installs them if they choose to do so. 
 * Returns: outcome: ABORT in case the user chose to abort because of an issue
 *                   SUCCESS otherwise
 *          wml_change: indicates if new wml content was installed
 */
addon_op_result do_resolve_addon_dependencies(display& disp, addons_client& client, const addons_list& addons, const addon_info& addon)
{
	addon_op_result result;
	result.outcome = SUCCESS;
	result.wml_changed = false;

	boost::scoped_ptr<cursor::setter> cursor_setter(new cursor::setter(cursor::WAIT));

	// TODO: We don't currently check for the need to upgrade. I'll probably
	// work on that when implementing dependency tiers later.

	const std::set<std::string>& deps = addon.resolve_dependencies(addons);

	std::vector<std::string> missing_deps;
	std::vector<std::string> broken_deps;

	BOOST_FOREACH(const std::string& dep, deps) {
		if(!is_addon_installed(dep)) {
			if(addons.find(dep) != addons.end()) {
				missing_deps.push_back(dep);
			} else {
				broken_deps.push_back(dep);
			}
		}
	}

	cursor_setter.reset();

	if(!broken_deps.empty()) {
		std::string broken_deps_report;

		broken_deps_report = _n(
			"The selected add-on has the following dependency, which is not currently installed or available from the server. Do you wish to continue?",
			"The selected add-on has the following dependencies, which are not currently installed or available from the server. Do you wish to continue?",
			broken_deps.size());
		broken_deps_report += "\n";

		BOOST_FOREACH(const std::string& broken_dep_id, broken_deps) {
			broken_deps_report += "\n    " + utils::unicode_bullet + " " + make_addon_title(broken_dep_id);
		}
Exemple #2
0
addons_client::install_result addons_client::do_resolve_addon_dependencies(const addons_list& addons, const addon_info& addon)
{
	install_result result;
	result.outcome = install_outcome::success;
	result.wml_changed = false;

	auto cursor_setter = std::make_unique<cursor::setter>(cursor::WAIT);

	// TODO: We don't currently check for the need to upgrade. I'll probably
	// work on that when implementing dependency tiers later.

	const std::set<std::string>& deps = addon.resolve_dependencies(addons);

	std::vector<std::string> missing_deps;
	std::vector<std::string> broken_deps;

	for(const std::string& dep : deps) {
		try {
			addon_tracking_info info = get_addon_tracking_info(addons.at(dep));

			// ADDON_NONE means not installed.
			if(info.state == ADDON_NONE) {
				missing_deps.push_back(dep);
			} else if(info.state == ADDON_INSTALLED_UPGRADABLE) {
				// Tight now, we don't need to distinguish the lists of missing
				// and outdated addons, so just add them to missing.
				missing_deps.push_back(dep);
			}
		} catch(const std::out_of_range&) {
			// Dependency wasn't found on server, check locally directly.
			if(!is_addon_installed(dep)) {
				broken_deps.push_back(dep);
			}
		}
	}

	cursor_setter.reset();

	if(!broken_deps.empty()) {
		std::string broken_deps_report;

		broken_deps_report = _n(
			"The selected add-on has the following dependency, which is not currently installed or available from the server. Do you wish to continue?",
			"The selected add-on has the following dependencies, which are not currently installed or available from the server. Do you wish to continue?",
			broken_deps.size());
		broken_deps_report += "\n";

		for(const std::string& broken_dep_id : broken_deps) {
			broken_deps_report += "\n    " + font::unicode_bullet + " " + make_addon_title(broken_dep_id);
		}

		if(gui2::show_message(_("Broken Dependencies"), broken_deps_report, gui2::dialogs::message::yes_no_buttons) != gui2::retval::OK) {
			result.outcome = install_outcome::abort;
			return result; // canceled by user
		}
	}

	if(missing_deps.empty()) {
		// No dependencies to install, carry on.
		return result;
	}

	{
		addons_list options;
		for(const std::string& dep : missing_deps) {
			options[dep] = addons.at(dep);
		}

		gui2::dialogs::install_dependencies dlg(options);
		bool cont = dlg.show();
		if(!cont) {
			return result; // the user has chosen to continue without installing anything.
		}
	}

	//
	// Install dependencies now.
	//

	std::vector<std::string> failed_titles;

	for(const std::string& dep : missing_deps) {
		const addon_info& missing_addon = addons.at(dep);

		if(!try_fetch_addon(missing_addon)) {
			failed_titles.push_back(missing_addon.title);
		} else {
			result.wml_changed = true;
		}
	}

	if(!failed_titles.empty()) {
		const std::string& failed_deps_report = _n(
			"The following dependency could not be installed. Do you still wish to continue?",
			"The following dependencies could not be installed. Do you still wish to continue?",
			failed_titles.size()) + std::string("\n\n") + utils::bullet_list(failed_titles);

		result.outcome = gui2::show_message(_("Dependencies Installation Failed"), failed_deps_report, gui2::dialogs::message::yes_no_buttons) == gui2::retval::OK ? install_outcome::success : install_outcome::abort; // If the user cancels, return abort. Otherwise, return success, since the user chose to ignore the failure.
		return result;
	}

	return result;
}