示例#1
0
        public void Setup()
        {
            // Make sure curl is all set up.
            Curl.Init();

            // Give us a registry to play with.
            ksp      = new DisposableKSP();
            registry = ksp.KSP.Registry;

            registry.ClearAvailable();
            registry.ClearDlls();
            registry.Installed().Clear();

            // Make sure we have a registry we can use.
            CKAN.Repo.UpdateRegistry(TestData.TestKAN(), registry, ksp.KSP, new NullUser());

            // Ready our downloader.
            async = new CKAN.NetAsyncDownloader(new NullUser());

            // General shortcuts
            cache = ksp.KSP.Cache;
        }
示例#2
0
        /// <summary>
        /// Upgrades the mods listed to the latest versions for the user's KSP.
        /// Will *re-install* with warning even if an upgrade is not available.
        /// Throws ModuleNotFoundKraken if module is not installed, or not available.
        /// </summary>
        public void Upgrade(IEnumerable <string> identifiers, NetAsyncDownloader netAsyncDownloader)
        {
            List <CkanModule> upgrades = new List <CkanModule>();

            foreach (string ident in identifiers)
            {
                CkanModule latest = registry_manager.registry.LatestAvailable(
                    ident, ksp.Version()
                    );

                if (latest == null)
                {
                    throw new ModuleNotFoundKraken(
                              ident,
                              "Can't upgrade {0}, no modules available", ident
                              );
                }

                upgrades.Add(latest);
            }

            Upgrade(upgrades, netAsyncDownloader);
        }
示例#3
0
        /// <summary>
        /// Upgrades the mods listed to the specified versions for the user's KSP.
        /// Will *re-install* or *downgrade* (with a warning) as well as upgrade.
        /// Throws ModuleNotFoundKraken if a module is not installed.
        /// </summary>
        public void Upgrade(IEnumerable <CkanModule> modules, NetAsyncDownloader netAsyncDownloader)
        {
            // Start by making sure we've downloaded everything.
            DownloadModules(modules, netAsyncDownloader);

            foreach (CkanModule module in modules)
            {
                string ident     = module.identifier;
                Module installed = registry_manager.registry.InstalledModule(ident).Module;

                if (installed == null)
                {
                    throw new ModuleNotFoundKraken(
                              ident,
                              "Can't upgrade {0}, it is not installed", ident
                              );
                }

                if (installed.version.IsEqualTo(module.version))
                {
                    log.WarnFormat("{0} is already at the latest version, reinstalling", installed.identifier);
                }
                else if (installed.version.IsGreaterThan(module.version))
                {
                    log.WarnFormat("Downgrading {0} from {1} to {2}", ident, installed.version, module.version);
                }
                else
                {
                    log.InfoFormat("Upgrading {0} to {1}", ident, module.version);
                }
            }

            AddRemove(
                modules,
                modules.Select(x => x.identifier)
                );
        }
示例#4
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);
        }
示例#5
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);
        }
 /// <summary>
 /// Returns a perfectly boring NetAsyncModulesDownloader.
 /// </summary>
 public NetAsyncModulesDownloader(IUser user)
 {
     modules    = new List <CkanModule>();
     downloader = new NetAsyncDownloader(user);
 }
示例#7
0
        public void Setup()
        {
            // Make sure curl is all set up.
            Curl.Init();

            // Give us a registry to play with.
            ksp = new DisposableKSP();
            registry = ksp.KSP.Registry;

            registry.ClearAvailable();
            registry.ClearDlls();
            registry.Installed().Clear();

            // Make sure we have a registry we can use.
            CKAN.Repo.UpdateRegistry(TestData.TestKANZip(), registry, ksp.KSP, new NullUser());

            // Ready our downloader.
            async = new CKAN.NetAsyncDownloader(new NullUser());

            // General shortcuts
            cache = ksp.KSP.Cache;
        }
示例#8
0
        /// <summary>
        /// Upgrades the mods listed to the latest versions for the user's KSP.
        /// Will *re-install* with warning even if an upgrade is not available.
        /// Throws ModuleNotFoundKraken if module is not installed, or not available.
        /// </summary>
        public void Upgrade(IEnumerable<string> identifiers, NetAsyncDownloader netAsyncDownloader)
        {
            var options = new RelationshipResolverOptions();

            // We do not wish to pull in any suggested or recommended mods.
            options.with_recommends = false;
            options.with_suggests = false;

            var resolver = new RelationshipResolver(identifiers.ToList(), options, registry_manager.registry, ksp.Version());
            List<CkanModule> upgrades = resolver.ModList();

            Upgrade(upgrades, netAsyncDownloader);
        }
示例#9
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, 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);

            m_TabController.HideTab("ChooseRecommendedModsTabPage");

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

            // Now let's make all our changes.

            m_TabController.RenameTab("WaitTabPage", "Status log");
            m_TabController.ShowTab("WaitTabPage");
            m_TabController.SetTabLock(true);

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

            //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(toInstall, opts.Value, downloader);
                    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>
 /// Returns a perfectly boring NetAsyncModulesDownloader.
 /// </summary>
 public NetAsyncModulesDownloader(IUser user, FactorioAuthData factorioAuthData = null)
 {
     modules               = new List <CfanModule>();
     downloader            = new NetAsyncDownloader(user);
     this.factorioAuthData = factorioAuthData;
 }
示例#11
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
                var module_installer = ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user);
                module_installer.onReportModInstalled = OnModInstalled;
                cancelCallback = downloader.CancelDownload;
                return WasSuccessful(
                    () => module_installer.InstallList(toInstall.ToList(), options, downloader));
            }

            return true;
        }
示例#12
0
 /// <summary>
 /// Returns a perfectly boring NetAsyncModulesDownloader.
 /// </summary>
 public NetAsyncModulesDownloader(IUser user, NetModuleCache cache)
 {
     modules    = new List <CkanModule>();
     downloader = new NetAsyncDownloader(user);
     this.cache = cache;
 }
示例#13
0
        /// <summary>
        /// Makes sure all the specified mods are downloaded.
        /// </summary>
        private void DownloadModules(IEnumerable<CkanModule> mods, NetAsyncDownloader downloader)
        {
            List<CkanModule> downloads = mods.Where(module => !ksp.Cache.IsCachedZip(module.download)).ToList();

            if (downloads.Count > 0)
            {
                downloader.DownloadModules(ksp.Cache, downloads);
            }
        }
示例#14
0
        /// <summary>
        /// Upgrades or installs the mods listed to the specified versions for the user's KSP.
        /// Will *re-install* or *downgrade* (with a warning) as well as upgrade.
        /// Throws ModuleNotFoundKraken if a module is not installed.
        /// </summary>
        public void Upgrade(IEnumerable<CkanModule> modules, NetAsyncDownloader netAsyncDownloader)
        {
            // Start by making sure we've downloaded everything.
            DownloadModules(modules, netAsyncDownloader);

            // Our upgrade involves removing everything that's currently installed, then
            // adding everything that needs installing (which may involve new mods to
            // satisfy dependencies). We always know the list passed in is what we need to
            // install, but we need to calculate what needs to be removed.
            var to_remove = new List<string>();

            // Let's discover what we need to do with each module!
            foreach (CkanModule module in modules)
            {
                string ident = module.identifier;
                InstalledModule installed_mod = registry_manager.registry.InstalledModule(ident);

                if (installed_mod == null)
                {
                    //Maybe ModuleNotInstalled ?
                    if (registry_manager.registry.IsAutodetected(ident))
                    {
                        throw new ModuleNotFoundKraken(ident, module.version.ToString(), String.Format("Can't upgrade {0} as it was not installed by CKAN. \n Please remove manually before trying to install it.", ident));
                    }

                    User.RaiseMessage("Installing previously uninstalled mod {0}", ident);
                }
                else
                {
                    // Module already installed. We'll need to remove it first.
                    to_remove.Add(module.identifier);

                    Module installed = installed_mod.Module;
                    if (installed.version.IsEqualTo(module.version))
                    {
                        log.WarnFormat("{0} is already at the latest version, reinstalling", installed.identifier);
                    }
                    else if (installed.version.IsGreaterThan(module.version))
                    {
                        log.WarnFormat("Downgrading {0} from {1} to {2}", ident, installed.version, module.version);
                    }
                    else
                    {
                        log.InfoFormat("Upgrading {0} to {1}", ident, module.version);
                    }
                }
            }

            AddRemove(
                modules,
                to_remove
            );
        }
示例#15
0
        /// <summary>
        ///     Installs all modules given a list of identifiers as a transaction. Resolves dependencies.
        ///     This *will* save the registry at the end of operation.
        ///
        /// Propagates a BadMetadataKraken if our install metadata is bad.
        /// Propagates a FileExistsKraken if we were going to overwrite a file.
        /// Propagates a CancelledActionKraken if the user cancelled the install.
        /// </summary>
        //
        // TODO: Break this up into smaller pieces! It's huge!
        public void InstallList(
            ICollection<CkanModule> modules,
            RelationshipResolverOptions options,
            IDownloader downloader = null
        )
        {
            var resolver = new RelationshipResolver(modules, options, registry_manager.registry, ksp.Version());
            List<CkanModule> modsToInstall = resolver.ModList();
            List<CkanModule> downloads = new List<CkanModule> ();

            // TODO: All this user-stuff should be happening in another method!
            // We should just be installing mods as a transaction.

            User.RaiseMessage("About to install...\n");

            foreach (CkanModule module in modsToInstall)
            {
                if (!ksp.Cache.IsCachedZip(module.download))
                {
                    User.RaiseMessage(" * {0} {1}", module.name, module.version);
                    downloads.Add(module);
                }
                else
                {
                    User.RaiseMessage(" * {0} {1}(cached)", module.name, module.version);
                }
            }

            bool ok = User.RaiseYesNoDialog("\nContinue?");

            if (!ok)
            {
                throw new CancelledActionKraken("User declined install list");
            }

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

            if (downloads.Count > 0)
            {
                if (downloader == null)
                {
                    downloader = new NetAsyncDownloader(User);
                }

                downloader.DownloadModules(ksp.Cache, downloads);
            }

            // We're about to install all our mods; so begin our transaction.
            using (TransactionScope transaction = CkanTransaction.CreateTransactionScope())
            {
                for (int i = 0; i < modsToInstall.Count; i++)
                {
                    int percent_complete = (i * 100) / modsToInstall.Count;

                    User.RaiseProgress(String.Format("Installing mod \"{0}\"", modsToInstall[i]),
                                         percent_complete);

                    Install(modsToInstall[i]);
                }

                User.RaiseProgress("Updating registry", 70);

                registry_manager.Save(!options.without_enforce_consistency);

                User.RaiseProgress("Commiting filesystem changes", 80);

                transaction.Complete();

            }

            // We can scan GameData as a separate transaction. Installing the mods
            // leaves everything consistent, and this is just gravy. (And ScanGameData
            // acts as a Tx, anyway, so we don't need to provide our own.)

            User.RaiseProgress("Rescanning GameData", 90);

            if (!options.without_enforce_consistency)
            {
                ksp.ScanGameData();
            }

            User.RaiseProgress("Done!\n", 100);
        }
示例#16
0
        // this probably needs to be refactored
        private void InstallMods(object sender, DoWorkEventArgs e)
        {
            installCanceled = false;

            ClearLog();

            var opts =
                (KeyValuePair<ModChanges, 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<GUIMod, 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.ToModule().recommends != null)
                    {
                        foreach (RelationshipDescriptor mod in change.Key.ToModule().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.ToModule().suggests != null)
                    {
                        foreach (RelationshipDescriptor mod in change.Key.ToModule().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, ModChanges>(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);

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

            //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(toInstall, opts.Value, downloader);
                    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);
        }
示例#17
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);

            m_TabController.HideTab("ChooseRecommendedModsTabPage");

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

            // Now let's make all our changes.

            m_TabController.RenameTab("WaitTabPage", "Status log");
            m_TabController.ShowTab("WaitTabPage");
            m_TabController.SetTabLock(true);


            var downloader = new NetAsyncDownloader(GUI.user);

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

            //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(toInstall, opts.Value, downloader);
                    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);
        }
示例#18
0
        /// <summary>
        ///     Installs all modules given a list of identifiers as a transaction. Resolves dependencies.
        ///     This *will* save the registry at the end of operation.
        ///
        /// Propagates a BadMetadataKraken if our install metadata is bad.
        /// Propagates a FileExistsKraken if we were going to overwrite a file.
        /// Propagates a CancelledActionKraken if the user cancelled the install.
        /// </summary>
        //
        // TODO: Break this up into smaller pieces! It's huge!
        public void InstallList(
            ICollection <CkanModule> modules,
            RelationshipResolverOptions options,
            IDownloader downloader = null
            )
        {
            var resolver = new RelationshipResolver(modules, options, registry_manager.registry, ksp.Version());
            List <CkanModule> modsToInstall = resolver.ModList();
            List <CkanModule> downloads     = new List <CkanModule> ();

            // TODO: All this user-stuff should be happening in another method!
            // We should just be installing mods as a transaction.

            User.RaiseMessage("About to install...\n");

            foreach (CkanModule module in modsToInstall)
            {
                if (!ksp.Cache.IsCachedZip(module.download))
                {
                    User.RaiseMessage(" * {0}", module);
                    downloads.Add(module);
                }
                else
                {
                    User.RaiseMessage(" * {0} (cached)", module);
                }
            }

            bool ok = User.RaiseYesNoDialog("\nContinue?");

            if (!ok)
            {
                throw new CancelledActionKraken("User declined install list");
            }

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

            if (downloads.Count > 0)
            {
                if (downloader == null)
                {
                    downloader = new NetAsyncDownloader(User);
                }

                downloader.DownloadModules(ksp.Cache, downloads);
            }

            // We're about to install all our mods; so begin our transaction.
            using (TransactionScope transaction = CkanTransaction.CreateTransactionScope())
            {
                for (int i = 0; i < modsToInstall.Count; i++)
                {
                    int percent_complete = (i * 100) / modsToInstall.Count;

                    User.RaiseProgress(String.Format("Installing mod \"{0}\"", modsToInstall[i]),
                                       percent_complete);

                    Install(modsToInstall[i]);
                }

                User.RaiseProgress("Updating registry", 70);

                registry_manager.Save(!options.without_enforce_consistency);

                User.RaiseProgress("Commiting filesystem changes", 80);

                transaction.Complete();
            }

            // We can scan GameData as a separate transaction. Installing the mods
            // leaves everything consistent, and this is just gravy. (And ScanGameData
            // acts as a Tx, anyway, so we don't need to provide our own.)

            User.RaiseProgress("Rescanning GameData", 90);

            if (!options.without_enforce_consistency)
            {
                ksp.ScanGameData();
            }

            User.RaiseProgress("Done!\n", 100);
        }
示例#19
0
        private void CacheMod(object sender, DoWorkEventArgs e)
        {
            ResetProgress();
            ClearLog();

            NetAsyncDownloader dowloader = new NetAsyncDownloader(m_User);
            
            dowloader.DownloadModules(CurrentInstance.Cache, new List<CkanModule> { (CkanModule)e.Argument });
            e.Result = e.Argument;
        }
示例#20
0
        /// <summary>
        ///     Installs all modules given a list of identifiers as a transaction. Resolves dependencies.
        ///     This *will* save the registry at the end of operation.
        ///
        /// Propagates a BadMetadataKraken if our install metadata is bad.
        /// Propagates a FileExistsKraken if we were going to overwrite a file.
        /// Propagates a CancelledActionKraken if the user cancelled the install.
        /// </summary>
        //
        // TODO: Break this up into smaller pieces! It's huge!
        public void InstallList(
            List <string> modules,
            RelationshipResolverOptions options,
            NetAsyncDownloader downloader = null
            )
        {
            onReportProgress = onReportProgress ?? ((message, progress) => { });

            var resolver = new RelationshipResolver(modules, options, registry_manager.registry);
            List <CkanModule> modsToInstall = resolver.ModList();
            List <CkanModule> downloads     = new List <CkanModule> ();

            // TODO: All this user-stuff should be happening in another method!
            // We should just be installing mods as a transaction.

            User.WriteLine("About to install...\n");

            foreach (CkanModule module in modsToInstall)
            {
                if (!ksp.Cache.IsCachedZip(module.download))
                {
                    User.WriteLine(" * {0}", module);
                    downloads.Add(module);
                }
                else
                {
                    User.WriteLine(" * {0} (cached)", module);
                }
            }

            bool ok = User.YesNo("\nContinue?", FrontEndType.CommandLine);

            if (!ok)
            {
                throw new CancelledActionKraken("User declined install list");
            }

            User.WriteLine(""); // Just to look tidy.

            if (downloads.Count > 0)
            {
                if (downloader == null)
                {
                    downloader = new NetAsyncDownloader();
                }

                downloader.DownloadModules(ksp.Cache, downloads, onReportProgress);
            }

            // We're about to install all our mods; so begin our transaction.
            var txoptions = new TransactionOptions();

            txoptions.Timeout = TransactionManager.MaximumTimeout;

            using (TransactionScope transaction = new TransactionScope(TransactionScopeOption.Required, txoptions))
            {
                for (int i = 0; i < modsToInstall.Count; i++)
                {
                    int percentComplete = (i * 100) / modsToInstall.Count;

                    onReportProgress(String.Format("Installing mod \"{0}\"", modsToInstall[i]),
                                     percentComplete);

                    Install(modsToInstall[i]);
                }

                onReportProgress("Updating registry", 70);

                registry_manager.Save();

                onReportProgress("Commiting filesystem changes", 80);

                transaction.Complete();
            }

            // We can scan GameData as a separate transaction. Installing the mods
            // leaves everything consistent, and this is just gravy. (And ScanGameData
            // acts as a Tx, anyway, so we don't need to provide our own.)

            onReportProgress("Rescanning GameData", 90);

            ksp.ScanGameData();

            onReportProgress("Done!", 100);
        }
示例#21
0
        public void InstallList(
            List<string> modules,
            RelationshipResolverOptions options,
            NetAsyncDownloader downloader = null
        )
        {
            var resolver = new RelationshipResolver(modules, options, registry_manager.registry, ksp.Version());
            List<CkanModule> modsToInstall = resolver.ModList();

            InstallList(modsToInstall, options, downloader);
        }