Exemplo n.º 1
0
        private void _UpdateModContentsTree(CkanModule module, bool force = false)
        {
            ContentsPreviewTree.BackColor = SystemColors.Window;
            ContentsPreviewTree.LineColor = SystemColors.WindowText;

            if (Equals(module, currentModContentsModule) && !force)
            {
                return;
            }
            else
            {
                currentModContentsModule = module;
            }
            if (module.IsMetapackage)
            {
                NotCachedLabel.Text            = Properties.Resources.ModInfoNoDownload;
                ContentsPreviewTree.Enabled    = false;
                ContentsDownloadButton.Enabled = false;
                ContentsOpenButton.Enabled     = false;
                ContentsPreviewTree.Nodes.Clear();
            }
            else
            {
                ContentsPreviewTree.Enabled = true;
                ContentsPreviewTree.Nodes.Clear();
                ContentsPreviewTree.Nodes.Add(module.name);
                if (!Main.Instance.Manager.Cache.IsMaybeCachedZip(module))
                {
                    NotCachedLabel.Text            = Properties.Resources.ModInfoNotCached;
                    ContentsDownloadButton.Enabled = true;
                    ContentsOpenButton.Enabled     = false;
                    ContentsPreviewTree.Enabled    = false;
                }
                else
                {
                    NotCachedLabel.Text            = Properties.Resources.ModInfoCached;
                    ContentsDownloadButton.Enabled = false;
                    ContentsOpenButton.Enabled     = true;
                    ContentsPreviewTree.Enabled    = true;

                    // Get all the data; can put this in bg if slow
                    var contents = ModuleInstaller.GetInstance(
                        manager.CurrentInstance,
                        Main.Instance.Manager.Cache,
                        Main.Instance.currentUser)
                                   .GetModuleContentsList(module)?.ToList();

                    // Update UI; must be in fg
                    if (contents != null)
                    {
                        foreach (string item in contents)
                        {
                            ContentsPreviewTree.Nodes[0].Nodes.Add(
                                item.Replace('/', Path.DirectorySeparatorChar));
                        }
                        ContentsPreviewTree.Nodes[0].ExpandAll();
                    }
                }
            }
        }
Exemplo n.º 2
0
        public void TestSimple()
        {
            var modules = _registry.available_modules
                          .Select((mod) => new GUIMod(mod.Value.Latest(), _registry, _instance.KSP.VersionCriteria()))
                          .ToList();

            // varargs method signature means we must call .ToArray()
            _listGui.Rows.AddRange(_modList.ConstructModList(modules).ToArray());
            // the header row adds one to the count
            Assert.AreEqual(modules.Count + 1, _listGui.Rows.Count);

            // sort by a text column, this is the fuse-lighting
            _listGui.Sort(_listGui.Columns[6], ListSortDirection.Descending);

            // mark the mod for install, after completion we will get an exception
            var otherModule = modules.First((mod) => mod.Identifier.Contains("kOS"));

            otherModule.IsInstallChecked = true;

            Assert.IsTrue(otherModule.IsInstallChecked);
            Assert.IsFalse(otherModule.IsInstalled);

            Assert.DoesNotThrow(() =>
            {
                // perform the install of the "other" module - now we need to sort
                ModuleInstaller.GetInstance(_instance.KSP, _manager.Cache, _manager.User).InstallList(
                    _modList.ComputeUserChangeSet(null).Select(change => change.Mod.ToCkanModule()).ToList(),
                    new RelationshipResolverOptions(),
                    new NetAsyncModulesDownloader(_manager.User, _manager.Cache)
                    );

                // trying to refresh the GUI state will throw a NullReferenceException
                _listGui.Refresh();
            });
        }
Exemplo n.º 3
0
        private void ContentsDownloadButton_Click(object sender, EventArgs e)
        {
            if (ModList.SelectedRows.Count == 0)
            {
                return;
            }

            DataGridViewRow selectedItem = ModList.SelectedRows[0];

            if (selectedItem == null)
            {
                return;
            }

            var module = ((GUIMod)selectedItem.Tag).ToCkanModule();

            if (module == null)
            {
                return;
            }

            ResetProgress();
            ShowWaitDialog(false);
            ModuleInstaller.GetInstance(CurrentInstance, GUI.user).CachedOrDownload(module);
            HideWaitDialog(true);

            UpdateModContentsTree(module);
            RecreateDialogs();
        }
Exemplo n.º 4
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)
        {
            RelationshipResolverOptions install_ops = RelationshipResolver.DefaultOpts();

            install_ops.with_recommends = false;

            try
            {
                var initialChangeSet = new HashSet <ModChange>();
                // Install the selected mod
                initialChangeSet.Add(new ModChange(
                                         new GUIMod(module, registry, CurrentInstance.VersionCriteria()),
                                         GUIModChangeType.Install,
                                         null
                                         ));
                InstalledModule installed = registry.InstalledModule(module.identifier);
                if (installed != null)
                {
                    // Already installed, remove it first
                    initialChangeSet.Add(new ModChange(
                                             new GUIMod(installed.Module, registry, CurrentInstance.VersionCriteria()),
                                             GUIModChangeType.Remove,
                                             null
                                             ));
                }
                List <ModChange> fullChangeSet = new List <ModChange>(
                    await mainModList.ComputeChangeSetFromModList(
                        registry,
                        initialChangeSet,
                        ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, GUI.user),
                        CurrentInstance.VersionCriteria()
                        )
                    );
                if (fullChangeSet != null && fullChangeSet.Count > 0)
                {
                    // Resolve the provides relationships in the dependencies
                    installWorker.RunWorkerAsync(
                        new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                            fullChangeSet,
                            install_ops
                            )
                        );
                }
            }
            catch
            {
                // If we failed, do the clean-up normally done by PostInstallMods.
                HideWaitDialog(false);
                menuStrip1.Enabled = true;
            }
            finally
            {
                changeSet = null;
            }
        }
Exemplo n.º 5
0
        private bool InstallList(ModuleResolution modules, RelationshipResolverOptions options)
        {
            if (toInstall.Any())
            {
                // actual magic happens here, we run the installer with our mod list
                var module_installer = ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user);
                module_installer.onReportModInstalled = OnModInstalled;
                return(WasSuccessful(() => module_installer.InstallList(modules, options)));
            }

            return(true);
        }
Exemplo n.º 6
0
Arquivo: Repo.cs Projeto: starllv/CKAN
        /// <summary>
        /// Resolve differences between installed and available metadata for given ModuleInstaller
        /// </summary>
        /// <param name="metadataChanges">List of modules that changed</param>
        /// <param name="user">Object for user interaction callbacks</param>
        /// <param name="ksp">Game instance</param>
        private static void HandleModuleChanges(List <CkanModule> metadataChanges, IUser user, KSP ksp, NetModuleCache cache, RegistryManager registry_manager)
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < metadataChanges.Count; i++)
            {
                CkanModule module = metadataChanges[i];
                sb.AppendLine(string.Format("- {0} {1}", module.identifier, module.version));
            }

            if (user.RaiseYesNoDialog(string.Format(@"The following mods have had their metadata changed since last update:

{0}
You should reinstall them in order to preserve consistency with the repository.

Do you wish to reinstall now?", sb)))
            {
                ModuleInstaller installer = ModuleInstaller.GetInstance(ksp, cache, new NullUser());
                // New upstream metadata may break the consistency of already installed modules
                // e.g. if user installs modules A and B and then later up A is made to conflict with B
                // This is perfectly normal and shouldn't produce an error, therefore we skip enforcing
                // consistency. However, we will show the user any inconsistencies later on.

                // Use the identifiers so we use the overload that actually resolves relationships
                // Do each changed module one at a time so a failure of one doesn't cause all the others to fail
                foreach (string changedIdentifier in metadataChanges.Select(i => i.identifier))
                {
                    try
                    {
                        HashSet <string> possibleConfigOnlyDirs = null;
                        installer.Upgrade(
                            new[] { changedIdentifier },
                            new NetAsyncModulesDownloader(new NullUser(), cache),
                            ref possibleConfigOnlyDirs,
                            registry_manager,
                            enforceConsistency: false
                            );
                    }
                    // Thrown when a dependency couldn't be satisfied
                    catch (ModuleNotFoundKraken)
                    {
                        log.WarnFormat("Skipping installation of {0} due to relationship error.", changedIdentifier);
                        user.RaiseMessage("Skipping installation of {0} due to relationship error.", changedIdentifier);
                    }
                    // Thrown when a conflicts relationship is violated
                    catch (InconsistentKraken)
                    {
                        log.WarnFormat("Skipping installation of {0} due to relationship error.", changedIdentifier);
                        user.RaiseMessage("Skipping installation of {0} due to relationship error.", changedIdentifier);
                    }
                }
            }
        }
Exemplo n.º 7
0
        private void _UpdateModContentsTree(bool force = false)
        {
            ContentsPreviewTree.BackColor = SystemColors.Window;
            ContentsPreviewTree.LineColor = SystemColors.WindowText;
            GUIMod guiMod = SelectedModule;

            if (!guiMod.IsCKAN)
            {
                return;
            }
            CkanModule module = guiMod.ToCkanModule();

            if (Equals(module, currentModContentsModule) && !force)
            {
                return;
            }
            else
            {
                currentModContentsModule = module;
            }
            if (!guiMod.IsCached)
            {
                NotCachedLabel.Text            = Properties.Resources.ModInfoNotCached;
                ContentsDownloadButton.Enabled = true;
                ContentsOpenButton.Enabled     = false;
                ContentsPreviewTree.Enabled    = false;
            }
            else
            {
                NotCachedLabel.Text            = Properties.Resources.ModInfoCached;
                ContentsDownloadButton.Enabled = false;
                ContentsOpenButton.Enabled     = true;
                ContentsPreviewTree.Enabled    = true;
            }

            ContentsPreviewTree.Nodes.Clear();
            ContentsPreviewTree.Nodes.Add(module.name);

            IEnumerable <string> contents = ModuleInstaller.GetInstance(manager.CurrentInstance, Main.Instance.Manager.Cache, Main.Instance.currentUser).GetModuleContentsList(module);

            if (contents == null)
            {
                return;
            }

            foreach (string item in contents)
            {
                ContentsPreviewTree.Nodes[0].Nodes.Add(item.Replace('/', Path.DirectorySeparatorChar));
            }

            ContentsPreviewTree.Nodes[0].ExpandAll();
        }
Exemplo n.º 8
0
        private bool InstallList(HashSet <string> toInstall, RelationshipResolverOptions options, IDownloader downloader)
        {
            if (toInstall.Any())
            {
                // actual magic happens here, we run the installer with our mod list
                var module_installer = ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user);
                module_installer.onReportModInstalled = OnModInstalled;
                return(WasSuccessful(
                           () => module_installer.InstallList(toInstall.ToList(), options, downloader)));
            }

            return(true);
        }
Exemplo n.º 9
0
        private async Task UpdateChangeSetAndConflicts(IRegistryQuerier registry)
        {
            IEnumerable <ModChange>     full_change_set = null;
            Dictionary <GUIMod, string> new_conflicts   = null;

            bool too_many_provides_thrown = false;
            var  user_change_set          = mainModList.ComputeUserChangeSet();

            try
            {
                var module_installer = ModuleInstaller.GetInstance(CurrentInstance, GUI.user);
                full_change_set = await mainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer, CurrentInstance.VersionCriteria());
            }
            catch (InconsistentKraken k)
            {
                // Need to be recomputed due to ComputeChangeSetFromModList possibly changing it with too many provides handling.
                AddStatusMessage(k.ShortDescription);
                user_change_set = mainModList.ComputeUserChangeSet();
                new_conflicts   = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.VersionCriteria());
                full_change_set = null;
            }
            catch (TooManyModsProvideKraken)
            {
                // Can be thrown by ComputeChangeSetFromModList if the user cancels out of it.
                // We can just rerun it as the ModInfoTabControl has been removed.
                too_many_provides_thrown = true;
            }
            catch (DependencyNotSatisfiedKraken k)
            {
                GUI.user.RaiseError(
                    "{0} depends on {1}, which is not compatible with the currently installed version of KSP",
                    k.parent,
                    k.module
                    );

                // Uncheck the box
                MarkModForInstall(k.parent.identifier, true);
            }

            if (too_many_provides_thrown)
            {
                await UpdateChangeSetAndConflicts(registry);

                new_conflicts   = Conflicts;
                full_change_set = ChangeSet;
            }

            last_mod_to_have_install_toggled.Clear();
            Conflicts = new_conflicts;
            ChangeSet = full_change_set;
        }
Exemplo n.º 10
0
        private void _UpdateModContentsTree(bool force = false)
        {
            GUIMod guiMod = SelectedModule;

            if (!guiMod.IsCKAN)
            {
                return;
            }
            CkanModule module = guiMod.ToCkanModule();

            if (Equals(module, current_mod_contents_module) && !force)
            {
                return;
            }
            else
            {
                current_mod_contents_module = module;
            }
            if (!guiMod.IsCached)
            {
                NotCachedLabel.Text            = Properties.Resources.MainModInfoNotCached;
                ContentsDownloadButton.Enabled = true;
                ContentsOpenButton.Enabled     = false;
                ContentsPreviewTree.Enabled    = false;
            }
            else
            {
                NotCachedLabel.Text            = Properties.Resources.MainModInfoCached;
                ContentsDownloadButton.Enabled = false;
                ContentsOpenButton.Enabled     = true;
                ContentsPreviewTree.Enabled    = true;
            }

            ContentsPreviewTree.Nodes.Clear();
            ContentsPreviewTree.Nodes.Add(module.name);

            IEnumerable <string> contents = ModuleInstaller.GetInstance(manager.CurrentInstance, Main.Instance.Manager.Cache, GUI.user).GetModuleContentsList(module);

            if (contents == null)
            {
                return;
            }

            foreach (string item in contents)
            {
                ContentsPreviewTree.Nodes[0].Nodes.Add(item);
            }

            ContentsPreviewTree.Nodes[0].ExpandAll();
        }
Exemplo n.º 11
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)
        {
            RelationshipResolverOptions install_ops = RelationshipResolver.DefaultOpts();

            install_ops.with_recommends = false;

            try
            {
                // Resolve the provides relationships in the dependencies
                List <ModChange> fullChangeSet = new List <ModChange>(
                    await mainModList.ComputeChangeSetFromModList(
                        registry,
                        new HashSet <ModChange>()
                {
                    new ModChange(
                        new GUIMod(
                            module,
                            registry,
                            CurrentInstance.VersionCriteria()
                            ),
                        GUIModChangeType.Install,
                        null
                        )
                },
                        ModuleInstaller.GetInstance(CurrentInstance, GUI.user),
                        CurrentInstance.VersionCriteria()
                        )
                    );
                if (fullChangeSet != null && fullChangeSet.Count > 0)
                {
                    installWorker.RunWorkerAsync(
                        new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                            fullChangeSet,
                            install_ops
                            )
                        );
                }
            }
            catch
            {
                // If we failed, do the clean-up normally done by PostInstallMods.
                HideWaitDialog(false);
                menuStrip1.Enabled = true;
            }
            finally
            {
                changeSet = null;
            }
        }
Exemplo n.º 12
0
        private bool allowInstall(CkanModule module)
        {
            GameInstance     currentInstance = Main.Instance.Manager.CurrentInstance;
            IRegistryQuerier registry        = RegistryManager.Instance(currentInstance).registry;
            var installer = ModuleInstaller.GetInstance(
                currentInstance,
                Main.Instance.Manager.Cache,
                Main.Instance.currentUser);

            return(installable(installer, module, registry) ||
                   Main.Instance.YesNoDialog(
                       string.Format(Properties.Resources.AllModVersionsInstallPrompt, module.ToString()),
                       Properties.Resources.AllModVersionsInstallYes,
                       Properties.Resources.AllModVersionsInstallNo));
        }
Exemplo n.º 13
0
        private void _UpdateModContentsTree(bool force = false)
        {
            GUIMod guiMod = GetSelectedModule();

            if (!guiMod.IsCKAN)
            {
                return;
            }
            CfanModule module = guiMod.ToCkanModule();

            if (Equals(module, current_mod_contents_module) && !force)
            {
                return;
            }
            else
            {
                current_mod_contents_module = module;
            }
            if (!guiMod.IsCached)
            {
                NotCachedLabel.Text            = "This mod is not in the cache, click 'Download' to preview contents";
                ContentsDownloadButton.Enabled = true;
                ContentsPreviewTree.Enabled    = false;
            }
            else
            {
                NotCachedLabel.Text            = "Module is cached, preview available";
                ContentsDownloadButton.Enabled = false;
                ContentsPreviewTree.Enabled    = true;
            }

            ContentsPreviewTree.Nodes.Clear();
            ContentsPreviewTree.Nodes.Add(module.title);

            IEnumerable <string> contents = ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user).GetModuleContentsList(module);

            if (contents == null)
            {
                return;
            }

            foreach (string item in contents)
            {
                ContentsPreviewTree.Nodes[0].Nodes.Add(item);
            }

            ContentsPreviewTree.Nodes[0].ExpandAll();
        }
Exemplo n.º 14
0
        public void Up()
        {
            _instance        = new DisposableKSP();
            _registryManager = RegistryManager.Instance(_instance.KSP);
            _registry        = Registry.Empty();
            _config          = new FakeConfiguration(_instance.KSP, _instance.KSP.Name);
            _manager         = new GameInstanceManager(
                new NullUser(),
                _config
                );

            // this module contains a ksp_version of "any" which repros our issue
            _anyVersionModule = TestData.DogeCoinFlag_101_module();

            // install it and set it as pre-installed
            _manager.Cache.Store(TestData.DogeCoinFlag_101_module(), TestData.DogeCoinFlagZip());
            _registry.RegisterModule(_anyVersionModule, new string[] { }, _instance.KSP, false);
            _registry.AddAvailable(_anyVersionModule);

            HashSet <string> possibleConfigOnlyDirs = null;

            ModuleInstaller.GetInstance(_instance.KSP, _manager.Cache, _manager.User).InstallList(
                new List <CkanModule> {
                { _anyVersionModule }
            },
                new RelationshipResolverOptions(),
                _registryManager,
                ref possibleConfigOnlyDirs,
                new NetAsyncModulesDownloader(_manager.User, _manager.Cache)
                );

            // this module is not for "any" version, to provide another to sort against
            _registry.AddAvailable(TestData.kOS_014_module());

            // test object
            _modList = new ModList(null);
            _listGui = new DataGridView();

            // todo: refactor the column header code to allow mocking of the GUI without creating columns
            _listGui.Columns.Add(new DataGridViewCheckBoxColumn());
            _listGui.Columns.Add(new DataGridViewCheckBoxColumn());
            _listGui.Columns.Add(new DataGridViewCheckBoxColumn());
            _listGui.Columns.Add(new DataGridViewCheckBoxColumn());
            for (int i = 0; i < 10; i++)
            {
                _listGui.Columns.Add(i.ToString(), "Column" + i);
            }
        }
Exemplo n.º 15
0
        private void ContentsDownloadButton_Click(object sender, EventArgs e)
        {
            var module = GetSelectedModule();

            if (module == null)
            {
                return;
            }
            ResetProgress();
            ShowWaitDialog(false);
            ModuleInstaller.GetInstance(CurrentInstance, GUI.user).CachedOrDownload(module);
            HideWaitDialog(true);

            UpdateModContentsTree(module);
            RecreateDialogs();
        }
Exemplo n.º 16
0
        public async Task TooManyProvidesCallsHandlers()
        {
            using (var tidy = new DisposableKSP())
            {
                var manager       = new KSPManager(new NullUser());
                var registry      = Registry.Empty();
                var generator     = new RandomModuleGenerator(new Random(0451));
                var provide_ident = "provide";
                var ksp_version   = tidy.KSP.Version();
                var mod           = generator.GeneratorRandomModule(depends: new List <RelationshipDescriptor>
                {
                    new ModuleRelationshipDescriptor {
                        name = provide_ident
                    }
                }, ksp_version: ksp_version);
                var moda = generator.GeneratorRandomModule(provides: new List <string> {
                    provide_ident
                }
                                                           , ksp_version: ksp_version);
                var modb = generator.GeneratorRandomModule(provides: new List <string> {
                    provide_ident
                }
                                                           , ksp_version: ksp_version);
                var choice_of_provide = modb;
                registry.AddAvailable(mod);
                registry.AddAvailable(moda);
                registry.AddAvailable(modb);
                var installer     = ModuleInstaller.GetInstance(tidy.KSP, manager.Cache, null);
                var main_mod_list = new MainModList(null, async kraken => await Task.FromResult(choice_of_provide));
                var a             = new HashSet <ModChange>
                {
                    new ModChange(new GUIMod(mod, registry, new KspVersionCriteria(ksp_version)), GUIModChangeType.Install, null)
                };

                var mod_list = await main_mod_list.ComputeChangeSetFromModList(registry, a, installer, new KspVersionCriteria (ksp_version));

                CollectionAssert.AreEquivalent(
                    new[] {
                    new ModChange(new GUIMod(mod, registry, new KspVersionCriteria(ksp_version)), GUIModChangeType.Install, null),
                    new ModChange(new GUIMod(modb, registry, new KspVersionCriteria(ksp_version)), GUIModChangeType.Install, null)
                }, mod_list);

                manager.Dispose();
            }
        }
Exemplo n.º 17
0
        private void ImportModules()
        {
            // Prompt the user to select one or more ZIP files
            OpenFileDialog dlg = new OpenFileDialog()
            {
                Title            = "Import Mods",
                AddExtension     = true,
                CheckFileExists  = true,
                CheckPathExists  = true,
                InitialDirectory = FindDownloadsPath(CurrentInstance),
                DefaultExt       = "zip",
                Filter           = "Mods (*.zip)|*.zip",
                Multiselect      = true
            };

            if (dlg.ShowDialog() == DialogResult.OK &&
                dlg.FileNames.Length > 0)
            {
                // Set up GUI to respond to IUser calls...
                GUIUser.DisplayYesNo old_YesNoDialog = currentUser.displayYesNo;
                currentUser.displayYesNo = YesNoDialog;
                tabController.RenameTab("WaitTabPage", "Status log");
                tabController.ShowTab("WaitTabPage");
                tabController.SetTabLock(true);

                try
                {
                    ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser).ImportFiles(
                        GetFiles(dlg.FileNames),
                        currentUser,
                        (CkanModule mod) => MarkModForInstall(mod.identifier, false)
                        );
                }
                finally
                {
                    // Put GUI back the way we found it
                    currentUser.displayYesNo = old_YesNoDialog;
                    tabController.SetTabLock(false);
                    tabController.HideTab("WaitTabPage");
                }
            }
        }
Exemplo n.º 18
0
        private void _UpdateModContentsTree()
        {
            var module = (CkanModule)ModInfoTabControl.Tag;

            if (module == current_mod_contents_module)
            {
                return;
            }
            else
            {
                current_mod_contents_module = module;
            }
            if (!manager.CurrentInstance.Cache.IsCachedZip(module.download))
            {
                NotCachedLabel.Text            = "This mod is not in the cache, click 'Download' to preview contents";
                ContentsDownloadButton.Enabled = true;
                ContentsPreviewTree.Enabled    = false;
            }
            else
            {
                NotCachedLabel.Text            = "Module is cached, preview available";
                ContentsDownloadButton.Enabled = false;
                ContentsPreviewTree.Enabled    = true;
            }

            ContentsPreviewTree.Nodes.Clear();
            ContentsPreviewTree.Nodes.Add(module.name);

            IEnumerable <string> contents = ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user).GetModuleContentsList(module);

            if (contents == null)
            {
                return;
            }

            foreach (string item in contents)
            {
                ContentsPreviewTree.Nodes[0].Nodes.Add(item);
            }

            ContentsPreviewTree.Nodes[0].ExpandAll();
        }
Exemplo n.º 19
0
        private void ImportModules()
        {
            // Prompt the user to select one or more ZIP files
            OpenFileDialog dlg = new OpenFileDialog()
            {
                Title            = Properties.Resources.MainImportTitle,
                AddExtension     = true,
                CheckFileExists  = true,
                CheckPathExists  = true,
                InitialDirectory = FindDownloadsPath(CurrentInstance),
                DefaultExt       = "zip",
                Filter           = Properties.Resources.MainImportFilter,
                Multiselect      = true
            };

            if (dlg.ShowDialog() == DialogResult.OK &&
                dlg.FileNames.Length > 0)
            {
                // Show WaitTabPage (status page) and lock it.
                tabController.RenameTab("WaitTabPage", Properties.Resources.MainImportWaitTitle);
                tabController.ShowTab("WaitTabPage");
                tabController.SetTabLock(true);

                try
                {
                    ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser).ImportFiles(
                        GetFiles(dlg.FileNames),
                        currentUser,
                        (CkanModule mod) => ManageMods.MarkModForInstall(mod.identifier, false),
                        RegistryManager.Instance(CurrentInstance).registry
                        );
                }
                finally
                {
                    // Put GUI back the way we found it
                    tabController.SetTabLock(false);
                    tabController.HideTab("WaitTabPage");
                }
            }
        }
Exemplo n.º 20
0
        private async Task UpdateChangeSetAndConflicts(IRegistryQuerier registry)
        {
            IEnumerable <ModChange>     full_change_set = null;
            Dictionary <GUIMod, string> new_conflicts   = null;

            bool too_many_provides_thrown = false;
            var  user_change_set          = mainModList.ComputeUserChangeSet();

            try
            {
                var module_installer = ModuleInstaller.GetInstance(CurrentInstance, GUI.user);
                full_change_set =
                    await mainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer,
                                                                  CurrentInstance.VersionCriteria());
            }
            catch (InconsistentKraken)
            {
                //Need to be recomputed due to ComputeChangeSetFromModList possibly changing it with too many provides handling.
                user_change_set = mainModList.ComputeUserChangeSet();
                new_conflicts   = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.VersionCriteria());
                full_change_set = null;
            }
            catch (TooManyModsProvideKraken)
            {
                //Can be thrown by ComputeChangeSetFromModList if the user cancels out of it.
                //We can just rerun it as the ModInfoTabControl has been removed.
                too_many_provides_thrown = true;
            }
            if (too_many_provides_thrown)
            {
                await UpdateChangeSetAndConflicts(registry);

                new_conflicts   = Conflicts;
                full_change_set = ChangeSet;
            }
            last_mod_to_have_install_toggled.Clear();
            Conflicts = new_conflicts;
            ChangeSet = full_change_set;
        }
Exemplo n.º 21
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);
            }
        }
Exemplo n.º 22
0
        private void UpdateChangeSetAndConflicts(Registry registry)
        {
            IEnumerable <KeyValuePair <CkanModule, GUIModChangeType> > full_change_set;
            Dictionary <Module, string> conflicts;

            var user_change_set = mainModList.ComputeUserChangeSet();

            try
            {
                var module_installer = ModuleInstaller.GetInstance(CurrentInstance, GUI.user);
                full_change_set = MainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer,
                                                                          CurrentInstance.Version());
                conflicts = null;
            }
            catch (InconsistentKraken)
            {
                conflicts       = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.Version());
                full_change_set = null;
            }

            Conflicts = conflicts;
            ChangeSet = full_change_set;
        }
Exemplo n.º 23
0
        // this probably needs to be refactored
        private void InstallMods(object sender, DoWorkEventArgs e)
        {
            installCanceled = false;
            ClearLog();

            var opts = (KeyValuePair <ModChanges, RelationshipResolverOptions>)e.Argument;

            IRegistryQuerier registry  = RegistryManager.Instance(manager.CurrentInstance).registry;
            ModuleInstaller  installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, GUI.user);

            // Avoid accumulating multiple event handlers
            installer.onReportModInstalled -= OnModInstalled;
            installer.onReportModInstalled += OnModInstalled;
            // setup progress callback

            // this will be the final list of mods we want to install
            HashSet <CkanModule> toInstall = new HashSet <CkanModule>();
            var toUninstall = new HashSet <string>();
            var toUpgrade   = new HashSet <string>();

            // First compose sets of what the user wants installed, upgraded, and removed.
            foreach (ModChange change in opts.Key)
            {
                switch (change.ChangeType)
                {
                case GUIModChangeType.Remove:
                    toUninstall.Add(change.Mod.Identifier);
                    break;

                case GUIModChangeType.Update:
                    toUpgrade.Add(change.Mod.Identifier);
                    break;

                case GUIModChangeType.Install:
                    toInstall.Add(change.Mod.ToModule());
                    break;

                case GUIModChangeType.Replace:
                    ModuleReplacement repl = registry.GetReplacement(change.Mod.ToModule(), CurrentInstance.VersionCriteria());
                    if (repl != null)
                    {
                        toUninstall.Add(repl.ToReplace.identifier);
                        toInstall.Add(repl.ReplaceWith);
                    }
                    break;
                }
            }

            // Prompt for recommendations and suggestions, if any
            var recRows = getRecSugRows(
                opts.Key.Where(ch => ch.ChangeType == GUIModChangeType.Install)
                .Select(ch => ch.Mod.ToModule()),
                registry, toInstall
                );

            if (recRows.Any())
            {
                ShowRecSugDialog(recRows, toInstall);
            }

            tabController.HideTab("ChooseRecommendedModsTabPage");

            if (installCanceled)
            {
                tabController.ShowTab("ManageModsTabPage");
                e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                return;
            }

            // Now let's make all our changes.
            tabController.RenameTab("WaitTabPage", "Status log");
            ShowWaitDialog();
            tabController.SetTabLock(true);

            IDownloader downloader = new NetAsyncModulesDownloader(GUI.user);

            cancelCallback = () =>
            {
                downloader.CancelDownload();
                installCanceled = true;
            };

            // checks if all actions were successfull
            bool processSuccessful       = false;
            bool resolvedAllProvidedMods = false;

            // uninstall/installs/upgrades until every list is empty
            // if the queue is NOT empty, resolvedAllProvidedMods is set to false until the action is done
            while (!resolvedAllProvidedMods)
            {
                try
                {
                    e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                    if (toUninstall.Count > 0)
                    {
                        processSuccessful = false;
                        if (!installCanceled)
                        {
                            installer.UninstallList(toUninstall, false, toInstall.Select(m => m.identifier));
                            processSuccessful = true;
                        }
                    }
                    if (toUpgrade.Count > 0)
                    {
                        processSuccessful = false;
                        if (!installCanceled)
                        {
                            installer.Upgrade(toUpgrade, downloader);
                            processSuccessful = true;
                        }
                    }
                    if (toInstall.Count > 0)
                    {
                        processSuccessful = false;
                        if (!installCanceled)
                        {
                            installer.InstallList(toInstall, opts.Value, downloader, false);
                            processSuccessful = true;
                        }
                    }
                    e.Result = new KeyValuePair <bool, ModChanges>(processSuccessful, opts.Key);
                    if (installCanceled)
                    {
                        return;
                    }
                    resolvedAllProvidedMods = true;
                }
                catch (TooManyModsProvideKraken k)
                {
                    // Prompt user to choose which mod to use
                    CkanModule chosen = TooManyModsProvideCore(k).Result;
                    // Close the selection prompt
                    Util.Invoke(this, () =>
                    {
                        tabController.ShowTab("WaitTabPage");
                        tabController.HideTab("ChooseProvidedModsTabPage");
                    });
                    if (chosen != null)
                    {
                        // User picked a mod, queue it up for installation
                        toInstall.Add(chosen);
                        // DON'T return so we can loop around and try the above InstallList call again
                    }
                    else
                    {
                        // User cancelled, get out
                        tabController.ShowTab("ManageModsTabPage");
                        e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                        return;
                    }
                }
                catch (DependencyNotSatisfiedKraken ex)
                {
                    GUI.user.RaiseMessage(
                        "{0} requires {1} but it is not listed in the index, or not available for your version of KSP.",
                        ex.parent, ex.module);
                    return;
                }
                catch (ModuleNotFoundKraken ex)
                {
                    GUI.user.RaiseMessage(
                        "Module {0} required but it is not listed in the index, or not available for your version of KSP.",
                        ex.module);
                    return;
                }
                catch (BadMetadataKraken ex)
                {
                    GUI.user.RaiseMessage("Bad metadata detected for module {0}: {1}", ex.module, ex.Message);
                    return;
                }
                catch (FileExistsKraken ex)
                {
                    if (ex.owningModule != null)
                    {
                        GUI.user.RaiseMessage(
                            "\r\nOh no! We tried to overwrite a file owned by another mod!\r\n" +
                            "Please try a `ckan update` and try again.\r\n\r\n" +
                            "If this problem re-occurs, then it maybe a packaging bug.\r\n" +
                            "Please report it at:\r\n\r\n" +
                            "https://github.com/KSP-CKAN/NetKAN/issues/new\r\n\r\n" +
                            "Please including the following information in your report:\r\n\r\n" +
                            "File           : {0}\r\n" +
                            "Installing Mod : {1}\r\n" +
                            "Owning Mod     : {2}\r\n" +
                            "CKAN Version   : {3}\r\n",
                            ex.filename, ex.installingModule, ex.owningModule,
                            Meta.GetVersion()
                            );
                    }
                    else
                    {
                        GUI.user.RaiseMessage(
                            "\r\n\r\nOh no!\r\n\r\n" +
                            "It looks like you're trying to install a mod which is already installed,\r\n" +
                            "or which conflicts with another mod which is already installed.\r\n\r\n" +
                            "As a safety feature, the CKAN will *never* overwrite or alter a file\r\n" +
                            "that it did not install itself.\r\n\r\n" +
                            "If you wish to install {0} via the CKAN,\r\n" +
                            "then please manually uninstall the mod which owns:\r\n\r\n" +
                            "{1}\r\n\r\n" + "and try again.\r\n",
                            ex.installingModule, ex.filename
                            );
                    }

                    GUI.user.RaiseMessage("Your GameData has been returned to its original state.\r\n");
                    return;
                }
                catch (InconsistentKraken ex)
                {
                    // The prettiest Kraken formats itself for us.
                    GUI.user.RaiseMessage(ex.InconsistenciesPretty);
                    return;
                }
                catch (CancelledActionKraken)
                {
                    return;
                }
                catch (MissingCertificateKraken kraken)
                {
                    // Another very pretty kraken.
                    GUI.user.RaiseMessage(kraken.ToString());
                    return;
                }
                catch (DownloadThrottledKraken kraken)
                {
                    string msg = kraken.ToString();
                    GUI.user.RaiseMessage(msg);
                    if (YesNoDialog($"{msg}\r\n\r\nOpen settings now?", "Open Settings", "No"))
                    {
                        // Launch the URL describing this host's throttling practices, if any
                        if (kraken.infoUrl != null)
                        {
                            Process.Start(new ProcessStartInfo()
                            {
                                UseShellExecute = true,
                                FileName        = kraken.infoUrl.ToString()
                            });
                        }
                        // Now pretend they clicked the menu option for the settings
                        Enabled = false;
                        settingsDialog.ShowDialog();
                        Enabled = true;
                    }
                    return;
                }
                catch (ModuleDownloadErrorsKraken kraken)
                {
                    GUI.user.RaiseMessage(kraken.ToString());
                    GUI.user.RaiseError(kraken.ToString());
                    return;
                }
                catch (DirectoryNotFoundKraken kraken)
                {
                    GUI.user.RaiseMessage("\r\n{0}", kraken.Message);
                    return;
                }
                catch (DllNotFoundException)
                {
                    if (GUI.user.RaiseYesNoDialog("libcurl installation not found. Open wiki page for help?"))
                    {
                        Process.Start(new ProcessStartInfo()
                        {
                            UseShellExecute = true,
                            FileName        = "https://github.com/KSP-CKAN/CKAN/wiki/libcurl"
                        });
                    }
                    throw;
                }
            }
        }
Exemplo n.º 24
0
        private bool InstallList(HashSet <string> toInstall, RelationshipResolverOptions options,
                                 NetAsyncDownloader downloader)
        {
            if (toInstall.Any())
            {
                // actual magic happens here, we run the installer with our mod list
                ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user).onReportModInstalled = OnModInstalled;
                cancelCallback = downloader.CancelDownload;
                try
                {
                    ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user)
                    .InstallList(toInstall.ToList(), options, downloader);
                }
                catch (ModuleNotFoundKraken ex)
                {
                    GUI.user.RaiseMessage("Module {0} required, but not listed in index, or not available for your version of KSP", ex.module);
                    return(false);
                }
                catch (BadMetadataKraken ex)
                {
                    GUI.user.RaiseMessage("Bad metadata detected for module {0}: {1}", ex.module, ex.Message);
                    return(false);
                }
                catch (FileExistsKraken ex)
                {
                    if (ex.owning_module != null)
                    {
                        GUI.user.RaiseMessage(
                            "\nOh no! We tried to overwrite a file owned by another mod!\n" +
                            "Please try a `ckan update` and try again.\n\n" +
                            "If this problem re-occurs, then it maybe a packaging bug.\n" +
                            "Please report it at:\n\n" +
                            "https://github.com/KSP-CKAN/CKAN-meta/issues/new\n\n" +
                            "Please including the following information in your report:\n\n" +
                            "File           : {0}\n" +
                            "Installing Mod : {1}\n" +
                            "Owning Mod     : {2}\n" +
                            "CKAN Version   : {3}\n",
                            ex.filename, ex.installing_module, ex.owning_module,
                            Meta.Version()
                            );
                    }
                    else
                    {
                        GUI.user.RaiseMessage(
                            "\n\nOh no!\n\n" +
                            "It looks like you're trying to install a mod which is already installed,\n" +
                            "or which conflicts with another mod which is already installed.\n\n" +
                            "As a safety feature, the CKAN will *never* overwrite or alter a file\n" +
                            "that it did not install itself.\n\n" +
                            "If you wish to install {0} via the CKAN,\n" +
                            "then please manually uninstall the mod which owns:\n\n" +
                            "{1}\n\n" + "and try again.\n",
                            ex.installing_module, ex.filename
                            );
                    }

                    GUI.user.RaiseMessage("Your GameData has been returned to its original state.\n");
                    return(false);
                }
                catch (InconsistentKraken ex)
                {
                    // The prettiest Kraken formats itself for us.
                    GUI.user.RaiseMessage(ex.InconsistenciesPretty);
                    return(false);
                }
                catch (CancelledActionKraken)
                {
                    return(false);
                }
                catch (MissingCertificateKraken kraken)
                {
                    // Another very pretty kraken.
                    GUI.user.RaiseMessage(kraken.ToString());
                    return(false);
                }
                catch (DownloadErrorsKraken)
                {
                    // User notified in InstallList
                    return(false);
                }
            }

            return(true);
        }
Exemplo n.º 25
0
        private void InstallMods(object sender, DoWorkEventArgs e) // this probably needs to be refactored
        {
            installCanceled = false;

            ClearLog();

            var opts =
                (KeyValuePair <List <KeyValuePair <CkanModule, GUIModChangeType> >, RelationshipResolverOptions>)e.Argument;

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

            // setup progress callback

            toInstall = new HashSet <string>();
            var toUninstall = new HashSet <string>();
            var toUpgrade   = new HashSet <string>();

            // First compose sets of what the user wants installed, upgraded, and removed.
            foreach (KeyValuePair <CkanModule, GUIModChangeType> change in opts.Key)
            {
                switch (change.Value)
                {
                case GUIModChangeType.Remove:
                    toUninstall.Add(change.Key.identifier);
                    break;

                case GUIModChangeType.Update:
                    toUpgrade.Add(change.Key.identifier);
                    break;

                case GUIModChangeType.Install:
                    toInstall.Add(change.Key.identifier);
                    break;
                }
            }

            // Now work on satisifying dependencies.

            var recommended = new Dictionary <string, List <string> >();
            var suggested   = new Dictionary <string, List <string> >();

            foreach (var change in opts.Key)
            {
                if (change.Value == GUIModChangeType.Install)
                {
                    if (change.Key.recommends != null)
                    {
                        foreach (RelationshipDescriptor mod in change.Key.recommends)
                        {
                            try
                            {
                                // if the mod is available for the current KSP version _and_
                                // the mod is not installed _and_
                                // the mod is not already in the install list
                                if (
                                    RegistryManager.Instance(manager.CurrentInstance)
                                    .registry.LatestAvailable(mod.name, manager.CurrentInstance.Version()) !=
                                    null &&
                                    !RegistryManager.Instance(manager.CurrentInstance)
                                    .registry.IsInstalled(mod.name) &&
                                    !toInstall.Contains(mod.name))
                                {
                                    // add it to the list of recommended mods we display to the user
                                    if (recommended.ContainsKey(mod.name))
                                    {
                                        recommended[mod.name].Add(change.Key.identifier);
                                    }
                                    else
                                    {
                                        recommended.Add(mod.name, new List <string> {
                                            change.Key.identifier
                                        });
                                    }
                                }
                            }
                            // XXX - Don't ignore all krakens! Those things are important!
                            catch (Kraken)
                            {
                            }
                        }
                    }

                    if (change.Key.suggests != null)
                    {
                        foreach (RelationshipDescriptor mod in change.Key.suggests)
                        {
                            try
                            {
                                if (
                                    RegistryManager.Instance(manager.CurrentInstance).registry.LatestAvailable(mod.name, manager.CurrentInstance.Version()) != null &&
                                    !RegistryManager.Instance(manager.CurrentInstance).registry.IsInstalled(mod.name) &&
                                    !toInstall.Contains(mod.name))
                                {
                                    if (suggested.ContainsKey(mod.name))
                                    {
                                        suggested[mod.name].Add(change.Key.identifier);
                                    }
                                    else
                                    {
                                        suggested.Add(mod.name, new List <string> {
                                            change.Key.identifier
                                        });
                                    }
                                }
                            }
                            // XXX - Don't ignore all krakens! Those things are important!
                            catch (Kraken)
                            {
                            }
                        }
                    }
                }
            }

            // If we're going to install something anyway, then don't list it in the
            // recommended list, since they can't de-select it anyway.
            foreach (var item in toInstall)
            {
                recommended.Remove(item);
            }

            // If there are any mods that would be recommended, prompt the user to make
            // selections.
            if (recommended.Any())
            {
                Util.Invoke(this, () => UpdateRecommendedDialog(recommended));

                m_TabController.ShowTab("ChooseRecommendedModsTabPage", 3);
                m_TabController.RenameTab("ChooseRecommendedModsTabPage", "Choose recommended mods");
                m_TabController.SetTabLock(true);

                lock (this)
                {
                    Monitor.Wait(this);
                }

                m_TabController.SetTabLock(false);
            }

            m_TabController.HideTab("ChooseRecommendedModsTabPage");

            // And now on to suggestions. Again, we don't show anything that's scheduled to
            // be installed on our suggest list.
            foreach (var item in toInstall)
            {
                suggested.Remove(item);
            }

            if (suggested.Any())
            {
                Util.Invoke(this, () => UpdateRecommendedDialog(suggested, true));

                m_TabController.ShowTab("ChooseRecommendedModsTabPage", 3);
                m_TabController.RenameTab("ChooseRecommendedModsTabPage", "Choose suggested mods");
                m_TabController.SetTabLock(true);

                lock (this)
                {
                    Monitor.Wait(this);
                }

                m_TabController.SetTabLock(false);
            }

            m_TabController.HideTab("ChooseRecommendedModsTabPage");

            if (installCanceled)
            {
                m_TabController.HideTab("WaitTabPage");
                m_TabController.ShowTab("ManageModsTabPage");
                e.Result = new KeyValuePair <bool, List <KeyValuePair <CkanModule, GUIModChangeType> > >(false, opts.Key);
                return;
            }

            // Now let's make all our changes.

            m_TabController.RenameTab("WaitTabPage", "Installing mods");
            m_TabController.ShowTab("WaitTabPage");
            m_TabController.SetTabLock(true);

            using (var transaction = new CkanTransaction())
            {
                var downloader = new NetAsyncDownloader(GUI.user);
                cancelCallback = () =>
                {
                    downloader.CancelDownload();
                    installCanceled = true;
                };


                SetDescription("Uninstalling selected mods");
                installer.UninstallList(toUninstall);
                if (installCanceled)
                {
                    return;
                }

                SetDescription("Updating selected mods");
                installer.Upgrade(toUpgrade, downloader);


                // TODO: We should be able to resolve all our provisioning conflicts
                // before we start installing anything. CKAN.SanityChecker can be used to
                // pre-check if our changes are going to be consistent.

                bool resolvedAllProvidedMods = false;

                while (!resolvedAllProvidedMods)
                {
                    if (installCanceled)
                    {
                        e.Result = new KeyValuePair <bool, List <KeyValuePair <CkanModule, GUIModChangeType> > >(false,
                                                                                                                 opts.Key);
                        return;
                    }
                    try
                    {
                        var ret = InstallList(toInstall, opts.Value, downloader);
                        if (!ret)
                        {
                            // install failed for some reason, error message is already displayed to the user
                            e.Result = new KeyValuePair <bool, List <KeyValuePair <CkanModule, GUIModChangeType> > >(false,
                                                                                                                     opts.Key);
                            return;
                        }
                        resolvedAllProvidedMods = true;
                    }
                    catch (TooManyModsProvideKraken tooManyProvides)
                    {
                        Util.Invoke(this, () => UpdateProvidedModsDialog(tooManyProvides));

                        m_TabController.ShowTab("ChooseProvidedModsTabPage", 3);
                        m_TabController.SetTabLock(true);

                        lock (this)
                        {
                            Monitor.Wait(this);
                        }

                        m_TabController.SetTabLock(false);

                        m_TabController.HideTab("ChooseProvidedModsTabPage");

                        if (installCanceled)
                        {
                            m_TabController.HideTab("WaitTabPage");
                            m_TabController.ShowTab("ManageModsTabPage");
                            e.Result = new KeyValuePair <bool, List <KeyValuePair <CkanModule, GUIModChangeType> > >(false,
                                                                                                                     opts.Key);
                            return;
                        }

                        m_TabController.ShowTab("WaitTabPage");
                    }
                }
                if (!installCanceled)
                {
                    transaction.Complete();
                }
            }
            e.Result = new KeyValuePair <bool, List <KeyValuePair <CkanModule, GUIModChangeType> > >(true, opts.Key);
        }
Exemplo n.º 26
0
Arquivo: Main.cs Projeto: sibaar/CKAN
        private async void installFromckanToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog open_file_dialog = new OpenFileDialog {
                Filter = Resources.CKANFileFilter
            };

            if (open_file_dialog.ShowDialog() == DialogResult.OK)
            {
                var        path = open_file_dialog.FileName;
                CkanModule module;

                try
                {
                    module = CkanModule.FromFile(path);
                }
                catch (Kraken kraken)
                {
                    currentUser.RaiseError(kraken.InnerException == null
                        ? kraken.Message
                        : $"{kraken.Message}: {kraken.InnerException.Message}");

                    return;
                }
                catch (Exception ex)
                {
                    currentUser.RaiseError(ex.Message);
                    return;
                }

                // We'll need to make some registry changes to do this.
                RegistryManager registry_manager = RegistryManager.Instance(CurrentInstance);

                // Remove this version of the module in the registry, if it exists.
                registry_manager.registry.RemoveAvailable(module);

                // Sneakily add our version in...
                registry_manager.registry.AddAvailable(module);

                menuStrip1.Enabled = false;

                RelationshipResolverOptions install_ops = RelationshipResolver.DefaultOpts();
                install_ops.with_recommends = false;

                try
                {
                    // Resolve the provides relationships in the dependencies
                    List <ModChange> fullChangeSet = new List <ModChange>(
                        await mainModList.ComputeChangeSetFromModList(
                            registry_manager.registry,
                            new HashSet <ModChange>()
                    {
                        new ModChange(
                            new GUIMod(
                                module,
                                registry_manager.registry,
                                CurrentInstance.VersionCriteria()
                                ),
                            GUIModChangeType.Install,
                            null
                            )
                    },
                            ModuleInstaller.GetInstance(CurrentInstance, GUI.user),
                            CurrentInstance.VersionCriteria()
                            )
                        );
                    if (fullChangeSet != null && fullChangeSet.Count > 0)
                    {
                        installWorker.RunWorkerAsync(
                            new KeyValuePair <List <ModChange>, RelationshipResolverOptions>(
                                fullChangeSet,
                                install_ops
                                )
                            );
                        ShowWaitDialog();
                    }
                }
                catch
                {
                    // If we failed, do the clean-up normally done by PostInstallMods.
                    HideWaitDialog(false);
                    menuStrip1.Enabled = true;
                }
                finally
                {
                    changeSet = null;
                }
            }
        }
Exemplo n.º 27
0
        /// <summary>
        /// Updates the supplied registry from the URL given.
        /// This does not *save* the registry. For that, you probably want Repo.Update
        /// </summary>
        internal static void UpdateRegistry(Uri repo, Registry registry, KSP ksp, IUser user, Boolean clear = true)
        {
            log.InfoFormat("Downloading {0}", repo);

            string repo_file = String.Empty;

            try
            {
                repo_file = Net.Download(repo);
            }
            catch (System.Net.WebException)
            {
                user.RaiseMessage("Connection to {0} could not be established.", repo);
                return;
            }

            // Clear our list of known modules.
            var old_available = registry.available_modules;

            if (clear)
            {
                registry.ClearAvailable();
            }

            // Check the filetype.
            FileType type = FileIdentifier.IdentifyFile(repo_file);

            switch (type)
            {
            case FileType.TarGz:
                UpdateRegistryFromTarGz(repo_file, registry);
                break;

            case FileType.Zip:
                UpdateRegistryFromZip(repo_file, registry);
                break;

            default:
                break;
            }

            List <CkanModule> metadataChanges = new List <CkanModule>();

            foreach (var identifierModulePair in old_available)
            {
                var identifier = identifierModulePair.Key;

                if (registry.IsInstalled(identifier))
                {
                    var installedVersion = registry.InstalledVersion(identifier);
                    if (!(registry.available_modules.ContainsKey(identifier)))
                    {
                        log.InfoFormat("UpdateRegistry, module {0}, version {1} not in repository ({2})", identifier, installedVersion, repo);
                        continue;
                    }

                    if (!registry.available_modules[identifier].module_version.ContainsKey(installedVersion))
                    {
                        continue;
                    }

                    // if the mod is installed and the metadata is different we have to reinstall it
                    var metadata = registry.available_modules[identifier].module_version[installedVersion];

                    if (!old_available.ContainsKey(identifier) ||
                        !old_available[identifier].module_version.ContainsKey(installedVersion))
                    {
                        continue;
                    }

                    var oldMetadata = old_available[identifier].module_version[installedVersion];

                    bool same = true;
                    if ((metadata.install == null) != (oldMetadata.install == null) ||
                        (metadata.install != null && metadata.install.Length != oldMetadata.install.Length))
                    {
                        same = false;
                    }
                    else
                    {
                        if (metadata.install != null)
                        {
                            for (int i = 0; i < metadata.install.Length; i++)
                            {
                                if (metadata.install[i].file != oldMetadata.install[i].file)
                                {
                                    same = false;
                                    break;
                                }

                                if (metadata.install[i].install_to != oldMetadata.install[i].install_to)
                                {
                                    same = false;
                                    break;
                                }

                                if ((metadata.install[i].filter == null) != (oldMetadata.install[i].filter == null))
                                {
                                    same = false;
                                    break;
                                }

                                if (metadata.install[i].filter != null)
                                {
                                    if (!metadata.install[i].filter.SequenceEqual(oldMetadata.install[i].filter))
                                    {
                                        same = false;
                                        break;
                                    }
                                }

                                if ((metadata.install[i].filter_regexp == null) != (oldMetadata.install[i].filter_regexp == null))
                                {
                                    same = false;
                                    break;
                                }

                                if (metadata.install[i].filter_regexp != null)
                                {
                                    if (!metadata.install[i].filter_regexp.SequenceEqual(oldMetadata.install[i].filter_regexp))
                                    {
                                        same = false;
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    if (!same)
                    {
                        metadataChanges.Add(registry.available_modules[identifier].module_version[installedVersion]);
                    }
                }
            }

            if (metadataChanges.Any())
            {
                string mods = "";
                for (int i = 0; i < metadataChanges.Count; i++)
                {
                    mods += metadataChanges[i].identifier + " "
                            + metadataChanges[i].version.ToString() + ((i < metadataChanges.Count - 1) ? ", " : "");
                }

                if (user.RaiseYesNoDialog(String.Format(
                                              @"The following mods have had their metadata changed since last update - {0}.
It is advisable that you reinstall them in order to preserve consistency with the repository. Do you wish to reinstall now?", mods)))
                {
                    ModuleInstaller installer = ModuleInstaller.GetInstance(ksp, new NullUser());
                    installer.Upgrade(metadataChanges, new NetAsyncDownloader(new NullUser()));
                }
            }

            // Remove our downloaded meta-data now we've processed it.
            // Seems weird to do this as part of a transaction, but Net.Download uses them, so let's be consistent.
            file_transaction.Delete(repo_file);
        }
Exemplo n.º 28
0
        // this probably needs to be refactored
        private void InstallMods(object sender, DoWorkEventArgs e)
        {
            installCanceled = false;
            Wait.ClearLog();

            var opts = (KeyValuePair <ModChanges, RelationshipResolverOptions>)e.Argument;

            RegistryManager registry_manager = RegistryManager.Instance(manager.CurrentInstance);
            Registry        registry         = registry_manager.registry;
            ModuleInstaller installer        = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser);

            // Avoid accumulating multiple event handlers
            installer.onReportModInstalled -= OnModInstalled;
            installer.onReportModInstalled += OnModInstalled;
            // setup progress callback

            // this will be the final list of mods we want to install
            HashSet <CkanModule> toInstall = new HashSet <CkanModule>();
            var toUninstall = new HashSet <string>();
            var toUpgrade   = new HashSet <string>();

            // First compose sets of what the user wants installed, upgraded, and removed.
            foreach (ModChange change in opts.Key)
            {
                switch (change.ChangeType)
                {
                case GUIModChangeType.Remove:
                    toUninstall.Add(change.Mod.identifier);
                    break;

                case GUIModChangeType.Update:
                    toUpgrade.Add(change.Mod.identifier);
                    break;

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

                case GUIModChangeType.Replace:
                    ModuleReplacement repl = registry.GetReplacement(change.Mod, CurrentInstance.VersionCriteria());
                    if (repl != null)
                    {
                        toUninstall.Add(repl.ToReplace.identifier);
                        toInstall.Add(repl.ReplaceWith);
                    }
                    break;
                }
            }

            // Prompt for recommendations and suggestions, if any
            if (installer.FindRecommendations(
                    opts.Key.Where(ch => ch.ChangeType == GUIModChangeType.Install)
                    .Select(ch => ch.Mod)
                    .ToHashSet(),
                    toInstall,
                    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, CurrentInstance.VersionCriteria(),
                    Manager.Cache, recommendations, suggestions, supporters);
                tabController.SetTabLock(true);
                var result = ChooseRecommendedMods.Wait();
                if (result == null)
                {
                    installCanceled = true;
                }
                else
                {
                    toInstall.UnionWith(result);
                }
                tabController.SetTabLock(false);
                tabController.HideTab("ChooseRecommendedModsTabPage");
            }

            if (installCanceled)
            {
                tabController.ShowTab("ManageModsTabPage");
                e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                return;
            }

            // Now let's make all our changes.
            Util.Invoke(this, () =>
            {
                // Need to be on the GUI thread to get the translated string
                tabController.RenameTab("WaitTabPage", Properties.Resources.MainInstallWaitTitle);
            });
            ShowWaitDialog();
            tabController.SetTabLock(true);

            IDownloader downloader = new NetAsyncModulesDownloader(currentUser, Manager.Cache);

            downloader.Progress    += Wait.SetModuleProgress;
            downloader.AllComplete += Wait.DownloadsComplete;
            cancelCallback          = () =>
            {
                downloader.CancelDownload();
                installCanceled = true;
            };

            HashSet <string> possibleConfigOnlyDirs = null;

            // checks if all actions were successfull
            bool processSuccessful       = false;
            bool resolvedAllProvidedMods = false;

            // uninstall/installs/upgrades until every list is empty
            // if the queue is NOT empty, resolvedAllProvidedMods is set to false until the action is done
            while (!resolvedAllProvidedMods)
            {
                try
                {
                    e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                    if (toUninstall.Count > 0)
                    {
                        processSuccessful = false;
                        if (!installCanceled)
                        {
                            installer.UninstallList(toUninstall, ref possibleConfigOnlyDirs, registry_manager, false, toInstall);
                            processSuccessful = true;
                        }
                    }
                    if (toUpgrade.Count > 0)
                    {
                        processSuccessful = false;
                        if (!installCanceled)
                        {
                            installer.Upgrade(toUpgrade, downloader, ref possibleConfigOnlyDirs, registry_manager);
                            processSuccessful = true;
                        }
                    }
                    if (toInstall.Count > 0)
                    {
                        processSuccessful = false;
                        if (!installCanceled)
                        {
                            installer.InstallList(toInstall, opts.Value, registry_manager, ref possibleConfigOnlyDirs, downloader, false);
                            processSuccessful = true;
                        }
                    }

                    HandlePossibleConfigOnlyDirs(registry, possibleConfigOnlyDirs);

                    e.Result = new KeyValuePair <bool, ModChanges>(processSuccessful, opts.Key);
                    if (installCanceled)
                    {
                        return;
                    }
                    resolvedAllProvidedMods = true;
                }
                catch (TooManyModsProvideKraken k)
                {
                    // Prompt user to choose which mod to use
                    tabController.ShowTab("ChooseProvidedModsTabPage", 3);
                    ChooseProvidedMods.LoadProviders(k.requested, k.modules, Manager.Cache);
                    tabController.SetTabLock(true);
                    CkanModule chosen = ChooseProvidedMods.Wait();
                    // Close the selection prompt
                    tabController.SetTabLock(false);
                    tabController.HideTab("ChooseProvidedModsTabPage");
                    if (chosen != null)
                    {
                        // User picked a mod, queue it up for installation
                        toInstall.Add(chosen);
                        // DON'T return so we can loop around and try the above InstallList call again
                        tabController.ShowTab("WaitTabPage");
                    }
                    else
                    {
                        // User cancelled, get out
                        tabController.ShowTab("ManageModsTabPage");
                        e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                        return;
                    }
                }
            }
        }
Exemplo n.º 29
0
        // this probably needs to be refactored
        private void InstallMods(object sender, DoWorkEventArgs e)
        {
            installCanceled = false;
            ClearLog();

            var opts = (KeyValuePair <ModChanges, RelationshipResolverOptions>)e.Argument;

            IRegistryQuerier registry  = RegistryManager.Instance(manager.CurrentInstance).registry;
            ModuleInstaller  installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, GUI.user);

            // Avoid accumulating multiple event handlers
            installer.onReportModInstalled -= OnModInstalled;
            installer.onReportModInstalled += OnModInstalled;
            // setup progress callback

            // this will be the final list of mods we want to install
            HashSet <CkanModule> toInstall = new HashSet <CkanModule>();
            var toUninstall = new HashSet <string>();
            var toUpgrade   = new HashSet <string>();

            // First compose sets of what the user wants installed, upgraded, and removed.
            foreach (ModChange change in opts.Key)
            {
                switch (change.ChangeType)
                {
                case GUIModChangeType.Remove:
                    toUninstall.Add(change.Mod.Identifier);
                    break;

                case GUIModChangeType.Update:
                    toUpgrade.Add(change.Mod.Identifier);
                    break;

                case GUIModChangeType.Install:
                    toInstall.Add(change.Mod.ToModule());
                    break;

                case GUIModChangeType.Replace:
                    ModuleReplacement repl = registry.GetReplacement(change.Mod.ToModule(), CurrentInstance.VersionCriteria());
                    if (repl != null)
                    {
                        toUninstall.Add(repl.ToReplace.identifier);
                        toInstall.Add(repl.ReplaceWith);
                    }
                    break;
                }
            }

            // Prompt for recommendations and suggestions, if any
            var recRows = getRecSugRows(
                opts.Key.Where(ch => ch.ChangeType == GUIModChangeType.Install)
                .Select(ch => ch.Mod.ToModule()),
                registry, toInstall
                );

            if (recRows.Any())
            {
                ShowRecSugDialog(recRows, toInstall);
            }

            tabController.HideTab("ChooseRecommendedModsTabPage");

            if (installCanceled)
            {
                tabController.ShowTab("ManageModsTabPage");
                e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                return;
            }

            // Now let's make all our changes.
            tabController.RenameTab("WaitTabPage", Properties.Resources.MainInstallWaitTitle);
            ShowWaitDialog();
            tabController.SetTabLock(true);

            IDownloader downloader = new NetAsyncModulesDownloader(GUI.user, Manager.Cache);

            cancelCallback = () =>
            {
                downloader.CancelDownload();
                installCanceled = true;
            };

            // checks if all actions were successfull
            bool processSuccessful       = false;
            bool resolvedAllProvidedMods = false;

            // uninstall/installs/upgrades until every list is empty
            // if the queue is NOT empty, resolvedAllProvidedMods is set to false until the action is done
            while (!resolvedAllProvidedMods)
            {
                try
                {
                    e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                    if (toUninstall.Count > 0)
                    {
                        processSuccessful = false;
                        if (!installCanceled)
                        {
                            installer.UninstallList(toUninstall, false, toInstall.Select(m => m.identifier));
                            processSuccessful = true;
                        }
                    }
                    if (toUpgrade.Count > 0)
                    {
                        processSuccessful = false;
                        if (!installCanceled)
                        {
                            installer.Upgrade(toUpgrade, downloader);
                            processSuccessful = true;
                        }
                    }
                    if (toInstall.Count > 0)
                    {
                        processSuccessful = false;
                        if (!installCanceled)
                        {
                            installer.InstallList(toInstall, opts.Value, downloader, false);
                            processSuccessful = true;
                        }
                    }
                    e.Result = new KeyValuePair <bool, ModChanges>(processSuccessful, opts.Key);
                    if (installCanceled)
                    {
                        return;
                    }
                    resolvedAllProvidedMods = true;
                }
                catch (TooManyModsProvideKraken k)
                {
                    // Prompt user to choose which mod to use
                    CkanModule chosen = TooManyModsProvideCore(k).Result;
                    // Close the selection prompt
                    Util.Invoke(this, () =>
                    {
                        tabController.ShowTab("WaitTabPage");
                        tabController.HideTab("ChooseProvidedModsTabPage");
                    });
                    if (chosen != null)
                    {
                        // User picked a mod, queue it up for installation
                        toInstall.Add(chosen);
                        // DON'T return so we can loop around and try the above InstallList call again
                    }
                    else
                    {
                        // User cancelled, get out
                        tabController.ShowTab("ManageModsTabPage");
                        e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                        return;
                    }
                }
                catch (DependencyNotSatisfiedKraken ex)
                {
                    GUI.user.RaiseMessage(Properties.Resources.MainInstallDepNotSatisfied, ex.parent, ex.module);
                    return;
                }
                catch (ModuleNotFoundKraken ex)
                {
                    GUI.user.RaiseMessage(Properties.Resources.MainInstallNotFound, ex.module);
                    return;
                }
                catch (BadMetadataKraken ex)
                {
                    GUI.user.RaiseMessage(Properties.Resources.MainInstallBadMetadata, ex.module, ex.Message);
                    return;
                }
                catch (FileExistsKraken ex)
                {
                    if (ex.owningModule != null)
                    {
                        GUI.user.RaiseMessage(
                            Properties.Resources.MainInstallFileExists,
                            ex.filename, ex.installingModule, ex.owningModule,
                            Meta.GetVersion()
                            );
                    }
                    else
                    {
                        GUI.user.RaiseMessage(
                            Properties.Resources.MainInstallUnownedFileExists,
                            ex.installingModule, ex.filename
                            );
                    }
                    GUI.user.RaiseMessage(Properties.Resources.MainInstallGameDataReverted);
                    return;
                }
                catch (InconsistentKraken ex)
                {
                    // The prettiest Kraken formats itself for us.
                    GUI.user.RaiseMessage(ex.InconsistenciesPretty);
                    return;
                }
                catch (CancelledActionKraken)
                {
                    return;
                }
                catch (MissingCertificateKraken kraken)
                {
                    // Another very pretty kraken.
                    GUI.user.RaiseMessage(kraken.ToString());
                    return;
                }
                catch (DownloadThrottledKraken kraken)
                {
                    string msg = kraken.ToString();
                    GUI.user.RaiseMessage(msg);
                    if (YesNoDialog(string.Format(Properties.Resources.MainInstallOpenSettingsPrompt, msg),
                                    Properties.Resources.MainInstallOpenSettings,
                                    Properties.Resources.MainInstallNo))
                    {
                        // Launch the URL describing this host's throttling practices, if any
                        if (kraken.infoUrl != null)
                        {
                            Process.Start(new ProcessStartInfo()
                            {
                                UseShellExecute = true,
                                FileName        = kraken.infoUrl.ToString()
                            });
                        }
                        // Now pretend they clicked the menu option for the settings
                        Enabled = false;
                        settingsDialog.ShowDialog();
                        Enabled = true;
                    }
                    return;
                }
                catch (ModuleDownloadErrorsKraken kraken)
                {
                    GUI.user.RaiseMessage(kraken.ToString());
                    GUI.user.RaiseError(kraken.ToString());
                    return;
                }
                catch (DirectoryNotFoundKraken kraken)
                {
                    GUI.user.RaiseMessage("\r\n{0}", kraken.Message);
                    return;
                }
                catch (DllNotFoundException)
                {
                    if (GUI.user.RaiseYesNoDialog(Properties.Resources.MainInstallLibCurlMissing))
                    {
                        Process.Start(new ProcessStartInfo()
                        {
                            UseShellExecute = true,
                            FileName        = "https://github.com/KSP-CKAN/CKAN/wiki/libcurl"
                        });
                    }
                    throw;
                }
            }
        }
Exemplo n.º 30
0
        /// <summary>
        /// Updates the supplied registry from the URL given.
        /// This does not *save* the registry. For that, you probably want Repo.Update
        /// </summary>
        internal static void UpdateRegistry(Uri repo, Registry registry, KSP ksp, IUser user, Boolean clear = true)
        {
            // Use this opportunity to also update the build mappings... kind of hacky
            ServiceLocator.Container.Resolve <IKspBuildMap>().Refresh();

            log.InfoFormat("Downloading {0}", repo);

            string repo_file = String.Empty;

            try
            {
                repo_file = Net.Download(repo);
            }
            catch (System.Net.WebException)
            {
                user.RaiseMessage("Connection to {0} could not be established.", repo);
                return;
            }

            // Clear our list of known modules.
            if (clear)
            {
                registry.ClearAvailable();
            }

            // Check the filetype.
            FileType type = FileIdentifier.IdentifyFile(repo_file);

            switch (type)
            {
            case FileType.TarGz:
                UpdateRegistryFromTarGz(repo_file, registry);
                break;

            case FileType.Zip:
                UpdateRegistryFromZip(repo_file, registry);
                break;

            default:
                break;
            }

            List <CkanModule> metadataChanges = new List <CkanModule>();

            foreach (var installedModule in registry.InstalledModules)
            {
                var identifier = installedModule.identifier;

                var installedVersion = registry.InstalledVersion(identifier);
                if (!(registry.available_modules.ContainsKey(identifier)))
                {
                    log.InfoFormat("UpdateRegistry, module {0}, version {1} not in repository ({2})", identifier, installedVersion, repo);
                    continue;
                }

                if (!registry.available_modules[identifier].module_version.ContainsKey(installedVersion))
                {
                    continue;
                }

                // if the mod is installed and the metadata is different we have to reinstall it
                var metadata = registry.available_modules[identifier].module_version[installedVersion];

                var oldMetadata = registry.InstalledModule(identifier).Module;

                bool same = true;
                if ((metadata.install == null) != (oldMetadata.install == null) ||
                    (metadata.install != null && metadata.install.Length != oldMetadata.install.Length))
                {
                    same = false;
                }
                else
                {
                    if (metadata.install != null)
                    {
                        for (int i = 0; i < metadata.install.Length; i++)
                        {
                            if (metadata.install[i].file != oldMetadata.install[i].file)
                            {
                                same = false;
                                break;
                            }

                            if (metadata.install[i].install_to != oldMetadata.install[i].install_to)
                            {
                                same = false;
                                break;
                            }

                            if (metadata.install[i].@as != oldMetadata.install[i].@as)
                            {
                                same = false;
                                break;
                            }

                            if ((metadata.install[i].filter == null) != (oldMetadata.install[i].filter == null))
                            {
                                same = false;
                                break;
                            }


                            if (metadata.install[i].filter != null)
                            {
                                if (!metadata.install[i].filter.SequenceEqual(oldMetadata.install[i].filter))
                                {
                                    same = false;
                                    break;
                                }
                            }

                            if ((metadata.install[i].filter_regexp == null) != (oldMetadata.install[i].filter_regexp == null))
                            {
                                same = false;
                                break;
                            }

                            if (metadata.install[i].filter_regexp != null)
                            {
                                if (!metadata.install[i].filter_regexp.SequenceEqual(oldMetadata.install[i].filter_regexp))
                                {
                                    same = false;
                                    break;
                                }
                            }
                        }
                    }
                }

                if (!RelationshipsAreEquivalent(metadata.conflicts, oldMetadata.conflicts))
                {
                    same = false;
                }

                if (!RelationshipsAreEquivalent(metadata.depends, oldMetadata.depends))
                {
                    same = false;
                }

                if (!RelationshipsAreEquivalent(metadata.recommends, oldMetadata.recommends))
                {
                    same = false;
                }

                if (metadata.provides != oldMetadata.provides)
                {
                    if (metadata.provides == null || oldMetadata.provides == null)
                    {
                        same = false;
                    }
                    else if (!metadata.provides.OrderBy(i => i).SequenceEqual(oldMetadata.provides.OrderBy(i => i)))
                    {
                        same = false;
                    }
                }

                if (!same)
                {
                    metadataChanges.Add(registry.available_modules[identifier].module_version[installedVersion]);
                }
            }

            if (metadataChanges.Any())
            {
                var sb = new StringBuilder();

                for (var i = 0; i < metadataChanges.Count; i++)
                {
                    var module = metadataChanges[i];

                    sb.AppendLine(string.Format("- {0} {1}", module.identifier, module.version));
                }

                if (user.RaiseYesNoDialog(string.Format(@"The following mods have had their metadata changed since last update:

{0}
You should reinstall them in order to preserve consistency with the repository.

Do you wish to reinstall now?", sb)))
                {
                    ModuleInstaller installer = ModuleInstaller.GetInstance(ksp, new NullUser());
                    // New upstream metadata may break the consistency of already installed modules
                    // e.g. if user installs modules A and B and then later up A is made to conflict with B
                    // This is perfectly normal and shouldn't produce an error, therefore we skip enforcing
                    // consistency. However, we will show the user any inconsistencies later on.

                    // Use the identifiers so we use the overload that actually resolves relationships
                    // Do each changed module one at a time so a failure of one doesn't cause all the others to fail
                    foreach (var changedIdentifier in metadataChanges.Select(i => i.identifier))
                    {
                        try
                        {
                            installer.Upgrade(
                                new[] { changedIdentifier },
                                new NetAsyncModulesDownloader(new NullUser()),
                                enforceConsistency: false
                                );
                        }
                        // Thrown when a dependency couldn't be satisfied
                        catch (ModuleNotFoundKraken)
                        {
                            log.WarnFormat("Skipping installation of {0} due to relationship error.", changedIdentifier);
                            user.RaiseMessage("Skipping installation of {0} due to relationship error.", changedIdentifier);
                        }
                        // Thrown when a conflicts relationship is violated
                        catch (InconsistentKraken)
                        {
                            log.WarnFormat("Skipping installation of {0} due to relationship error.", changedIdentifier);
                            user.RaiseMessage("Skipping installation of {0} due to relationship error.", changedIdentifier);
                        }
                    }
                }
            }

            // Remove our downloaded meta-data now we've processed it.
            // Seems weird to do this as part of a transaction, but Net.Download uses them, so let's be consistent.
            file_transaction.Delete(repo_file);
        }