/// <summary> /// Attempts to convert the module_names to ckan modules via CkanModule.FromIDandVersion and then calls RelationshipResolver.ctor(IEnumerable{CkanModule}, Registry, KSPVersion)"/> /// </summary> /// <param name="module_names"></param> /// <param name="options"></param> /// <param name="registry"></param> /// <param name="kspversion"></param> public RelationshipResolver(IEnumerable<string> module_names, RelationshipResolverOptions options, IRegistryQuerier registry, KSPVersion kspversion) : this(module_names.Select(name => CkanModule.FromIDandVersion(registry, name, kspversion)).ToList(), options, registry, kspversion) { // Does nothing, just calls the other overloaded constructor }
public void Export(IRegistryQuerier registry, Stream stream) { using (var writer = new StreamWriter(stream)) { foreach (var mod in registry.InstalledModules.OrderBy(i => i.Module.name)) { writer.WriteLine(@"- **{0}** `{1} {2}`", mod.Module.name, mod.identifier, mod.Module.version); } } }
public void Export(IRegistryQuerier registry, Stream stream) { using (var writer = new StreamWriter(stream)) { writer.WriteLine(WritePattern, _delimter, "identifier", "version", "name", "abstract", "description", "author", "kind", "download", "download_size", "ksp_version", "ksp_version_min", "ksp_version_max", "license", "release_status", "repository", "homepage", "bugtracker", "kerbalstuff", "spacedock" ); foreach (var mod in registry.InstalledModules.OrderBy(i => i.Module.name)) { writer.WriteLine(WritePattern, _delimter, mod.Module.identifier, mod.Module.version, QuoteIfNecessary(mod.Module.name), QuoteIfNecessary(mod.Module.@abstract), QuoteIfNecessary(mod.Module.description), QuoteIfNecessary(string.Join(";", mod.Module.author)), QuoteIfNecessary(mod.Module.kind), WriteUri(mod.Module.download), mod.Module.download_size, mod.Module.ksp_version, mod.Module.ksp_version_min, mod.Module.ksp_version_max, mod.Module.license, mod.Module.release_status, WriteRepository(mod.Module.resources), WriteHomepage(mod.Module.resources), WriteBugtracker(mod.Module.resources), WriteKerbalStuff(mod.Module.resources), WriteSpaceDock(mod.Module.resources) ); } } }
/// <summary> /// Creates a new Relationship resolver. /// </summary> /// <param name="options"><see cref="RelationshipResolverOptions"/></param> /// <param name="registry">The registry to use</param> /// <param name="kspversion">The version of the install that the registry corresponds to</param> public RelationshipResolver(RelationshipResolverOptions options, IRegistryQuerier registry, KSPVersion kspversion) { this.registry = registry; this.kspversion = kspversion; this.options = options; installed_modules = new HashSet<Module>(registry.InstalledModules.Select(i_module => i_module.Module)); var installed_relationship = new SelectionReason.Installed(); foreach (var module in installed_modules) { reasons.Add(module, installed_relationship); } }
private async Task UpdateChangeSetAndConflicts(IRegistryQuerier registry) { IEnumerable <ModChange> full_change_set = null; Dictionary <GUIMod, string> new_conflicts = null; bool too_many_provides_thrown = false; var user_change_set = mainModList.ComputeUserChangeSet(); try { var module_installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, GUI.user); full_change_set = await mainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer, CurrentInstance.VersionCriteria()); } catch (InconsistentKraken k) { // Need to be recomputed due to ComputeChangeSetFromModList possibly changing it with too many provides handling. AddStatusMessage(k.ShortDescription); user_change_set = mainModList.ComputeUserChangeSet(); new_conflicts = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.VersionCriteria()); full_change_set = null; } catch (TooManyModsProvideKraken) { // Can be thrown by ComputeChangeSetFromModList if the user cancels out of it. // We can just rerun it as the ModInfoTabControl has been removed. too_many_provides_thrown = true; } catch (DependencyNotSatisfiedKraken k) { GUI.user.RaiseError( "{0} depends on {1}, which is not compatible with the currently installed version of KSP", k.parent, k.module ); // Uncheck the box MarkModForInstall(k.parent.identifier, true); } if (too_many_provides_thrown) { await UpdateChangeSetAndConflicts(registry); new_conflicts = Conflicts; full_change_set = ChangeSet; } last_mod_to_have_install_toggled.Clear(); Conflicts = new_conflicts; ChangeSet = full_change_set; }
public void Export(IRegistryQuerier registry, Stream stream) { using (var writer = new StreamWriter(stream)) { writer.WriteLine("[LIST]"); foreach (var mod in registry.InstalledModules.OrderBy(i => i.Module.identifier)) { writer.WriteLine(@"[*][B]{0}[/B] ({1} {2})", mod.Module.title, mod.identifier, mod.Module.modVersion); } writer.WriteLine("[/LIST]"); } }
private TreeNode indexedNode(IRegistryQuerier registry, CkanModule module, RelationshipType relationship, bool compatible) { int icon = (int)relationship + 1; string suffix = compatible ? "" : $" ({registry.CompatibleGameVersions(module.identifier)})"; return(new TreeNode($"{module.name} {module.version}{suffix}", icon, icon) { Name = module.identifier, ToolTipText = relationship.ToString(), Tag = module, ForeColor = compatible ? SystemColors.WindowText : Color.Red, }); }
public void Export(IRegistryQuerier registry, Stream stream) { using (var writer = new StreamWriter(stream)) { writer.WriteLine("[LIST]"); foreach (var mod in registry.InstalledModules.OrderBy(i => i.Module.name)) { writer.WriteLine(@"[*][B]{0}[/B] ({1} {2})", mod.Module.name, mod.identifier, mod.Module.version); } writer.WriteLine("[/LIST]"); } }
/// <summary> /// Initialize a GUIMod based on an InstalledModule /// </summary> /// <param name="instMod">The installed 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(InstalledModule instMod, IRegistryQuerier registry, KspVersionCriteria current_ksp_version, bool incompatible = false) : this(instMod.Module, registry, current_ksp_version, incompatible) { IsInstalled = true; IsInstallChecked = true; InstalledMod = instMod; IsAutoInstalled = instMod.AutoInstalled; InstallDate = instMod.InstallTime; InstalledVersion = instMod.Module.version.ToString(); if (LatestVersion == null || LatestVersion.Equals("-")) { LatestVersion = InstalledVersion; } }
/// <summary> /// Creates a new Relationship resolver. /// </summary> /// <param name="options">Options for the RelationshipResolver</param> /// <param name="registry">CKAN registry object for current game instance</param> /// <param name="GameVersion">The current KSP version criteria to consider</param> public RelationshipResolver(RelationshipResolverOptions options, IRegistryQuerier registry, GameVersionCriteria GameVersion) { this.registry = registry; this.GameVersion = GameVersion; this.options = options; installed_modules = new HashSet <CkanModule>(registry.InstalledModules.Select(i_module => i_module.Module)); var installed_relationship = new SelectionReason.Installed(); foreach (var module in installed_modules) { reasons.Add(module, installed_relationship); } }
// Build up the list of who recommends what private Dictionary <CkanModule, List <string> > getDependersIndex( IEnumerable <CkanModule> sourceModules, IRegistryQuerier registry, HashSet <CkanModule> toExclude ) { Dictionary <CkanModule, List <string> > dependersIndex = new Dictionary <CkanModule, List <string> >(); foreach (CkanModule mod in sourceModules) { foreach (List <RelationshipDescriptor> relations in new List <List <RelationshipDescriptor> >() { mod.recommends, mod.suggests }) { if (relations != null) { foreach (RelationshipDescriptor rel in relations) { List <CkanModule> providers = rel.LatestAvailableWithProvides( registry, CurrentInstance.VersionCriteria() ); foreach (CkanModule provider in providers) { if (!registry.IsInstalled(provider.identifier) && !toExclude.Any(m => m.identifier == provider.identifier)) { List <string> dependers; if (dependersIndex.TryGetValue(provider, out dependers)) { // Add the dependent mod to the list of reasons this dependency is shown. dependers.Add(mod.identifier); } else { // Add a new entry if this provider isn't listed yet. dependersIndex.Add(provider, new List <string>() { mod.identifier }); } } } } } } } return(dependersIndex); }
public HashSet <ModChange> ComputeUserChangeSet(IRegistryQuerier registry) { var removableAuto = registry?.FindRemovableAutoInstalled(registry?.InstalledModules) ?? new InstalledModule[] {}; return(new HashSet <ModChange>( Modules .SelectMany(mod => mod.GetModChanges()) .Union(removableAuto.Select(im => new ModChange( im.Module, GUIModChangeType.Remove, new SelectionReason.NoLongerUsed()))) )); }
public static Dictionary <GUIMod, string> ComputeConflictsFromModList(IRegistryQuerier registry, IEnumerable <ModChange> change_set, FactorioVersion ksp_version) { var modules_to_install = new HashSet <string>(); var modules_to_remove = new HashSet <string>(); var options = new RelationshipResolverOptions { without_toomanyprovides_kraken = true, procede_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; default: throw new ArgumentOutOfRangeException(); } } var installed = registry.Installed() .Where(pair => pair.Value.CompareTo(new ProvidedVersion("", "0.0.0")) != 0) .Select(pair => pair.Key); //We wish to only check mods that would exist after the changes are made. var mods_to_check = installed.Union(modules_to_install).Except(modules_to_remove).Select(p => new CfanModuleIdAndVersion(p)); var resolver = new RelationshipResolver(mods_to_check.ToList(), options, registry, ksp_version); return(resolver.ConflictList.ToDictionary(item => new GUIMod(item.Key, registry, ksp_version), item => item.Value)); }
private void reinstallToolStripMenuItem_Click(object sender, EventArgs e) { GUIMod module = ModInfoTabControl.SelectedModule; if (module == null || !module.IsCKAN) { return; } YesNoDialog reinstallDialog = new YesNoDialog(); string confirmationText = $"Do you want to reinstall {module.Name}?"; if (reinstallDialog.ShowYesNoDialog(confirmationText) == DialogResult.No) { return; } IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry; KspVersionCriteria versCrit = CurrentInstance.VersionCriteria(); // Build the list of changes, first the mod to remove: List <ModChange> toReinstall = new List <ModChange>() { new ModChange(module, GUIModChangeType.Remove, null) }; // Then everything we need to re-install: HashSet <string> goners = registry.FindReverseDependencies( new List <string>() { module.Identifier } ); foreach (string id in goners) { toReinstall.Add(new ModChange( mainModList.full_list_of_mod_rows[id]?.Tag as GUIMod, GUIModChangeType.Install, null )); } // Hand off to centralized [un]installer code installWorker.RunWorkerAsync( new KeyValuePair <List <ModChange>, RelationshipResolverOptions>( toReinstall, RelationshipResolver.DefaultOpts() ) ); }
/// <summary> /// Initiate the GUI installer flow for one specific module /// </summary> /// <param name="registry">Reference to the registry</param> /// <param name="module">Module to install</param> public async void InstallModuleDriver(IRegistryQuerier registry, CkanModule module) { RelationshipResolverOptions install_ops = RelationshipResolver.DefaultOpts(); install_ops.with_recommends = false; try { // Resolve the provides relationships in the dependencies List <ModChange> fullChangeSet = new List <ModChange>( await mainModList.ComputeChangeSetFromModList( registry, new HashSet <ModChange>() { new ModChange( new GUIMod( module, registry, CurrentInstance.VersionCriteria() ), GUIModChangeType.Install, null ) }, ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, GUI.user), CurrentInstance.VersionCriteria() ) ); if (fullChangeSet != null && fullChangeSet.Count > 0) { installWorker.RunWorkerAsync( new KeyValuePair <List <ModChange>, RelationshipResolverOptions>( fullChangeSet, install_ops ) ); } } catch { // If we failed, do the clean-up normally done by PostInstallMods. HideWaitDialog(false); menuStrip1.Enabled = true; } finally { changeSet = null; } }
private IEnumerable <ModuleReplacement> AllReplacements(IEnumerable <string> identifiers) { IRegistryQuerier registry = RegistryManager.Instance(manager.CurrentInstance).registry; foreach (string id in identifiers) { ModuleReplacement repl = registry.GetReplacement( id, manager.CurrentInstance.VersionCriteria() ); if (repl != null) { yield return(repl); } } }
/// <summary> /// Is the mod installed and does it have a replaced_by relationship with a compatible version /// Check latest information on installed version of mod "identifier" and if it has a "replaced_by" /// value, check if there is a compatible version of the linked mod /// Given a mod identifier, return a ModuleReplacement containing the relevant replacement /// if compatibility matches. /// </summary> public static ModuleReplacement GetReplacement(this IRegistryQuerier querier, string identifier, KspVersionCriteria version) { // We only care about the installed version CkanModule installedVersion; try { installedVersion = querier.GetInstalledVersion(identifier); } catch (ModuleNotFoundKraken) { return(null); } return(querier.GetReplacement(installedVersion, version)); }
private bool allowInstall(CkanModule module) { GameInstance currentInstance = Main.Instance.Manager.CurrentInstance; IRegistryQuerier registry = RegistryManager.Instance(currentInstance).registry; var installer = new ModuleInstaller( currentInstance, Main.Instance.Manager.Cache, Main.Instance.currentUser); return(installable(installer, module, registry) || Main.Instance.YesNoDialog( string.Format(Properties.Resources.AllModVersionsInstallPrompt, module.ToString()), Properties.Resources.AllModVersionsInstallYes, Properties.Resources.AllModVersionsInstallNo)); }
private void UpdateRepo(object sender, DoWorkEventArgs e) { try { AddStatusMessage(Properties.Resources.MainRepoScanning); log.Debug("Scanning before repo update"); bool scanChanged = CurrentInstance.Scan(); AddStatusMessage(Properties.Resources.MainRepoUpdating); // Note the current mods' compatibility for the NewlyCompatible filter GameVersionCriteria versionCriteria = CurrentInstance.VersionCriteria(); IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry; Dictionary <string, bool> oldModules = registry.CompatibleModules(versionCriteria) .ToDictionary(m => m.identifier, m => false); registry.IncompatibleModules(versionCriteria) .Where(m => !oldModules.ContainsKey(m.identifier)) .ToList() .ForEach(m => oldModules.Add(m.identifier, true)); RepoUpdateResult result = Repo.UpdateAllRepositories( RegistryManager.Instance(CurrentInstance), CurrentInstance, Manager.Cache, currentUser); if (result == RepoUpdateResult.NoChanges && scanChanged) { result = RepoUpdateResult.Updated; } e.Result = new KeyValuePair <RepoUpdateResult, Dictionary <string, bool> >( result, oldModules); } catch (UriFormatException ex) { errorDialog.ShowErrorDialog(ex.Message); } catch (MissingCertificateKraken ex) { errorDialog.ShowErrorDialog(ex.ToString()); } catch (ReinstallModuleKraken) { // Bypass the generic error dialog so the Post can handle this throw; } catch (Exception ex) { errorDialog.ShowErrorDialog(string.Format(Properties.Resources.MainRepoFailedToConnect, ex.Message)); } }
private void _CheckForConsistency() { IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry; try { registry.CheckSanity(); } catch (InconsistentKraken e) { m_User.displayError( "Installed mods has unmet dependencies. \"Apply changes\" button will be unavailable until you fix inconsistencies:\n{0}", new object[] { e.InconsistenciesPretty } ); } }
private static List <CfanModule> getModulesFromRegistry( IEnumerable <CfanModuleIdAndVersion> module_names, IRegistryQuerier registry, FactorioVersion kspversion) { return(module_names.Select( p => { var mod = p.version != null ? registry.GetModuleByVersion(p.identifier, p.version) : registry.LatestAvailable(p.identifier, kspversion); if (mod == null) { throw new ModuleNotFoundKraken(p.identifier, p.version?.ToString(), "Module not found."); } return mod; }).ToList()); }
public int RunCommand(CKAN.KSP ksp, object raw_options) { IRegistryQuerier registry = RegistryManager.Instance(ksp).registry; List <CkanModule> available = registry.Available(ksp.VersionCriteria()); user.RaiseMessage("Mods available for KSP {0}", ksp.Version()); user.RaiseMessage(""); foreach (CkanModule module in available) { user.RaiseMessage("* {0} ({1}) - {2}", module.identifier, module.version, module.name); } return(Exit.OK); }
public void LoadRecommendations( IRegistryQuerier registry, KspVersionCriteria kspVersion, NetModuleCache cache, Dictionary <CkanModule, Tuple <bool, List <string> > > recommendations, Dictionary <CkanModule, List <string> > suggestions, Dictionary <CkanModule, HashSet <string> > supporters ) { this.registry = registry; this.kspVersion = kspVersion; Util.Invoke(this, () => { RecommendedModsToggleCheckbox.Checked = true; RecommendedModsListView.Items.Clear(); RecommendedModsListView.Items.AddRange( getRecSugRows(cache, recommendations, suggestions, supporters).ToArray()); }); }
/// <summary> /// Initialize a GUIMod based on an InstalledModule /// </summary> /// <param name="instMod">The installed module to represent</param> /// <param name="registry">CKAN registry object for current game instance</param> /// <param name="current_game_version">Current game version</param> /// <param name="incompatible">If true, mark this module as incompatible</param> public GUIMod(InstalledModule instMod, IRegistryQuerier registry, GameVersionCriteria current_game_version, bool?incompatible = null) : this(instMod.Module, registry, current_game_version, incompatible) { IsInstalled = true; IsInstallChecked = true; InstalledMod = instMod; selectedMod = instMod.Module; IsAutoInstalled = instMod.AutoInstalled; InstallDate = instMod.InstallTime; InstalledVersion = instMod.Module.version.ToString(); if (LatestVersion == null || LatestVersion.Equals("-")) { LatestVersion = InstalledVersion; } // For mods not known to the registry LatestCompatibleMod is null, however the installed module might be compatible IsIncompatible = incompatible ?? LatestCompatibleMod == null && !instMod.Module.IsCompatibleKSP(current_game_version); }
private void LoadRelationships(IRegistryQuerier registry) { if (module.depends == null) { module.depends = new List <RelationshipDescriptor>(); } if (module.recommends == null) { module.recommends = new List <RelationshipDescriptor>(); } if (module.suggests == null) { module.suggests = new List <RelationshipDescriptor>(); } ignored.Clear(); // Find installed modules that aren't in the module's relationships ignored.AddRange(registry.Installed(false, false) .Where(kvp => { var ids = new string[] { kvp.Key }; return(!module.depends.Any(rel => rel.ContainsAny(ids)) && !module.recommends.Any(rel => rel.ContainsAny(ids)) && !module.suggests.Any(rel => rel.ContainsAny(ids))); }) .Select(kvp => (RelationshipDescriptor) new ModuleRelationshipDescriptor() { name = kvp.Key, version = kvp.Value, }) ); RelationshipsListView.Items.Clear(); AddGroup(module.depends, DependsGroup, registry); AddGroup(module.recommends, RecommendationsGroup, registry); AddGroup(module.suggests, SuggestionsGroup, registry); AddGroup(ignored, IgnoredGroup, registry); RelationshipsListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); GroupToRelationships.Clear(); GroupToRelationships.Add(DependsGroup, module.depends); GroupToRelationships.Add(RecommendationsGroup, module.recommends); GroupToRelationships.Add(SuggestionsGroup, module.suggests); GroupToRelationships.Add(IgnoredGroup, ignored); RelationshipsListView_ItemSelectionChanged(null, null); }
public HashSet <ModChange> ComputeUserChangeSet(IRegistryQuerier registry) { var removableAuto = registry?.FindRemovableAutoInstalled(registry?.InstalledModules) ?? new InstalledModule[] {}; return(new HashSet <ModChange>( Modules .Where(mod => mod.IsInstallable()) .Select(mod => mod.GetRequestedChange()) .Where(change => change.HasValue) .Select(change => change.Value) .Select(change => new ModChange(change.Key, change.Value, null)) .Union(removableAuto.Select(im => new ModChange( new GUIMod(im, registry, Main.Instance.CurrentInstance.VersionCriteria()), GUIModChangeType.Remove, new SelectionReason.NoLongerUsed()))) )); }
private void _UpdateModDependencyGraph() { CkanModule module = (CkanModule)ModInfoTabControl.Tag; DependsGraphTree.BeginUpdate(); DependsGraphTree.Nodes.Clear(); IRegistryQuerier registry = RegistryManager.Instance(manager.CurrentInstance).registry; TreeNode root = new TreeNode($"{module.name} {module.version}", 0, 0) { Name = module.identifier, Tag = module }; DependsGraphTree.Nodes.Add(root); AddChildren(registry, root); root.Expand(); DependsGraphTree.EndUpdate(); }
private void _UpdateModDependencyGraph(CkanModule module) { DependsGraphTree.BeginUpdate(); DependsGraphTree.BackColor = SystemColors.Window; DependsGraphTree.LineColor = SystemColors.WindowText; DependsGraphTree.Nodes.Clear(); IRegistryQuerier registry = RegistryManager.Instance(manager.CurrentInstance).registry; TreeNode root = new TreeNode($"{module.name} {module.version}", 0, 0) { Name = module.identifier, Tag = module }; DependsGraphTree.Nodes.Add(root); AddChildren(registry, root); root.Expand(); DependsGraphTree.EndUpdate(); }
/// <summary> /// Is the mod installed and does it have a newer version compatible with version /// </summary> public static bool HasUpdate(this IRegistryQuerier querier, string identifier, KSPVersion version) { CkanModule newest_version; try { newest_version = querier.LatestAvailable(identifier, version); } catch (ModuleNotFoundKraken) { return(false); } if (newest_version == null) { return(false); } return(querier.IsInstalled(identifier) && newest_version.version.IsGreaterThan(querier.InstalledVersion(identifier))); }
/// <summary> /// Return a mod's current status /// This can't be static because the user's installation plans are part of the object. /// This function is extremely performance-sensitive because it's the default sort for /// the main mod list, so anything in here should be O(1) and fast. /// </summary> /// <param name="manager">KSP manager containing the instances</param> /// <param name="registry">Registry of instance being displayed</param> /// <param name="identifier">The mod</param> /// <returns> /// Status of mod /// </returns> public InstallStatus GetModStatus(KSPManager manager, IRegistryQuerier registry, string identifier) { if (registry.IsInstalled(identifier, false)) { if (registry.IsAutodetected(identifier)) { return(InstallStatus.AutoDetected); } else if (Remove.Contains(identifier)) { return(InstallStatus.Removing); } else if (registry.HasUpdate(identifier, manager.CurrentInstance.VersionCriteria())) { if (Upgrade.Contains(identifier)) { return(InstallStatus.Upgrading); } else { return(InstallStatus.Upgradeable); } } else if (!IsAnyAvailable(registry, identifier)) { return(InstallStatus.Unavailable); } else { return(InstallStatus.Installed); } } else { foreach (CkanModule m in Install) { if (m.identifier == identifier) { return(InstallStatus.Installing); } } return(InstallStatus.NotInstalled); } }
/// <summary> /// Tries to get every mod in the Dictionary, which can be installed /// It also transforms the Recommender list to a string /// </summary> /// <param name="mods">Map from recommendations to lists of recommenders</param> /// <param name="registry">Registry of current game instance</param> /// <param name="versionCriteria">Versions compatible with current instance</param> /// <param name="toInstall">Modules planned to be installed</param> /// <returns>Map from installable recommendations to string describing recommenders</returns> private Dictionary <CkanModule, string> GetShowableMods( Dictionary <CkanModule, List <string> > mods, IRegistryQuerier registry, KspVersionCriteria versionCriteria, HashSet <CkanModule> toInstall ) { return(mods.Where(kvp => CanInstall( registry, versionCriteria, RelationshipResolver.DependsOnlyOpts(), toInstall.ToList().Concat(new List <CkanModule>() { kvp.Key }).ToList() )).ToDictionary( kvp => kvp.Key, kvp => string.Join(", ", kvp.Value.ToArray()) )); }
/// <summary> /// Initiate the GUI installer flow for one specific module /// </summary> /// <param name="registry">Reference to the registry</param> /// <param name="module">Module to install</param> public async void InstallModuleDriver(IRegistryQuerier registry, CkanModule module) { try { var userChangeSet = new List <ModChange>(); InstalledModule installed = registry.InstalledModule(module.identifier); if (installed != null) { // Already installed, remove it first userChangeSet.Add(new ModChange( new GUIMod(installed.Module, registry, CurrentInstance.VersionCriteria()), GUIModChangeType.Remove, null )); } // Install the selected mod userChangeSet.Add(new ModChange( new GUIMod(module, registry, CurrentInstance.VersionCriteria()), GUIModChangeType.Install, null )); if (userChangeSet.Count > 0) { // Resolve the provides relationships in the dependencies installWorker.RunWorkerAsync( new KeyValuePair <List <ModChange>, RelationshipResolverOptions>( userChangeSet, RelationshipResolver.DependsOnlyOpts() ) ); } } catch { // If we failed, do the clean-up normally done by PostInstallMods. HideWaitDialog(false); menuStrip1.Enabled = true; } finally { changeSet = null; } }
/// <summary> /// Is the mod installed and does it have a newer version compatible with version /// We can't update AD mods /// </summary> public static bool HasUpdate(this IRegistryQuerier querier, string identifier, FactorioVersion version) { CfanModule newest_version; try { newest_version = querier.LatestAvailable(identifier, version); } catch (ModuleNotFoundKraken) { return(false); } if (newest_version == null) { return(false); } return(!new List <string>(querier.InstalledPreexistingModules).Contains(identifier) && querier.IsInstalled(identifier, false) && newest_version.modVersion.IsGreaterThan(querier.InstalledVersion(identifier))); }
private void UpdateRepo(object sender, DoWorkEventArgs e) { try { AddStatusMessage("Scanning GameData for DLCs and manually installed modules..."); bool scanChanged = CurrentInstance.ScanGameData(); AddStatusMessage("Updating repositories..."); // Note the current mods' compatibility for the NewlyCompatible filter KspVersionCriteria versionCriteria = CurrentInstance.VersionCriteria(); IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry; Dictionary <string, bool> oldModules = registry.Available(versionCriteria) .ToDictionary(m => m.identifier, m => false); registry.Incompatible(versionCriteria) .Where(m => !oldModules.ContainsKey(m.identifier)) .ToList() .ForEach(m => oldModules.Add(m.identifier, true)); RepoUpdateResult result = Repo.UpdateAllRepositories( RegistryManager.Instance(CurrentInstance), CurrentInstance, Manager.Cache, GUI.user); if (result == RepoUpdateResult.NoChanges && scanChanged) { result = RepoUpdateResult.Updated; } e.Result = new KeyValuePair <RepoUpdateResult, Dictionary <string, bool> >( result, oldModules); } catch (UriFormatException ex) { errorDialog.ShowErrorDialog(ex.Message); } catch (MissingCertificateKraken ex) { errorDialog.ShowErrorDialog(ex.ToString()); } catch (Exception ex) { errorDialog.ShowErrorDialog("Failed to connect to repository. Exception: " + ex.Message); } }
private void AddMod( IEnumerable <RelationshipDescriptor> relations, Dictionary <CkanModule, List <string> > chooseAble, string identifier, IRegistryQuerier registry, HashSet <CkanModule> toInstall) { if (relations == null) { return; } foreach (RelationshipDescriptor rel in relations) { List <CkanModule> providers = registry.LatestAvailableWithProvides( rel.name, CurrentInstance.VersionCriteria(), rel ); foreach (CkanModule provider in providers) { if (!registry.IsInstalled(provider.identifier) && !toInstall.Any(m => m.identifier == provider.identifier)) { // We want to show this mod to the user. Add it. List <string> dependers; if (chooseAble.TryGetValue(provider, out dependers)) { // Add the dependent mod to the list of reasons this dependency is shown. dependers.Add(identifier); } else { // Add a new entry if this provider isn't listed yet. chooseAble.Add(provider, new List <string>() { identifier }); } } } } }
public GUIMod(Module mod, IRegistryQuerier registry, KSPVersion current_ksp_version) { IsCKAN = mod is CkanModule; //Currently anything which could alter these causes a full reload of the modlist // If this is ever changed these could be moved into the properties Mod = mod; IsInstalled = registry.IsInstalled(mod.identifier, false); IsInstallChecked = IsInstalled; HasUpdate = registry.HasUpdate(mod.identifier, current_ksp_version); IsIncompatible = !mod.IsCompatibleKSP(current_ksp_version); IsAutodetected = registry.IsAutodetected(mod.identifier); Authors = mod.author == null ? "N/A" : String.Join(",", mod.author); var installed_version = registry.InstalledVersion(mod.identifier); Version latest_version = null; var ksp_version = mod.ksp_version; try { var latest_available = registry.LatestAvailable(mod.identifier, current_ksp_version); if (latest_available != null) latest_version = latest_available.version; } catch (ModuleNotFoundKraken) { latest_version = installed_version; } InstalledVersion = installed_version != null ? installed_version.ToString() : "-"; LatestVersion = latest_version != null ? latest_version.ToString() : "-"; KSPversion = ksp_version != null ? ksp_version.ToString() : "-"; Abstract = mod.@abstract; Homepage = mod.resources != null && mod.resources.homepage != null ? (object) mod.resources.homepage : "N/A"; Identifier = mod.identifier; }
/// <summary> /// Creates a new resolver that will find a way to install all the modules specified. /// </summary> public RelationshipResolver(IEnumerable<CkanModule> modules, RelationshipResolverOptions options, IRegistryQuerier registry, KSPVersion kspversion) : this(options,registry,kspversion) { AddModulesToInstall(modules); }
private async Task UpdateChangeSetAndConflicts(IRegistryQuerier registry) { IEnumerable<ModChange> full_change_set = null; Dictionary<GUIMod, string> new_conflicts = null; bool too_many_provides_thrown = false; var user_change_set = mainModList.ComputeUserChangeSet(); try { var module_installer = ModuleInstaller.GetInstance(CurrentInstance, GUI.user); full_change_set = await mainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer, CurrentInstance.VersionCriteria()); } catch (InconsistentKraken) { //Need to be recomputed due to ComputeChangeSetFromModList possibly changing it with too many provides handling. user_change_set = mainModList.ComputeUserChangeSet(); new_conflicts = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.VersionCriteria()); full_change_set = null; } catch (TooManyModsProvideKraken) { //Can be thrown by ComputeChangeSetFromModList if the user cancels out of it. //We can just rerun it as the ModInfoTabControl has been removed. too_many_provides_thrown = true; } if (too_many_provides_thrown) { await UpdateChangeSetAndConflicts(registry); new_conflicts = Conflicts; full_change_set = ChangeSet; } last_mod_to_have_install_toggled.Clear(); Conflicts = new_conflicts; ChangeSet = full_change_set; }
/// <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, KSPVersion version) { var modules_to_install = new HashSet<CkanModule>(); var modules_to_remove = new HashSet<Module>(); var options = new RelationshipResolverOptions { without_toomanyprovides_kraken = false, with_recommends = false }; foreach (var change in changeSet) { switch (change.ChangeType) { case GUIModChangeType.None: break; 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.Update: break; default: throw new ArgumentOutOfRangeException(); } } var installed_modules = registry.InstalledModules.Select(imod => imod.Module).ToDictionary(mod => mod.identifier, mod => mod); bool handled_all_to_many_provides = false; while (!handled_all_to_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.ToList(), options, registry, version); handled_all_to_many_provides = true; continue; } catch (TooManyModsProvideKraken k) { kraken = k; } catch (ModuleNotFoundKraken k) { //We shouldn't need this. However the relationship provider will throw TMPs with incompatible mods. user.RaiseError("Module {0} has not been found. This may be because it is not compatible " + "with the currently installed version of KSP", k.module); return null; } //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; } } foreach (var dependency in registry.FindReverseDependencies(modules_to_remove.Select(mod=>mod.identifier))) { //TODO This would be a good place to have a event that alters the row's graphics to show it will be removed Module 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)); } //May throw InconsistentKraken var resolver = new RelationshipResolver(options, registry, version); resolver.RemoveModsFromInstalledList( changeSet.Where(change => change.ChangeType.Equals(GUIModChangeType.Remove)).Select(m => m.Mod.ToModule())); resolver.AddModulesToInstall(modules_to_install.ToList()); changeSet.UnionWith( resolver.ModList() .Select(m => new ModChange(new GUIMod(m, registry, version), GUIModChangeType.Install, resolver.ReasonFor(m)))); return changeSet; }
public static Dictionary<GUIMod, string> ComputeConflictsFromModList(IRegistryQuerier registry, IEnumerable<ModChange> change_set, KSPVersion ksp_version) { var modules_to_install = new HashSet<string>(); var modules_to_remove = new HashSet<string>(); var options = new RelationshipResolverOptions { without_toomanyprovides_kraken = true, procede_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; default: throw new ArgumentOutOfRangeException(); } } var installed = registry.Installed() .Where(pair => pair.Value.CompareTo(new ProvidesVersion("")) != 0) .Select(pair => pair.Key); //We wish to only check mods that would exist after the changes are made. var mods_to_check = installed.Union(modules_to_install).Except(modules_to_remove); var resolver = new RelationshipResolver(mods_to_check.ToList(), options, registry, ksp_version); return resolver.ConflictList.ToDictionary(item => new GUIMod(item.Key, registry, ksp_version), item => item.Value); }
public GUIMod(CkanModule mod, IRegistryQuerier registry, KSPVersion current_ksp_version) : this((Module) mod, registry, current_ksp_version) { }
private void AddMod(IEnumerable<RelationshipDescriptor> relations, Dictionary<string, List<string>> chooseAble, string identifier, IRegistryQuerier registry) { if (relations == null) return; foreach (RelationshipDescriptor mod in relations) { 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 ( registry.LatestAvailable(mod.name, CurrentInstance.Version()) != null && !registry.IsInstalled(mod.name) && !toInstall.Contains(mod.name)) { // add it to the list of chooseAble mods we display to the user if (!chooseAble.ContainsKey(mod.name)) { chooseAble.Add(mod.name, new List<string>()); } chooseAble[mod.name].Add(identifier); } } // XXX - Don't ignore all krakens! Those things are important! catch (Kraken) { } } }
public GUIMod(CkanModule mod, IRegistryQuerier registry, KspVersionCriteria current_ksp_version) { IsCKAN = mod is CkanModule; //Currently anything which could alter these causes a full reload of the modlist // If this is ever changed these could be moved into the properties Mod = mod; IsInstalled = registry.IsInstalled(mod.identifier, false); IsInstallChecked = IsInstalled; HasUpdate = registry.HasUpdate(mod.identifier, current_ksp_version); IsIncompatible = !mod.IsCompatibleKSP(current_ksp_version); IsAutodetected = registry.IsAutodetected(mod.identifier); Authors = mod.author == null ? "N/A" : String.Join(",", mod.author); var installed_version = registry.InstalledVersion(mod.identifier); Version latest_version = null; var ksp_version = mod.ksp_version; try { var latest_available = registry.LatestAvailable(mod.identifier, current_ksp_version); if (latest_available != null) latest_version = latest_available.version; } catch (ModuleNotFoundKraken) { latest_version = installed_version; } InstalledVersion = installed_version != null ? installed_version.ToString() : "-"; // 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(mod.identifier, null); } catch { // If we can't find the mod in the CKAN, but we've a CkanModule installed, then // use that. if (IsCKAN) latest_available_for_any_ksp = (CkanModule) mod; } // If there's known information for this mod in any form, calculate the highest compatible // KSP. if (latest_available_for_any_ksp != null) { KSPCompatibility = KSPCompatibilityLong = latest_available_for_any_ksp.HighestCompatibleKSP(); // If the mod we have installed is *not* the mod we have installed, or we don't know // what we have installed, indicate that an upgrade would be needed. if (installed_version == null || !latest_available_for_any_ksp.version.IsEqualTo(installed_version)) { KSPCompatibilityLong = string.Format("{0} (using mod version {1})", KSPCompatibility, 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 = "-"; } KSPversion = ksp_version != null ? ksp_version.ToString() : "-"; Abstract = mod.@abstract; // 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"; if (mod.resources != null) { if (mod.resources.homepage != null) { Homepage = mod.resources.homepage.ToString(); } else if (mod.resources.spacedock != null) { Homepage = mod.resources.spacedock.ToString(); } else if (mod.resources.curse != null) { Homepage = mod.resources.curse.ToString(); } else if (mod.resources.repository != null) { Homepage = mod.resources.repository.ToString(); } } Identifier = mod.identifier; if (mod.download_size == 0) DownloadSize = "N/A"; else if (mod.download_size / 1024.0 < 1) DownloadSize = "1<KB"; else DownloadSize = mod.download_size / 1024+""; Abbrevation = new string(mod.name.Split(' '). Where(s => s.Length > 0).Select(s => s[0]).ToArray()); UpdateIsCached(); }
public void Export(IRegistryQuerier registry, Stream stream) { _exporter.Export(registry, stream); }