Ejemplo n.º 1
0
        /// <summary>
        /// This function returns a changeset based on the selections of the user.
        /// Currently returns null if a conflict is detected.
        /// </summary>
        /// <param name="registry"></param>
        /// <param name="changeSet"></param>
        /// <param name="installer">A module installer for the current KSP install</param>
        /// <param name="version">The version of the current KSP install</param>
        public async Task<IEnumerable<KeyValuePair<GUIMod, GUIModChangeType>>> ComputeChangeSetFromModList(
            Registry registry, HashSet<KeyValuePair<GUIMod, GUIModChangeType>> changeSet, ModuleInstaller installer,
            KSPVersion version)
        {
            var modules_to_install = new HashSet<CkanModule>();
            var modules_to_remove = new HashSet<Module>();
            var options = new RelationshipResolverOptions
            {
                without_toomanyprovides_kraken = false,
                with_recommends = false
            };

            foreach (var change in changeSet)
            {
                switch (change.Value)
                {
                    case GUIModChangeType.None:
                        break;
                    case GUIModChangeType.Install:
                        modules_to_install.Add(change.Key.ToCkanModule());
                        break;
                    case GUIModChangeType.Remove:
                        modules_to_remove.Add(change.Key);
                        break;
                    case GUIModChangeType.Update:
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
            var installed_modules =
                registry.InstalledModules.Select(imod => imod.Module).ToDictionary(mod => mod.identifier, mod => mod);


            bool handled_all_to_many_provides = false;
            while (!handled_all_to_many_provides)
            {
                //Can't await in catch clause - doesn't seem to work in mono. Hence this flag
                TooManyModsProvideKraken kraken;
                try
                {
                    new RelationshipResolver(modules_to_install.ToList(), options, registry, version);
                    handled_all_to_many_provides = true;
                    continue;
                }
                catch (TooManyModsProvideKraken k)
                {
                    kraken = k;
                }
                catch (ModuleNotFoundKraken k)
                {
                    //We shouldn't need this. However the relationship provider will throw TMPs with incompatible mods.
                    user.RaiseError("Module {0} has not been found. This may be because it is not compatible " +
                                    "with the currently installed version of KSP", k.module);
                    return null;
                }
                //Shouldn't get here unless there is a kraken.
                var mod = await too_many_provides(kraken);
                if (mod != null)
                {
                    modules_to_install.Add(mod);
                }
                else
                {
                    //TODO Is could be a new type of Kraken.
                    throw kraken;
                }
            }


            foreach (var dependency in modules_to_remove.
                Select(mod => installer.FindReverseDependencies(mod.identifier)).
                SelectMany(reverse_dependencies => reverse_dependencies))
            {
                //TODO This would be a good place to have a event that alters the row's graphics to show it will be removed
                Module module_by_version = registry.GetModuleByVersion(installed_modules[dependency].identifier,
                    installed_modules[dependency].version) ?? registry.InstalledModule(dependency).Module;
                changeSet.Add(
                    new KeyValuePair<GUIMod, GUIModChangeType>(
                        new GUIMod(module_by_version, registry, version), GUIModChangeType.Remove));
            }
            //May throw InconsistentKraken
            var resolver = new RelationshipResolver(options, registry, version);
            resolver.RemoveModsFromInstalledList(
                changeSet.Where(change => change.Value.Equals(GUIModChangeType.Remove)).Select(m => m.Key.ToModule()));
            resolver.AddModulesToInstall(modules_to_install.ToList());
            changeSet.UnionWith(
                resolver.ModList()
                    .Select(
                        mod =>
                            new KeyValuePair<GUIMod, GUIModChangeType>(new GUIMod(mod, registry, version),
                                GUIModChangeType.Install)));


            return changeSet;
        }
Ejemplo n.º 2
0
        // this functions computes a changeset from the user's choices in the GUI
        private List <KeyValuePair <CkanModule, GUIModChangeType> > ComputeChangeSetFromModList()
        // this probably needs to be refactored
        {
            var changeset = new HashSet <KeyValuePair <CkanModule, GUIModChangeType> >();

            // these are the lists
            var modulesToInstall = new HashSet <string>();
            var modulesToRemove  = new HashSet <string>();

            Registry registry = RegistryManager.Instance(KSPManager.CurrentInstance).registry;

            foreach (DataGridViewRow row in ModList.Rows)
            {
                var mod = (CkanModule)row.Tag;
                if (mod == null)
                {
                    continue;
                }

                bool isInstalled        = registry.IsInstalled(mod.identifier);
                var  isInstalledCell    = row.Cells[0] as DataGridViewCheckBoxCell;
                var  isInstalledChecked = (bool)isInstalledCell.Value;

                if (!isInstalled && isInstalledChecked)
                {
                    modulesToInstall.Add(mod.identifier);
                }
                else if (isInstalled && !isInstalledChecked)
                {
                    modulesToRemove.Add(mod.identifier);
                }
            }

            RelationshipResolverOptions options = RelationshipResolver.DefaultOpts();

            options.with_recommends = false;
            options.without_toomanyprovides_kraken = true;
            options.without_enforce_consistency    = true;

            RelationshipResolver resolver = null;

            try
            {
                resolver = new RelationshipResolver(modulesToInstall.ToList(), options, registry);
            }
            catch (Exception e)
            {
                return(null);
            }

            foreach (CkanModule mod in resolver.ModList())
            {
                changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Install));
            }

            ModuleInstaller installer = ModuleInstaller.Instance;

            foreach (string moduleName in modulesToRemove)
            {
                var reverseDependencies = installer.FindReverseDependencies(moduleName);
                foreach (string reverseDependency in reverseDependencies)
                {
                    CkanModule mod = registry.LatestAvailable(reverseDependency);
                    changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Remove));
                }
            }

            foreach (DataGridViewRow row in ModList.Rows)
            {
                var mod = (CkanModule)row.Tag;
                if (mod == null)
                {
                    continue;
                }

                bool             isInstalled         = registry.IsInstalled(mod.identifier);
                var              isInstalledCell     = row.Cells[0] as DataGridViewCheckBoxCell;
                var              isInstalledChecked  = (bool)isInstalledCell.Value;
                DataGridViewCell shouldBeUpdatedCell = row.Cells[1];
                bool             shouldBeUpdated     = false;
                if (shouldBeUpdatedCell is DataGridViewCheckBoxCell && shouldBeUpdatedCell.Value != null)
                {
                    shouldBeUpdated = (bool)shouldBeUpdatedCell.Value;
                }

                if (isInstalled && !isInstalledChecked)
                {
                    changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Remove));
                }
                else if (isInstalled && isInstalledChecked &&
                         mod.version.IsGreaterThan(registry.InstalledVersion(mod.identifier)) && shouldBeUpdated)
                {
                    changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Update));
                }
            }

            return(changeset.ToList());
        }
Ejemplo n.º 3
0
        /// <summary>
        /// This function returns a changeset based on the selections of the user.
        /// Currently returns null if a conflict is detected.
        /// </summary>
        /// <param name="registry"></param>
        /// <param name="current_instance"></param>
        public List <KeyValuePair <CkanModule, GUIModChangeType> > ComputeChangeSetFromModList(Registry registry, KSP current_instance)
        {
            var changeset        = new HashSet <KeyValuePair <CkanModule, GUIModChangeType> >();
            var modulesToInstall = new HashSet <string>();
            var modulesToRemove  = new HashSet <string>();

            foreach (var mod in Modules.Where(mod => mod.IsInstallable()))
            {
                if (mod.IsInstalled)
                {
                    if (!mod.IsInstallChecked)
                    {
                        modulesToRemove.Add(mod.Identifier);
                        changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod.ToCkanModule(),
                                                                                      GUIModChangeType.Remove));
                    }
                    else if (mod.IsInstallChecked && mod.HasUpdate && mod.IsUpgradeChecked)
                    {
                        changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod.ToCkanModule(),
                                                                                      GUIModChangeType.Update));
                    }
                }
                else if (mod.IsInstallChecked)
                {
                    modulesToInstall.Add(mod.Identifier);
                }
            }

            RelationshipResolverOptions options = RelationshipResolver.DefaultOpts();

            options.with_recommends = false;
            options.without_toomanyprovides_kraken = true;
            options.without_enforce_consistency    = true;

            RelationshipResolver resolver;

            try
            {
                resolver = new RelationshipResolver(modulesToInstall.ToList(), options, registry);
            }
            catch (Exception)
            {
                //TODO FIX this so the UI reacts.
                return(null);
            }

            changeset.UnionWith(
                resolver.ModList()
                .Select(mod => new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Install)));


            ModuleInstaller installer = ModuleInstaller.GetInstance(current_instance, GUI.user);

            foreach (var reverseDependencies in modulesToRemove.Select(mod => installer.FindReverseDependencies(mod)))
            {
                //TODO This would be a good place to have a event that alters the row's graphics to show it will be removed
                var modules = reverseDependencies.Select(rDep => registry.LatestAvailable(rDep));
                changeset.UnionWith(
                    modules.Select(mod => new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Remove)));
            }

            return(changeset.ToList());
        }