public override List <CkanModule> LatestAvailableWithProvides( IRegistryQuerier registry, GameVersionCriteria crit, IEnumerable <CkanModule> installed = null, IEnumerable <CkanModule> toInstall = null ) { return(registry.LatestAvailableWithProvides(name, crit, this, installed, toInstall)); }
private TreeNode findDependencyShallow(IRegistryQuerier registry, string identifier, RelationshipType relationship, KspVersionCriteria crit) { try { CkanModule dependencyModule = registry.LatestAvailable(identifier, crit); if (dependencyModule != null) { return(indexedNode(registry, dependencyModule, relationship, crit != null)); } } catch (ModuleNotFoundKraken) { // Maybe it's a DLC? ModuleVersion installedVersion = registry.InstalledVersion(identifier, false); if (installedVersion != null) { return(nonModuleNode(identifier, installedVersion, relationship)); } // If we don't find a module by this name, look for other modules that provide it. List <CkanModule> dependencyModules = registry.LatestAvailableWithProvides(identifier, crit); if (dependencyModules != null && dependencyModules.Count > 0) { List <TreeNode> children = new List <TreeNode>(); foreach (CkanModule dep in dependencyModules) { children.Add(indexedNode(registry, dep, relationship, crit != null)); } return(providesNode(identifier, relationship, children)); } } return(null); }
private TreeNode findDependencyShallow(IRegistryQuerier registry, string identifier, RelationshipType relationship, KspVersionCriteria crit) { // Maybe it's a DLC? ModuleVersion installedVersion = registry.InstalledVersion(identifier, false); if (installedVersion != null) { return(nonModuleNode(identifier, installedVersion, relationship)); } // Find modules that satisfy this dependency List <CkanModule> dependencyModules = registry.LatestAvailableWithProvides(identifier, crit); if (dependencyModules.Count == 0) { // Nothing found, don't return a node return(null); } else if (dependencyModules.Count == 1 && dependencyModules[0].identifier == identifier) { // Only one exact match module, return a simple node return(indexedNode(registry, dependencyModules[0], relationship, crit != null)); } else { // Several found or not same id, return a "provides" node return(providesNode(identifier, relationship, dependencyModules.Select(dep => indexedNode(registry, dep, relationship, crit != null)) )); } }
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.VersionCriteria()) != null && !registry.IsInstalled(mod.name) && !toInstall.Any(m => m.identifier == 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); } } catch (ModuleNotFoundKraken) { List <CkanModule> providers = registry.LatestAvailableWithProvides( mod.name, CurrentInstance.VersionCriteria(), mod ); 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. if (!chooseAble.ContainsKey(provider.identifier)) { // Add a new entry if this provider isn't listed yet. chooseAble.Add(provider.identifier, new List <string>()); } // Add the dependent mod to the list of reasons this dependency is shown. chooseAble[provider.identifier].Add(identifier); } } } catch (Kraken) { } } }
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 }); } } } } }
/// <summary> /// Resolve a relationship stanza (a list of relationships). /// This will add modules to be installed, if required. /// May recurse back to Resolve for those new modules. /// /// If `soft_resolve` is true, we warn rather than throw exceptions on mods we cannot find. /// If `soft_resolve` is false (default), we throw a ModuleNotFoundKraken if we can't find a dependency. /// /// Throws a TooManyModsProvideKraken if we have too many choices and /// options.without_toomanyprovides_kraken is not set. /// /// See RelationshipResolverOptions for further adjustments that can be made. /// /// </summary> private void ResolveStanza(IEnumerable <RelationshipDescriptor> stanza, SelectionReason reason, RelationshipResolverOptions options, bool soft_resolve = false, IEnumerable <RelationshipDescriptor> old_stanza = null) { if (stanza == null) { return; } foreach (var descriptor in stanza) { string dep_name = descriptor.name; log.DebugFormat("Considering {0}", dep_name); // If we already have this dependency covered, skip. // If it's already installed, skip. if (modlist.ContainsKey(dep_name)) { var module = modlist[dep_name]; if (descriptor.version_within_bounds(module.version)) { continue; } //TODO Ideally we could check here if it can be replaced by the version we want. if (options.procede_with_inconsistencies) { conflicts.Add(new KeyValuePair <CkanModule, CkanModule>(module, reason.Parent)); conflicts.Add(new KeyValuePair <CkanModule, CkanModule>(reason.Parent, module)); continue; } throw new InconsistentKraken( string.Format( "{0} requires a version {1}. However a incompatible version, {2}, is in the resolver", dep_name, descriptor.RequiredVersion, module.version)); } if (registry.IsInstalled(dep_name)) { if (descriptor.version_within_bounds(registry.InstalledVersion(dep_name))) { continue; } var module = registry.InstalledModule(dep_name).Module; //TODO Ideally we could check here if it can be replaced by the version we want. if (options.procede_with_inconsistencies) { conflicts.Add(new KeyValuePair <CkanModule, CkanModule>(module, reason.Parent)); conflicts.Add(new KeyValuePair <CkanModule, CkanModule>(reason.Parent, module)); continue; } throw new InconsistentKraken( string.Format( "{0} requires a version {1}. However a incompatible version, {2}, is already installed", dep_name, descriptor.RequiredVersion, registry.InstalledVersion(dep_name))); } var descriptor1 = descriptor; List <CkanModule> candidates = registry.LatestAvailableWithProvides(dep_name, kspversion, descriptor) .Where(mod => descriptor1.version_within_bounds(mod.version) && MightBeInstallable(mod)).ToList(); if (candidates.Count == 0) { if (!soft_resolve) { log.ErrorFormat("Dependency on {0} found, but nothing provides it.", dep_name); throw new ModuleNotFoundKraken(dep_name); } log.InfoFormat("{0} is recommended/suggested, but nothing provides it.", dep_name); continue; } if (candidates.Count > 1) { // Oh no, too many to pick from! // TODO: It would be great if instead we picked the one with the // most recommendations. if (options.without_toomanyprovides_kraken) { continue; } // If we've got a parent stanza that has a relationship on a mod that provides what // we need, then select that. if (old_stanza != null) { List <CkanModule> provide = candidates.Where(can => old_stanza.Where(relation => can.identifier == relation.name).Any()).ToList(); if (!provide.Any() || provide.Count() > 1) { //We still have either nothing, or too my to pick from //Just throw the TMP now throw new TooManyModsProvideKraken(dep_name, candidates); } candidates[0] = provide.First(); } else { throw new TooManyModsProvideKraken(dep_name, candidates); } } CkanModule candidate = candidates[0]; // Finally, check our candidate against everything which might object // to it being installed; that's all the mods which are fixed in our // list thus far, as well as everything on the system. var fixed_mods = new HashSet <CkanModule>(modlist.Values); fixed_mods.UnionWith(installed_modules); var conflicting_mod = fixed_mods.FirstOrDefault(mod => mod.ConflictsWith(candidate)); if (conflicting_mod == null) { // Okay, looks like we want this one. Adding. Add(candidate, reason); Resolve(candidate, options, stanza); } else if (soft_resolve) { log.InfoFormat("{0} would cause conflicts, excluding it from consideration", candidate); } else { if (options.procede_with_inconsistencies) { Add(candidate, reason); conflicts.Add(new KeyValuePair <CkanModule, CkanModule>(conflicting_mod, candidate)); conflicts.Add(new KeyValuePair <CkanModule, CkanModule>(candidate, conflicting_mod)); } else { throw new InconsistentKraken(string.Format("{0} conflicts with {1}, can't install both.", conflicting_mod, candidate)); } } } }
private TreeNode UpdateModDependencyGraphRecursively(TreeNode parentNode, CfanModule 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.title; if (virtualProvides) { nodeText = String.Format("provided by - {0}", module.title); } var node = parentNode == null ? new TreeNode(nodeText) : parentNode.Nodes.Add(nodeText); node.Name = module.title; IEnumerable <ModDependency> 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 (ModDependency dependency in relationships) { IRegistryQuerier registry = RegistryManager.Instance(manager.CurrentInstance).registry; try { try { var dependencyModule = registry.LatestAvailable (dependency.modName, manager.CurrentInstance.Version()); UpdateModDependencyGraphRecursively(node, dependencyModule, relationship, depth + 1); } catch (ModuleNotFoundKraken) { List <CfanModule> dependencyModules = registry.LatestAvailableWithProvides (dependency.modName, manager.CurrentInstance.Version()); if (dependencyModules == null) { continue; } var newNode = node.Nodes.Add(dependency.modName + " (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); }