示例#1
0
文件: Repo.cs 项目: 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);
                    }
                }
            }
        }
示例#2
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;
                }
            }
        }
示例#3
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);
        }
示例#4
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;
                    }
                }
            }
        }
示例#5
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);
        }
示例#6
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;
                }
            }
        }
示例#7
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);
        }
示例#8
0
        private void InstallMods(object sender, DoWorkEventArgs e) // this probably needs to be refactored
        {
            ShowWaitDialog();
            installCanceled = false;

            ClearLog();

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

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

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

            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;
                }
            }

            // Now work on satisifying dependencies.

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

            foreach (var change in opts.Key)
            {
                if (change.ChangeType == GUIModChangeType.Install)
                {
                    AddMod(change.Mod.ToModule().recommends, recommended, change.Mod.Identifier, registry);
                    AddMod(change.Mod.ToModule().suggests, suggested, change.Mod.Identifier, registry);
                }
            }

            ShowSelection(recommended);
            ShowSelection(suggested, true);

            tabController.HideTab("ChooseRecommendedModsTabPage");

            if (installCanceled)
            {
                tabController.HideTab("WaitTabPage");
                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");
            tabController.ShowTab("WaitTabPage");
            tabController.SetTabLock(true);

            IDownloader downloader = new NetAsyncModulesDownloader(GUI.user);

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

            bool resolvedAllProvidedMods = false;

            while (!resolvedAllProvidedMods)
            {
                try
                {
                    e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                    if (!installCanceled && toUninstall.Count > 0)
                    {
                        installer.UninstallList(toUninstall);
                    }
                    if (!installCanceled && toUpgrade.Count > 0)
                    {
                        installer.Upgrade(toUpgrade, downloader);
                    }
                    if (!installCanceled && toInstall.Count > 0)
                    {
                        installer.InstallList(toInstall, opts.Value, downloader);
                    }
                    e.Result = new KeyValuePair <bool, ModChanges>(!installCanceled, opts.Key);
                    if (installCanceled)
                    {
                        return;
                    }
                    resolvedAllProvidedMods = true;
                }
                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?"))
                    {
                        // 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;
                }
            }
        }
示例#9
0
        private void InstallMods(object sender, DoWorkEventArgs e) // this probably needs to be refactored
        {
            installCanceled = false;

            ClearLog();

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

            IRegistryQuerier registry  = RegistryManager.Instance(manager.CurrentInstance).registry;
            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 (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.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.ChangeType == GUIModChangeType.Install)
                {
                    AddMod(change.Mod.ToModule().recommends, recommended, change.Mod.Identifier, registry);
                    AddMod(change.Mod.ToModule().suggests, suggested, change.Mod.Identifier, registry);
                }
            }

            ShowSelection(recommended);
            ShowSelection(suggested, true);

            tabController.HideTab("ChooseRecommendedModsTabPage");

            if (installCanceled)
            {
                tabController.HideTab("WaitTabPage");
                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");
            tabController.ShowTab("WaitTabPage");
            tabController.SetTabLock(true);


            var downloader = new NetAsyncModulesDownloader(GUI.user);

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

            GUI.user.RaiseMessage("About to install...\r\n");

            // FIXME: here we should heat up the cache with any mods we're going to install, because
            // when this transaction types out it f***s up everything else.
            var resolvedMods = installer.ResolveModules(toInstall, opts.Value);

            foreach (var module in resolvedMods.CachedModules)
            {
                GUI.user.RaiseMessage(" * {0} {1}(cached)", module.name, module.version);
            }

            foreach (var module in resolvedMods.UncachedModules)
            {
                GUI.user.RaiseMessage(" * {0} {1}", module.name, module.version);
            }

            if (!GUI.user.RaiseYesNoDialog("\r\nContinue?"))
            {
                throw new CancelledActionKraken("User declined install list");
            }

            GUI.user.RaiseMessage(String.Empty); // Just to look tidy.

            installer.EnsureCache(resolvedMods.UncachedModules);

            //Transaction is needed here to revert changes when an installation is cancelled
            //TODO: Cancellation should be handelt in the ModuleInstaller
            using (var transaction = CkanTransaction.CreateTransactionScope())
            {
                //Set the result to false/failed in case we return
                e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                SetDescription("Uninstalling selected mods");
                if (!WasSuccessful(() => installer.UninstallList(toUninstall)))
                {
                    return;
                }
                if (installCanceled)
                {
                    return;
                }

                SetDescription("Updating selected mods");
                if (!WasSuccessful(() => installer.Upgrade(toUpgrade, downloader)))
                {
                    return;
                }
                if (installCanceled)
                {
                    return;
                }

                // 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, ModChanges>(false, opts.Key);
                        return;
                    }
                    var ret = InstallList(resolvedMods, opts.Value);
                    if (!ret)
                    {
                        // install failed for some reason, error message is already displayed to the user
                        e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key);
                        return;
                    }
                    resolvedAllProvidedMods = true;
                }

                if (!installCanceled)
                {
                    transaction.Complete();
                }
            }

            e.Result = new KeyValuePair <bool, ModChanges>(!installCanceled, opts.Key);
        }
示例#10
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 e)
            {
                user.RaiseError($"Couldn't download {repo}.", e);
                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 <CfanModule> metadataChanges = new List <CfanModule>();

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

                if (registry.IsInstalled(identifier))
                {
                    AbstractVersion abstractVersion  = registry.InstalledVersion(identifier);
                    var             installedVersion = new ModVersion(abstractVersion.ToString());

                    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
                    CfanModule metadata = new CfanModule(registry.available_modules[identifier].module_version[installedVersion]);

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

                    CfanModule oldMetadata = new CfanModule(old_available[identifier].module_version[installedVersion]);

                    bool same = metadata.kind == oldMetadata.kind;

                    if (!same)
                    {
                        metadataChanges.Add(new CfanModule(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].modVersion.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 NetAsyncModulesDownloader(new NullUser(), ksp.tryGetFactorioAuthData()));
                }
            }

            // 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);
        }