Example #1
0
 private bool installable(ModuleInstaller installer, CkanModule module, IRegistryQuerier registry)
 {
     return(module.IsCompatibleKSP(Main.Instance.CurrentInstance.VersionCriteria()) &&
            installer.CanInstall(
                RelationshipResolver.DependsOnlyOpts(),
                new List <CkanModule>()
     {
         module
     },
                registry));
 }
Example #2
0
        private void reinstallToolStripMenuItem_Click(object sender, EventArgs e)
        {
            GUIMod module = ModInfoTabControl.SelectedModule;

            if (module == null || !module.IsCKAN)
            {
                return;
            }

            YesNoDialog reinstallDialog  = new YesNoDialog();
            string      confirmationText = $"Do you want to reinstall {module.Name}?";

            if (reinstallDialog.ShowYesNoDialog(confirmationText) == DialogResult.No)
            {
                return;
            }

            IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry;

            // Build the list of changes, first the mod to remove:
            List <ModChange> toReinstall = new List <ModChange>()
            {
                new ModChange(module, GUIModChangeType.Remove, null)
            };
            // Then everything we need to re-install:
            var revdep = registry.FindReverseDependencies(new List <string>()
            {
                module.Identifier
            });
            var goners = revdep.Union(
                registry.FindRemovableAutoInstalled(
                    registry.InstalledModules.Where(im => !revdep.Contains(im.identifier))
                    ).Select(im => im.Module.identifier)
                );

            foreach (string id in goners)
            {
                toReinstall.Add(new ModChange(
                                    mainModList.full_list_of_mod_rows[id]?.Tag as GUIMod,
                                    GUIModChangeType.Install,
                                    null
                                    ));
            }
            // Hand off to centralized [un]installer code
            installWorker.RunWorkerAsync(
                new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                    toReinstall,
                    RelationshipResolver.DependsOnlyOpts()
                    )
                );
        }
Example #3
0
        private void Changeset_OnConfirmChanges()
        {
            menuStrip1.Enabled = false;

            //Using the changeset passed in can cause issues with versions.
            // An example is Mechjeb for FAR at 25/06/2015 with a 1.0.2 install.
            // TODO Work out why this is.
            installWorker.RunWorkerAsync(
                new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                    mainModList.ComputeUserChangeSet(RegistryManager.Instance(Main.Instance.CurrentInstance).registry).ToList(),
                    RelationshipResolver.DependsOnlyOpts()
                    )
                );
        }
Example #4
0
        private void minimizeNotifyIcon_BalloonTipClicked(object sender, EventArgs e)
        {
            // Unminimize
            OpenWindow();

            // Check all the upgrade checkboxes
            ManageMods.MarkAllUpdates();

            // Install
            installWorker.RunWorkerAsync(
                new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                    ManageMods.mainModList.ComputeUserChangeSet(RegistryManager.Instance(Main.Instance.CurrentInstance).registry).ToList(),
                    RelationshipResolver.DependsOnlyOpts()
                    )
                );
        }
Example #5
0
 /// <summary>
 /// Initiate the GUI installer flow for one specific module
 /// </summary>
 /// <param name="registry">Reference to the registry</param>
 /// <param name="module">Module to install</param>
 public async void InstallModuleDriver(IRegistryQuerier registry, CkanModule module)
 {
     try
     {
         var             userChangeSet = new List <ModChange>();
         InstalledModule installed     = registry.InstalledModule(module.identifier);
         if (installed != null)
         {
             // Already installed, remove it first
             userChangeSet.Add(new ModChange(
                                   new GUIMod(installed.Module, registry, CurrentInstance.VersionCriteria()),
                                   GUIModChangeType.Remove,
                                   null
                                   ));
         }
         // Install the selected mod
         userChangeSet.Add(new ModChange(
                               new GUIMod(module, registry, CurrentInstance.VersionCriteria()),
                               GUIModChangeType.Install,
                               null
                               ));
         if (userChangeSet.Count > 0)
         {
             // Resolve the provides relationships in the dependencies
             installWorker.RunWorkerAsync(
                 new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                     userChangeSet,
                     RelationshipResolver.DependsOnlyOpts()
                     )
                 );
         }
     }
     catch
     {
         // If we failed, do the clean-up normally done by PostInstallMods.
         HideWaitDialog(false);
         menuStrip1.Enabled = true;
     }
     finally
     {
         changeSet = null;
     }
 }
Example #6
0
 /// <summary>
 /// Tries to get every mod in the Dictionary, which can be installed
 /// It also transforms the Recommender list to a string
 /// </summary>
 /// <param name="mods">Map from recommendations to lists of recommenders</param>
 /// <param name="registry">Registry of current game instance</param>
 /// <param name="versionCriteria">Versions compatible with current instance</param>
 /// <param name="toInstall">Modules planned to be installed</param>
 /// <returns>Map from installable recommendations to string describing recommenders</returns>
 private Dictionary <CkanModule, string> GetShowableMods(
     Dictionary <CkanModule, List <string> > mods,
     IRegistryQuerier registry,
     KspVersionCriteria versionCriteria,
     HashSet <CkanModule> toInstall
     )
 {
     return(mods.Where(kvp => CanInstall(
                           registry, versionCriteria,
                           RelationshipResolver.DependsOnlyOpts(),
                           toInstall.ToList().Concat(new List <CkanModule>()
     {
         kvp.Key
     }).ToList()
                           )).ToDictionary(
                kvp => kvp.Key,
                kvp => string.Join(", ", kvp.Value.ToArray())
                ));
 }
Example #7
0
        private void ConfirmChangesButton_Click(object sender, EventArgs e)
        {
            if (changeSet == null)
            {
                return;
            }

            menuStrip1.Enabled = false;
            RetryCurrentActionButton.Visible = false;

            //Using the changeset passed in can cause issues with versions.
            // An example is Mechjeb for FAR at 25/06/2015 with a 1.0.2 install.
            // TODO Work out why this is.
            installWorker.RunWorkerAsync(
                new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                    mainModList.ComputeUserChangeSet().ToList(),
                    RelationshipResolver.DependsOnlyOpts()
                    )
                );
        }
Example #8
0
        private void AuditRecommendations(IRegistryQuerier registry, KspVersionCriteria versionCriteria)
        {
            var recommended = new Dictionary <CkanModule, List <string> >();
            var suggested   = new Dictionary <CkanModule, List <string> >();
            var toInstall   = new HashSet <CkanModule>();

            // Find recommendations and suggestions
            foreach (var mod in registry.InstalledModules.Select(im => im.Module))
            {
                AddMod(mod.recommends, recommended, mod.identifier, registry, toInstall);
                AddMod(mod.suggests, suggested, mod.identifier, registry, toInstall);
            }

            if (!recommended.Any() && !suggested.Any())
            {
                GUI.user.RaiseError("No recommendations or suggestions found.");
                return;
            }

            // Prompt user to choose
            installCanceled = false;
            ShowSelection(recommended, toInstall);
            ShowSelection(suggested, toInstall, true);
            tabController.HideTab("ChooseRecommendedModsTabPage");

            // Install
            if (!installCanceled && toInstall.Any())
            {
                installWorker.RunWorkerAsync(
                    new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                        toInstall.Select(mod => new ModChange(
                                             new GUIMod(mod, registry, versionCriteria),
                                             GUIModChangeType.Install,
                                             null
                                             )).ToList(),
                        RelationshipResolver.DependsOnlyOpts()
                        )
                    );
            }
        }
Example #9
0
        private void AuditRecommendations(IRegistryQuerier registry, GameVersionCriteria versionCriteria)
        {
            var installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser);

            if (installer.FindRecommendations(
                    registry.InstalledModules.Select(im => im.Module).ToHashSet(),
                    new HashSet <CkanModule>(),
                    registry as Registry,
                    out Dictionary <CkanModule, Tuple <bool, List <string> > > recommendations,
                    out Dictionary <CkanModule, List <string> > suggestions,
                    out Dictionary <CkanModule, HashSet <string> > supporters
                    ))
            {
                tabController.ShowTab("ChooseRecommendedModsTabPage", 3);
                ChooseRecommendedMods.LoadRecommendations(
                    registry, new HashSet <CkanModule>(), new HashSet <CkanModule>(),
                    versionCriteria, Manager.Cache,
                    recommendations, suggestions, supporters);
                var result = ChooseRecommendedMods.Wait();
                tabController.HideTab("ChooseRecommendedModsTabPage");
                if (result != null && result.Any())
                {
                    installWorker.RunWorkerAsync(
                        new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                            result.Select(mod => new ModChange(
                                              mod,
                                              GUIModChangeType.Install,
                                              null
                                              )).ToList(),
                            RelationshipResolver.DependsOnlyOpts()
                            )
                        );
                }
            }
            else
            {
                currentUser.RaiseError(Properties.Resources.MainRecommendationsNoneFound);
            }
        }
Example #10
0
        private void Changeset_OnConfirmChanges()
        {
            menuStrip1.Enabled = false;

            // Using the changeset passed in can cause issues with versions.
            // An example is Mechjeb for FAR at 25/06/2015 with a 1.0.2 install.
            // TODO Work out why this is.
            try
            {
                installWorker.RunWorkerAsync(
                    new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                        ManageMods.mainModList
                        .ComputeUserChangeSet(RegistryManager.Instance(Main.Instance.CurrentInstance).registry)
                        .ToList(),
                        RelationshipResolver.DependsOnlyOpts()
                        )
                    );
            }
            catch (InvalidOperationException)
            {
                // Thrown if it's already busy, can happen if the user fouble-clicks the button. Ignore it.
                // More thread-safe than checking installWorker.IsBusy beforehand.
            }
        }
Example #11
0
        private IEnumerable <ListViewItem> getRecSugRows(
            IEnumerable <CkanModule> sourceModules,
            IRegistryQuerier registry,
            HashSet <CkanModule> toInstall
            )
        {
            Dictionary <CkanModule, List <string> > dependersIndex = getDependersIndex(sourceModules, registry, toInstall);

            foreach (CkanModule mod in sourceModules.Where(m => m.recommends != null))
            {
                foreach (RelationshipDescriptor rel in mod.recommends)
                {
                    List <CkanModule> providers = rel.LatestAvailableWithProvides(
                        registry,
                        CurrentInstance.VersionCriteria()
                        );
                    foreach (CkanModule provider in providers)
                    {
                        List <string> dependers;
                        if (!registry.IsInstalled(provider.identifier) &&
                            !toInstall.Any(m => m.identifier == provider.identifier) &&
                            dependersIndex.TryGetValue(provider, out dependers) &&
                            CanInstall(registry, CurrentInstance.VersionCriteria(),
                                       RelationshipResolver.DependsOnlyOpts(),
                                       toInstall.ToList().Concat(new List <CkanModule>()
                        {
                            provider
                        }).ToList()))
                        {
                            dependersIndex.Remove(provider);
                            yield return(getRecSugItem(
                                             provider,
                                             string.Join(", ", dependers),
                                             RecommendationsGroup,
                                             providers.Count <= 1 || provider.identifier == (rel as ModuleRelationshipDescriptor)?.name
                                             ));
                        }
                    }
                }
            }
            foreach (CkanModule mod in sourceModules.Where(m => m.suggests != null))
            {
                foreach (RelationshipDescriptor rel in mod.suggests)
                {
                    List <CkanModule> providers = rel.LatestAvailableWithProvides(
                        registry,
                        CurrentInstance.VersionCriteria()
                        );
                    foreach (CkanModule provider in providers)
                    {
                        List <string> dependers;
                        if (!registry.IsInstalled(provider.identifier) &&
                            !toInstall.Any(m => m.identifier == provider.identifier) &&
                            dependersIndex.TryGetValue(provider, out dependers) &&
                            CanInstall(registry, CurrentInstance.VersionCriteria(),
                                       RelationshipResolver.DependsOnlyOpts(),
                                       toInstall.ToList().Concat(new List <CkanModule>()
                        {
                            provider
                        }).ToList()))
                        {
                            dependersIndex.Remove(provider);
                            yield return(getRecSugItem(
                                             provider,
                                             string.Join(", ", dependers),
                                             SuggestionsGroup,
                                             false
                                             ));
                        }
                    }
                }
            }
        }
Example #12
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 game instance</param>
        /// <param name="version">The version of the current game instance</param>
        public IEnumerable <ModChange> ComputeChangeSetFromModList(
            IRegistryQuerier registry, HashSet <ModChange> changeSet, ModuleInstaller installer,
            GameVersionCriteria version)
        {
            var modules_to_install = new HashSet <CkanModule>();
            var modules_to_remove  = new HashSet <CkanModule>();

            foreach (var change in changeSet)
            {
                switch (change.ChangeType)
                {
                case GUIModChangeType.None:
                    break;

                case GUIModChangeType.Update:
                case GUIModChangeType.Install:
                    modules_to_install.Add(change.Mod);
                    break;

                case GUIModChangeType.Remove:
                    modules_to_remove.Add(change.Mod);
                    break;

                case GUIModChangeType.Replace:
                    ModuleReplacement repl = registry.GetReplacement(change.Mod, version);
                    if (repl != null)
                    {
                        modules_to_remove.Add(repl.ToReplace);
                        modules_to_install.Add(repl.ReplaceWith);
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            var installed_modules =
                registry.InstalledModules.Select(imod => imod.Module).ToDictionary(mod => mod.identifier, mod => mod);

            foreach (var dependent in registry.FindReverseDependencies(
                         modules_to_remove
                         .Select(mod => mod.identifier)
                         .Except(modules_to_install.Select(m => m.identifier)),
                         modules_to_install
                         ))
            {
                //TODO This would be a good place to have an event that alters the row's graphics to show it will be removed
                CkanModule depMod;
                if (installed_modules.TryGetValue(dependent, out depMod))
                {
                    CkanModule module_by_version = registry.GetModuleByVersion(depMod.identifier,
                                                                               depMod.version)
                                                   ?? registry.InstalledModule(dependent).Module;
                    changeSet.Add(new ModChange(module_by_version, GUIModChangeType.Remove, null));
                    modules_to_remove.Add(module_by_version);
                }
            }
            foreach (var im in registry.FindRemovableAutoInstalled(
                         registry.InstalledModules.Where(im => !modules_to_remove.Any(m => m.identifier == im.identifier) || modules_to_install.Any(m => m.identifier == im.identifier))
                         ))
            {
                changeSet.Add(new ModChange(im.Module, GUIModChangeType.Remove, new SelectionReason.NoLongerUsed()));
                modules_to_remove.Add(im.Module);
            }

            // Get as many dependencies as we can, but leave decisions and prompts for installation time
            RelationshipResolverOptions opts = RelationshipResolver.DependsOnlyOpts();

            opts.without_toomanyprovides_kraken = true;
            opts.without_enforce_consistency    = true;

            var resolver = new RelationshipResolver(
                modules_to_install,
                modules_to_remove,
                opts, registry, version);

            changeSet.UnionWith(
                resolver.ModList()
                .Select(m => new ModChange(m, GUIModChangeType.Install, resolver.ReasonFor(m))));

            return(changeSet);
        }
Example #13
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 <ModChange> > ComputeChangeSetFromModList(
            IRegistryQuerier registry, HashSet <ModChange> changeSet, ModuleInstaller installer,
            KspVersionCriteria version)
        {
            var modules_to_install = new HashSet <CkanModule>();
            var modules_to_remove  = new HashSet <CkanModule>();

            foreach (var change in changeSet)
            {
                switch (change.ChangeType)
                {
                case GUIModChangeType.None:
                    break;

                case GUIModChangeType.Update:
                case GUIModChangeType.Install:
                    //TODO: Fix
                    //This will give us a mod with a wrong version!
                    modules_to_install.Add(change.Mod.ToCkanModule());
                    break;

                case GUIModChangeType.Remove:
                    modules_to_remove.Add(change.Mod);
                    break;

                case GUIModChangeType.Replace:
                    ModuleReplacement repl = registry.GetReplacement(change.Mod.ToModule(), version);
                    if (repl != null)
                    {
                        modules_to_remove.Add(repl.ToReplace);
                        modules_to_install.Add(repl.ReplaceWith);
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            var installed_modules =
                registry.InstalledModules.Select(imod => imod.Module).ToDictionary(mod => mod.identifier, mod => mod);

            foreach (var dependency in registry.FindReverseDependencies(
                         modules_to_remove
                         .Select(mod => mod.identifier)
                         .Except(modules_to_install.Select(m => m.identifier))
                         ))
            {
                //TODO This would be a good place to have a event that alters the row's graphics to show it will be removed
                CkanModule module_by_version = registry.GetModuleByVersion(installed_modules[dependency].identifier,
                                                                           installed_modules[dependency].version) ?? registry.InstalledModule(dependency).Module;
                changeSet.Add(new ModChange(new GUIMod(module_by_version, registry, version), GUIModChangeType.Remove, null));
                modules_to_remove.Add(module_by_version);
            }
            foreach (var im in registry.FindRemovableAutoInstalled(
                         registry.InstalledModules.Where(im => !modules_to_remove.Any(m => m.identifier == im.identifier))
                         ))
            {
                changeSet.Add(new ModChange(new GUIMod(im.Module, registry, version), GUIModChangeType.Remove, new SelectionReason.NoLongerUsed()));
                modules_to_remove.Add(im.Module);
            }

            bool handled_all_too_many_provides = false;

            while (!handled_all_too_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,
                        modules_to_remove,
                        RelationshipResolver.DependsOnlyOpts(),
                        registry, version);
                    handled_all_too_many_provides = true;
                    continue;
                }
                catch (TooManyModsProvideKraken k)
                {
                    kraken = k;
                }
                //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;
                }
            }

            var resolver = new RelationshipResolver(
                modules_to_install,
                modules_to_remove,
                RelationshipResolver.DependsOnlyOpts(), registry, version);

            changeSet.UnionWith(
                resolver.ModList()
                .Select(m => new ModChange(new GUIMod(m, registry, version), GUIModChangeType.Install, resolver.ReasonFor(m))));

            return(changeSet);
        }