Esempio n. 1
0
        public void UpdateRegistryTarGz()
        {
            CKAN.Repo.UpdateRegistry(TestData.TestKANTarGz(), registry, ksp.KSP, new NullUser());

            // Test we've got an expected module.
            CKAN.CkanModule far = registry.LatestAvailable("FerramAerospaceResearch", new CKAN.KSPVersion("0.25.0"));

            Assert.AreEqual("v0.14.3.2", far.version.ToString());
        }
Esempio n. 2
0
        public void SetUp()
        {
            _testModule = TestData.DogeCoinFlag_101_module();

            _instance  = new DisposableKSP();
            _registry  = CKAN.RegistryManager.Instance(_instance.KSP).registry;
            _installer = CKAN.ModuleInstaller.GetInstance(_instance.KSP, NullUser.User);

            _gameDataDir = _instance.KSP.GameData();
            _registry.AddAvailable(_testModule);
            var testModFile = TestData.DogeCoinFlagZip();

            _instance.KSP.Cache.Store(_testModule.download, testModFile);
            _installer.InstallList(
                new List <string>()
            {
                _testModule.identifier
            },
                new RelationshipResolverOptions()
                );
        }
Esempio n. 3
0
 public override bool WithinBounds(CkanModule otherModule)
 {
     return(otherModule.ProvidesList.Contains(name) &&
            WithinBounds(otherModule.version));
 }
Esempio n. 4
0
 public bool IsCached(CkanModule m)
 {
     return(cache.IsCached(m.download));
 }
Esempio n. 5
0
        private void UpdateModInfo(GUIMod gui_module)
        {
            CkanModule module = gui_module.ToModule();

            Util.Invoke(MetadataModuleNameTextBox, () => MetadataModuleNameTextBox.Text = module.name);
            UpdateTagsAndLabels(module);
            Util.Invoke(MetadataModuleAbstractLabel, () => MetadataModuleAbstractLabel.Text = module.@abstract);
            Util.Invoke(MetadataModuleDescriptionTextBox, () =>
            {
                MetadataModuleDescriptionTextBox.Text = module.description
                                                        ?.Replace("\r\n", "\n").Replace("\n", Environment.NewLine);
                MetadataModuleDescriptionTextBox.ScrollBars =
                    string.IsNullOrWhiteSpace(module.description)
                        ? ScrollBars.None
                        : ScrollBars.Vertical;
            });

            Util.Invoke(MetadataModuleVersionTextBox, () => MetadataModuleVersionTextBox.Text = gui_module.LatestVersion.ToString());
            Util.Invoke(MetadataModuleLicenseTextBox, () => MetadataModuleLicenseTextBox.Text = string.Join(", ", module.license));
            Util.Invoke(MetadataModuleAuthorTextBox, () => MetadataModuleAuthorTextBox.Text   = gui_module.Authors);
            Util.Invoke(MetadataIdentifierTextBox, () => MetadataIdentifierTextBox.Text       = module.identifier);

            Util.Invoke(MetadataModuleReleaseStatusTextBox, () =>
            {
                if (module.release_status == null)
                {
                    ReleaseLabel.Visible = false;
                    MetadataModuleReleaseStatusTextBox.Visible = false;
                    MetaDataLowerLayoutPanel.LayoutSettings.RowStyles[3].Height = 0;
                }
                else
                {
                    ReleaseLabel.Visible = true;
                    MetadataModuleReleaseStatusTextBox.Visible = true;
                    MetaDataLowerLayoutPanel.LayoutSettings.RowStyles[3].Height = 30;
                    MetadataModuleReleaseStatusTextBox.Text = module.release_status.ToString();
                }
            });
            Util.Invoke(MetadataModuleGameCompatibilityTextBox, () => MetadataModuleGameCompatibilityTextBox.Text = gui_module.GameCompatibilityLong);

            Util.Invoke(ModInfoTabControl, () =>
            {
                // Mono doesn't draw TabPage.ImageIndex, so fake it
                const string fakeStopSign          = "<!> ";
                ComponentResourceManager resources = new SingleAssemblyComponentResourceManager(typeof(ModInfo));
                resources.ApplyResources(RelationshipTabPage, "RelationshipTabPage");
                resources.ApplyResources(AllModVersionsTabPage, "AllModVersionsTabPage");
                if (gui_module.IsIncompatible)
                {
                    if (!module.IsCompatibleKSP(manager.CurrentInstance.VersionCriteria()))
                    {
                        AllModVersionsTabPage.Text = fakeStopSign + AllModVersionsTabPage.Text;
                    }
                    else
                    {
                        RelationshipTabPage.Text = fakeStopSign + RelationshipTabPage.Text;
                    }
                }
            });
            Util.Invoke(ReplacementTextBox, () =>
            {
                if (module.replaced_by == null)
                {
                    ReplacementLabel.Visible   = false;
                    ReplacementTextBox.Visible = false;
                    MetaDataLowerLayoutPanel.LayoutSettings.RowStyles[6].Height = 0;
                }
                else
                {
                    ReplacementLabel.Visible   = true;
                    ReplacementTextBox.Visible = true;
                    MetaDataLowerLayoutPanel.LayoutSettings.RowStyles[6].Height = 30;
                    ReplacementTextBox.Text = module.replaced_by.ToString();
                }
            });

            Util.Invoke(MetaDataLowerLayoutPanel, () =>
            {
                ClearResourceLinks();
                var res = module.resources;
                if (res != null)
                {
                    AddResourceLink(Properties.Resources.ModInfoHomepageLabel, res.homepage);
                    AddResourceLink(Properties.Resources.ModInfoSpaceDockLabel, res.spacedock);
                    AddResourceLink(Properties.Resources.ModInfoCurseLabel, res.curse);
                    AddResourceLink(Properties.Resources.ModInfoRepositoryLabel, res.repository);
                    AddResourceLink(Properties.Resources.ModInfoBugTrackerLabel, res.bugtracker);
                    AddResourceLink(Properties.Resources.ModInfoContinuousIntegrationLabel, res.ci);
                    AddResourceLink(Properties.Resources.ModInfoLicenseLabel, res.license);
                    AddResourceLink(Properties.Resources.ModInfoManualLabel, res.manual);
                    AddResourceLink(Properties.Resources.ModInfoMetanetkanLabel, res.metanetkan);
                    AddResourceLink(Properties.Resources.ModInfoRemoteAvcLabel, res.remoteAvc);
                    AddResourceLink(Properties.Resources.ModInfoStoreLabel, res.store);
                    AddResourceLink(Properties.Resources.ModInfoSteamStoreLabel, res.steamstore);
                }
            });
        }
Esempio n. 6
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);

            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, 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;
                    }
                }
            }
        }
Esempio n. 7
0
        private static CkanModule ProcessRegistryMetadataFromJSON(string metadata, string filename)
        {
            log.DebugFormat("Converting metadata from JSON.");

            try
            {
                CkanModule module = CkanModule.FromJson(metadata);
                // FromJson can return null for the empty string
                if (module != null)
                {
                    log.DebugFormat("Found {0} version {1}", module.identifier, module.version);
                }
                return(module);
            }
            catch (Exception exception)
            {
                // Alas, we can get exceptions which *wrap* our exceptions,
                // because json.net seems to enjoy wrapping rather than propagating.
                // See KSP-CKAN/CKAN-meta#182 as to why we need to walk the whole
                // exception stack.

                bool handled = false;

                while (exception != null)
                {
                    if (exception is UnsupportedKraken || exception is BadMetadataKraken)
                    {
                        // Either of these can be caused by data meant for future
                        // clients, so they're not really warnings, they're just
                        // informational.

                        log.InfoFormat("Skipping {0} : {1}", filename, exception.Message);

                        // I'd *love a way to "return" from the catch block.
                        handled = true;
                        break;
                    }

                    // Look further down the stack.
                    exception = exception.InnerException;
                }

                // If we haven't handled our exception, then it really was exceptional.
                if (handled == false)
                {
                    if (exception == null)
                    {
                        // Had exception, walked exception tree, reached leaf, got stuck.
                        log.ErrorFormat("Error processing {0} (exception tree leaf)", filename);
                    }
                    else
                    {
                        // In case whatever's calling us is lazy in error reporting, we'll
                        // report that we've got an issue here.
                        log.ErrorFormat("Error processing {0} : {1}", filename, exception.Message);
                    }

                    throw;
                }
                return(null);
            }
        }
Esempio n. 8
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>
        public void InstallList(ICollection <CkanModule> modules, RelationshipResolverOptions options, IDownloader downloader = null)
        {
            // TODO: Break this up into smaller pieces! It's huge!
            var resolver                = new RelationshipResolver(modules, options, registry_manager.registry, ksp.VersionCriteria());
            var modsToInstall           = resolver.ModList().ToList();
            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...\r\n");

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

            bool ok = User.RaiseYesNoDialog("\r\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 NetAsyncModulesDownloader(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("Committing 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!\r\n", 100);
        }
Esempio n. 9
0
 /// <summary>
 /// Removes the given module from the registry of available modules.
 /// Does *nothing* if the module was not present to begin with.</summary>
 public void RemoveAvailable(CkanModule module)
 {
     RemoveAvailable(module.identifier, module.version);
 }
Esempio n. 10
0
        /// <summary>
        /// Create a CkanModule object that represents the currently installed
        /// mod list as a metapackage.
        /// </summary>
        /// <param name="recommends">If true, put the mods in the recommends relationship, otherwise use depends</param>
        /// <param name="with_versions">If true, set the installed mod versions in the relationships</param>
        /// <returns>
        /// The CkanModule object
        /// </returns>
        public CkanModule GenerateModpack(bool recommends = false, bool with_versions = true)
        {
            string kspInstanceName = ksp.Name;
            string name            = $"installed-{kspInstanceName}";
            var    module          = new CkanModule(
                // v1.18 to allow Unlicense
                new ModuleVersion("v1.18"),
                Identifier.Sanitize(name),
                name,
                $"A list of modules installed on the {kspInstanceName} KSP instance",
                null,
                new List <string>()
            {
                System.Environment.UserName
            },
                new List <License>()
            {
                new License("unknown")
            },
                new ModuleVersion(DateTime.UtcNow.ToString("yyyy.MM.dd.hh.mm.ss")),
                null,
                "metapackage"
                )
            {
                download_content_type = "application/zip",
                release_date          = DateTime.Now,
            };

            List <RelationshipDescriptor> mods = registry.Installed(false, false)
                                                 .Where(kvp => {
                // Skip unavailable modules (custom .ckan files)
                try
                {
                    var avail = registry.LatestAvailable(kvp.Key, null, null);
                    return(!avail.IsDLC);
                }
                catch
                {
                    return(false);
                }
            })
                                                 // Case insensitive sort by identifier
                                                 .OrderBy(kvp => kvp.Key, StringComparer.OrdinalIgnoreCase)
                                                 .Select(kvp => (RelationshipDescriptor) new ModuleRelationshipDescriptor()
            {
                name    = kvp.Key,
                version = with_versions ? kvp.Value : null
            })
                                                 .ToList();

            if (recommends)
            {
                module.recommends = mods;
            }
            else
            {
                module.depends = mods;
            }

            return(module);
        }
Esempio n. 11
0
        /// <summary>
        /// Initialize a GUIMod based on just an identifier
        /// </summary>
        /// <param name="identifier">The id of the module to represent</param>
        /// <param name="registry">CKAN registry object for current game instance</param>
        /// <param name="current_ksp_version">Current game version</param>
        /// <param name="incompatible">If true, mark this module as incompatible</param>
        public GUIMod(string identifier, IRegistryQuerier registry, KspVersionCriteria current_ksp_version, bool incompatible = false)
        {
            Identifier     = identifier;
            IsIncompatible = incompatible;
            IsAutodetected = registry.IsAutodetected(identifier);
            DownloadCount  = registry.DownloadCount(identifier);
            if (registry.IsAutodetected(identifier))
            {
                IsInstalled = true;
            }

            ModuleVersion latest_version = null;

            try
            {
                latest_version = registry.LatestAvailable(identifier, current_ksp_version)?.version;
            }
            catch (ModuleNotFoundKraken)
            {
            }

            // Let's try to find the compatibility for this mod. If it's not in the registry at
            // all (because it's a DarkKAN mod) then this might fail.

            CkanModule latest_available_for_any_ksp = null;

            try
            {
                latest_available_for_any_ksp = registry.LatestAvailable(identifier, null);
            }
            catch
            { }

            // If there's known information for this mod in any form, calculate the highest compatible
            // KSP.
            if (latest_available_for_any_ksp != null)
            {
                KSPCompatibility = registry.LatestCompatibleKSP(identifier)?.ToYalovString()
                                   ?? "Unknown";
                KSPCompatibilityLong = $"{KSPCompatibility} (using mod version {latest_available_for_any_ksp.version})";
            }
            else
            {
                // No idea what this mod is, sorry!
                KSPCompatibility = KSPCompatibilityLong = "unknown";
            }

            if (latest_version != null)
            {
                LatestVersion = latest_version.ToString();
            }
            else if (latest_available_for_any_ksp != null)
            {
                LatestVersion = latest_available_for_any_ksp.version.ToString();
            }
            else
            {
                LatestVersion = "-";
            }

            // If we have a homepage provided, use that; otherwise use the spacedock page, curse page or the github repo so that users have somewhere to get more info than just the abstract.
            Homepage = "N/A";

            SearchableIdentifier = CkanModule.nonAlphaNums.Replace(Identifier, "");
        }
Esempio n. 12
0
        public void LoadProviders(string message, List <CkanModule> modules, NetModuleCache cache)
        {
            Util.Invoke(this, () =>
            {
                ChooseProvidedModsLabel.Text = message;

                ChooseProvidedModsListView.Items.Clear();
                ChooseProvidedModsListView.Items.AddRange(modules
                                                          .Select(module => new ListViewItem(new string[]
                {
                    cache.IsMaybeCachedZip(module)
                            ? string.Format(Properties.Resources.MainChangesetCached, module.name, module.version)
                            : string.Format(Properties.Resources.MainChangesetHostSize, module.name, module.version, module.download.Host ?? "", CkanModule.FmtSize(module.download_size)),
                    module.@abstract
                })
                {
                    Tag     = module,
                    Checked = false
                })
                                                          .ToArray());
                ChooseProvidedModsListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
                ChooseProvidedModsContinueButton.Enabled = false;
            });
        }
Esempio n. 13
0
        /// <summary>
        /// This function returns a changeset based on the selections of the user.
        /// Currently returns null if a conflict is detected.
        /// </summary>
        /// <param name="registry"></param>
        /// <param name="changeSet"></param>
        /// <param name="installer">A module installer for the current KSP install</param>
        /// <param name="version">The version of the current KSP install</param>
        public async Task <IEnumerable <ModChange> > ComputeChangeSetFromModList(
            IRegistryQuerier registry, HashSet <ModChange> changeSet, ModuleInstaller installer,
            KspVersionCriteria version)
        {
            var modules_to_install = new HashSet <CkanModule>();
            var modules_to_remove  = new HashSet <CkanModule>();

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

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

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

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

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

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

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

            bool handled_all_too_many_provides = false;

            while (!handled_all_too_many_provides)
            {
                //Can't await in catch clause - doesn't seem to work in mono. Hence this flag
                TooManyModsProvideKraken kraken;
                try
                {
                    new RelationshipResolver(
                        modules_to_install,
                        modules_to_remove,
                        RelationshipResolver.DependsOnlyOpts(),
                        registry, version);
                    handled_all_too_many_provides = true;
                    continue;
                }
                catch (TooManyModsProvideKraken k)
                {
                    kraken = k;
                }
                //Shouldn't get here unless there is a kraken.
                var mod = await too_many_provides(kraken);

                if (mod != null)
                {
                    modules_to_install.Add(mod);
                }
                else
                {
                    //TODO Is could be a new type of Kraken.
                    throw kraken;
                }
            }

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

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

            return(changeSet);
        }
Esempio n. 14
0
        public static Dictionary <GUIMod, string> ComputeConflictsFromModList(IRegistryQuerier registry,
                                                                              IEnumerable <ModChange> change_set, KspVersionCriteria ksp_version)
        {
            var modules_to_install = new HashSet <string>();
            var modules_to_remove  = new HashSet <string>();
            var options            = new RelationshipResolverOptions
            {
                without_toomanyprovides_kraken = true,
                proceed_with_inconsistencies   = true,
                without_enforce_consistency    = true,
                with_recommends = false
            };

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

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

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

                case GUIModChangeType.Update:
                    break;

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

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            // Only check mods that would exist after the changes are made.
            IEnumerable <CkanModule> installed = registry.InstalledModules.Where(
                im => !modules_to_remove.Contains(im.Module.identifier)
                ).Select(im => im.Module);

            // Convert ONLY modules_to_install with CkanModule.FromIDandVersion,
            // because it may not find already-installed modules.
            IEnumerable <CkanModule> mods_to_check = installed.Union(
                modules_to_install.Except(modules_to_remove).Select(
                    name => CkanModule.FromIDandVersion(registry, name, ksp_version)
                    )
                );
            var resolver = new RelationshipResolver(
                mods_to_check,
                change_set.Where(ch => ch.ChangeType == GUIModChangeType.Remove)
                .Select(ch => ch.Mod.ToModule()),
                options, registry, ksp_version
                );

            return(resolver.ConflictList.ToDictionary(item => new GUIMod(item.Key, registry, ksp_version),
                                                      item => item.Value));
        }
Esempio n. 15
0
 public InvalidModuleAttributesException(string why, CkanModule module = null)
     : base(why)
 {
     this.why    = why;
     this.module = module;
 }
Esempio n. 16
0
 public void UpdateModContentsTree(CkanModule module, bool force = false)
 {
     ModInfo.UpdateModContentsTree(module, force);
 }
Esempio n. 17
0
 /// <summary>
 /// Returns the path to a cached copy of a module if it exists, or downloads
 /// and returns the downloaded copy otherwise.
 ///
 /// If no filename is provided, the module's standard name will be used.
 /// Chcecks the CKAN cache first.
 /// </summary>
 public string CachedOrDownload(CkanModule module, string filename = null)
 {
     return(CachedOrDownload(module, Cache, filename));
 }
Esempio n. 18
0
        private void DeSerialisationFixes(StreamingContext context)
        {
            // Our context is our KSP install.
            KSP ksp = (KSP)context.Context;


            // Older registries didn't have the installed_files list, so we create one
            // if absent.

            if (installed_files == null)
            {
                log.Warn("Older registry format detected, adding installed files manifest...");
                ReindexInstalled();
            }

            // If we have no registry version at all, then we're from the pre-release period.
            // We would check for a null here, but ints *can't* be null.
            if (registry_version == 0)
            {
                log.Warn("Older registry format detected, normalising paths...");

                var normalised_installed_files = new Dictionary <string, string>();

                foreach (KeyValuePair <string, string> tuple in installed_files)
                {
                    string path = KSPPathUtils.NormalizePath(tuple.Key);

                    if (Path.IsPathRooted(path))
                    {
                        path = ksp.ToRelativeGameDir(path);
                        normalised_installed_files[path] = tuple.Value;
                    }
                    else
                    {
                        // Already relative.
                        normalised_installed_files[path] = tuple.Value;
                    }
                }

                installed_files = normalised_installed_files;

                // Now update all our module file manifests.

                foreach (InstalledModule module in installed_modules.Values)
                {
                    module.Renormalise(ksp);
                }

                // Our installed dlls have contained relative paths since forever,
                // and the next `ckan scan` will fix them anyway. (We can't scan here,
                // because that needs a registry, and we chicken-egg.)

                log.Warn("Registry upgrade complete");
            }

            // Fix control lock, which previously was indexed with an invalid identifier.
            if (registry_version < 2)
            {
                InstalledModule control_lock_entry;
                const string    old_ident = "001ControlLock";
                const string    new_ident = "ControlLock";

                if (installed_modules.TryGetValue("001ControlLock", out control_lock_entry))
                {
                    if (ksp == null)
                    {
                        throw new Kraken("Internal bug: No KSP instance provided on registry deserialisation");
                    }

                    log.WarnFormat("Older registry detected. Reindexing {0} as {1}. This may take a moment.", old_ident, new_ident);

                    // Remove old record.
                    installed_modules.Remove(old_ident);

                    // Extract the old module metadata
                    CkanModule control_lock_mod = control_lock_entry.Module;

                    // Change to the correct ident.
                    control_lock_mod.identifier = new_ident;

                    // Prepare to re-index.
                    var new_control_lock_installed = new InstalledModule(
                        ksp,
                        control_lock_mod,
                        control_lock_entry.Files
                        );

                    // Re-insert into registry.
                    installed_modules[new_control_lock_installed.identifier] = new_control_lock_installed;

                    // Re-index files.
                    ReindexInstalled();
                }
            }

            // If we spot a default repo with the old .zip URL, flip it to the new .tar.gz URL
            // Any other repo we leave *as-is*, even if it's the github meta-repo, as it's been
            // custom-added by our user.

            Repository default_repo;
            var        oldDefaultRepo = new Uri("https://github.com/KSP-CKAN/CKAN-meta/archive/master.zip");

            if (repositories != null && repositories.TryGetValue(Repository.default_ckan_repo_name, out default_repo) && default_repo.uri == oldDefaultRepo)
            {
                log.InfoFormat("Updating default metadata URL from {0} to {1}", oldDefaultRepo, Repository.default_ckan_repo_uri);
                repositories["default"].uri = Repository.default_ckan_repo_uri;
            }

            registry_version = LATEST_REGISTRY_VERSION;
        }
Esempio n. 19
0
 /// <summary>
 /// Downloads the given mod to the cache. Returns the filename it was saved to.
 /// </summary>
 public string Download(CkanModule module, string filename)
 {
     User.RaiseProgress(String.Format("Downloading \"{0}\"", module.download), 0);
     return(Download(module, filename, Cache));
 }
Esempio n. 20
0
        private string SerializeCurrentInstall(bool recommends = false, bool with_versions = true)
        {
            var pack = GenerateModpack(recommends, with_versions);

            return(CkanModule.ToJson(pack));
        }
Esempio n. 21
0
 private void OnModInstalled(CkanModule mod)
 {
     AddStatusMessage(string.Format(Properties.Resources.MainInstallModSuccess, mod.name));
     LabelsAfterInstall(mod);
 }
Esempio n. 22
0
        private void UpdateProvidedModsDialog(TooManyModsProvideKraken tooManyProvides, TaskCompletionSource <CkanModule> task)
        {
            toomany_source = task;
            ChooseProvidedModsLabel.Text = String.Format(
                Properties.Resources.MainInstallProvidedBy,
                tooManyProvides.requested
                );

            ChooseProvidedModsListView.Items.Clear();

            ChooseProvidedModsListView.ItemChecked += ChooseProvidedModsListView_ItemChecked;

            foreach (CkanModule module in tooManyProvides.modules)
            {
                ListViewItem item = new ListViewItem()
                {
                    Tag     = module,
                    Checked = false,
                    Text    = Manager.Cache.IsMaybeCachedZip(module)
                        ? string.Format(Properties.Resources.MainChangesetCached, module.name, module.version)
                        : string.Format(Properties.Resources.MainChangesetHostSize, module.name, module.version, module.download.Host ?? "", CkanModule.FmtSize(module.download_size))
                };
                ListViewItem.ListViewSubItem description = new ListViewItem.ListViewSubItem()
                {
                    Text = module.@abstract
                };

                item.SubItems.Add(description);
                ChooseProvidedModsListView.Items.Add(item);
            }
            ChooseProvidedModsListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            ChooseProvidedModsContinueButton.Enabled = false;
        }
Esempio n. 23
0
 private void OnModInstalled(CkanModule mod)
 {
     AddStatusMessage("Module \"{0}\" successfully installed", mod.name);
 }
Esempio n. 24
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(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.
            tabController.RenameTab("WaitTabPage", Properties.Resources.MainInstallWaitTitle);
            ShowWaitDialog();
            tabController.SetTabLock(true);

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

            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.Select(m => m.identifier));
                            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, 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
                    CkanModule chosen = TooManyModsProvideCore(k);
                    // Close the selection prompt
                    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;
                    }
                }
                catch (DependencyNotSatisfiedKraken ex)
                {
                    currentUser.RaiseMessage(Properties.Resources.MainInstallDepNotSatisfied, ex.parent, ex.module);
                    return;
                }
                catch (ModuleNotFoundKraken ex)
                {
                    currentUser.RaiseMessage(Properties.Resources.MainInstallNotFound, ex.module);
                    return;
                }
                catch (BadMetadataKraken ex)
                {
                    currentUser.RaiseMessage(Properties.Resources.MainInstallBadMetadata, ex.module, ex.Message);
                    return;
                }
                catch (FileExistsKraken ex)
                {
                    if (ex.owningModule != null)
                    {
                        currentUser.RaiseMessage(
                            Properties.Resources.MainInstallFileExists,
                            ex.filename, ex.installingModule, ex.owningModule,
                            Meta.GetVersion()
                            );
                    }
                    else
                    {
                        currentUser.RaiseMessage(
                            Properties.Resources.MainInstallUnownedFileExists,
                            ex.installingModule, ex.filename
                            );
                    }
                    currentUser.RaiseMessage(Properties.Resources.MainInstallGameDataReverted);
                    return;
                }
                catch (InconsistentKraken ex)
                {
                    // The prettiest Kraken formats itself for us.
                    currentUser.RaiseMessage(ex.InconsistenciesPretty);
                    return;
                }
                catch (CancelledActionKraken)
                {
                    return;
                }
                catch (MissingCertificateKraken kraken)
                {
                    // Another very pretty kraken.
                    currentUser.RaiseMessage(kraken.ToString());
                    return;
                }
                catch (DownloadThrottledKraken kraken)
                {
                    string msg = kraken.ToString();
                    currentUser.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)
                        {
                            Utilities.ProcessStartURL(kraken.infoUrl.ToString());
                        }
                        // Now pretend they clicked the menu option for the settings
                        Enabled = false;
                        new SettingsDialog(currentUser).ShowDialog();
                        Enabled = true;
                    }
                    return;
                }
                catch (ModuleDownloadErrorsKraken kraken)
                {
                    currentUser.RaiseMessage(kraken.ToString());
                    currentUser.RaiseError(kraken.ToString());
                    return;
                }
                catch (DirectoryNotFoundKraken kraken)
                {
                    currentUser.RaiseMessage("\r\n{0}", kraken.Message);
                    return;
                }
                catch (DllNotFoundException)
                {
                    if (currentUser.RaiseYesNoDialog(Properties.Resources.MainInstallLibCurlMissing))
                    {
                        Utilities.ProcessStartURL("https://github.com/KSP-CKAN/CKAN/wiki/libcurl");
                    }
                    throw;
                }
            }
        }
Esempio n. 25
0
        private TreeNode UpdateModDependencyGraphRecursively(TreeNode parentNode, CkanModule module, RelationshipType relationship, int depth, bool virtualProvides = false)
        {
            if (module == null ||
                (depth > 0 && dependencyGraphRootModule == module) ||
                (alreadyVisited.Contains(module)))
            {
                return(null);
            }

            alreadyVisited.Add(module);

            string nodeText = module.name;

            if (virtualProvides)
            {
                nodeText = String.Format("provided by - {0}", module.name);
            }

            var node = parentNode == null ? new TreeNode(nodeText) : parentNode.Nodes.Add(nodeText);

            node.Name = module.name;

            IEnumerable <RelationshipDescriptor> relationships = null;

            switch (relationship)
            {
            case RelationshipType.Depends:
                relationships = module.depends;
                break;

            case RelationshipType.Recommends:
                relationships = module.recommends;
                break;

            case RelationshipType.Suggests:
                relationships = module.suggests;
                break;

            case RelationshipType.Supports:
                relationships = module.supports;
                break;

            case RelationshipType.Conflicts:
                relationships = module.conflicts;
                break;
            }

            if (relationships == null)
            {
                return(node);
            }

            foreach (RelationshipDescriptor dependency in relationships)
            {
                IRegistryQuerier registry = RegistryManager.Instance(manager.CurrentInstance).registry;

                try
                {
                    try
                    {
                        var dependencyModule = registry.LatestAvailable
                                                   (dependency.name, manager.CurrentInstance.Version());
                        UpdateModDependencyGraphRecursively(node, dependencyModule, relationship, depth + 1);
                    }
                    catch (ModuleNotFoundKraken)
                    {
                        List <CkanModule> dependencyModules = registry.LatestAvailableWithProvides
                                                                  (dependency.name, manager.CurrentInstance.Version());

                        if (dependencyModules == null)
                        {
                            continue;
                        }

                        var newNode = node.Nodes.Add(dependency.name + " (virtual)");
                        newNode.ForeColor = Color.Gray;

                        foreach (var dep in dependencyModules)
                        {
                            UpdateModDependencyGraphRecursively(newNode, dep, relationship, depth + 1, true);
                        }
                    }
                }
                catch (Exception)
                {
                }
            }

            if (virtualProvides)
            {
                node.Collapse(true);
            }
            else
            {
                node.ExpandAll();
            }

            return(node);
        }
Esempio n. 26
0
 public BadMetadataKraken(CkanModule module, string reason = null, Exception innerException = null)
     : base(reason, innerException)
 {
     this.module = module;
 }
Esempio n. 27
0
 public bool IsCached(CkanModule m, out string outFilename)
 {
     return(cache.IsCached(m.download, out outFilename));
 }
Esempio n. 28
0
 /// <summary>
 /// Release the kraken
 /// </summary>
 /// <param name="module">Module to check against path</param>
 /// <param name="Path">Path to the file to check against module</param>
 /// <param name="reason">Human-readable description of the problem</param>
 public InvalidModuleFileKraken(CkanModule module, string path, string reason = null)
     : base(reason)
 {
     this.module = module;
     this.path   = path;
 }
Esempio n. 29
0
 public ModuleIsDLCKraken(CkanModule module, string reason = null)
     : base(reason)
 {
     this.module = module;
 }
Esempio n. 30
0
 public abstract bool WithinBounds(CkanModule otherModule);