Exemple #1
0
        private TreeNode UpdateModDependencyGraphRecursively(TreeNode parentNode, CkanModule module, RelationshipType relationship, int depth, bool virtualProvides = false)
        {
            TreeNode node = null;

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

            if (depth > 0 && dependencyGraphRootModule == module)
            {
                return(node);
            }

            if (alreadyVisited.Contains(module))
            {
                return(node);
            }

            alreadyVisited.Add(module);

            if (parentNode == null)
            {
                node = new TreeNode(module.name);
            }
            else
            {
                node = parentNode.Nodes.Add(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;
            }

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

            int i = 0;

            foreach (RelationshipDescriptor dependency in relationships)
            {
                Registry registry = RegistryManager.Instance(KSPManager.CurrentInstance).registry;

                try
                {
                    CkanModule dependencyModule = null;

                    try
                    {
                        dependencyModule = registry.LatestAvailable
                                               (dependency.name.ToString(), KSPManager.CurrentInstance.Version());
                        UpdateModDependencyGraphRecursively(node, dependencyModule, relationship, depth + 1);
                    }
                    catch (ModuleNotFoundKraken)
                    {
                        List <CkanModule> dependencyModules = registry.LatestAvailableWithProvides
                                                                  (dependency.name.ToString(), KSPManager.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);
                            i++;
                        }
                    }
                }
                catch (Exception)
                {
                }
            }

            return(node);
        }
Exemple #2
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);

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

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

            foreach (RelationshipDescriptor dependency in relationships)
            {
                Registry 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);
        }
Exemple #3
0
        /// <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.
        /// </summary>
        private void ResolveStanza(IEnumerable <RelationshipDescriptor> stanza, RelationshipResolverOptions options, bool soft_resolve = false)
        {
            if (stanza == null)
            {
                return;
            }

            foreach (string dep_name in stanza.Select(dep => dep.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) || registry.IsInstalled(dep_name))
                {
                    continue;
                }

                List <CkanModule> candidates = registry.LatestAvailableWithProvides(dep_name, kspversion);

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

                    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 <Module>(modlist.Values);

                fixed_mods.UnionWith(registry.InstalledModules.Select(x => x.Module));

                foreach (Module mod in fixed_mods)
                {
                    if (mod.ConflictsWith(candidate))
                    {
                        if (soft_resolve)
                        {
                            log.InfoFormat("{0} would cause conflicts, excluding it from consideration", candidate);

                            // I want labeled loops please, so I don't have to set this to null,
                            // break, and then look at it at the end. o_O
                            candidate = null;
                            break;
                        }
                        var this_is_why_we_cant_have_nice_things = new List <string> {
                            string.Format(
                                "{0} and {1} conflict with each other, yet we require them both!",
                                candidate, mod)
                        };

                        throw new InconsistentKraken(this_is_why_we_cant_have_nice_things);
                    }
                }

                // Our candidate may have been set to null if it was vetoed by our
                // sanity check above.
                if (candidate != null)
                {
                    // Okay, looks like we want this one. Adding.
                    Add(candidate);
                    Resolve(candidate, options);
                }
            }
        }
        /// <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, Relationship reason,
                                   RelationshipResolverOptions options, bool soft_resolve = false)
        {
            if (stanza == null)
            {
                return;
            }

            foreach (string dep_name in stanza.Select(dep => dep.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) || registry.IsInstalled(dep_name))
                {
                    continue;
                }

                List <CkanModule> candidates = registry.LatestAvailableWithProvides(dep_name, kspversion);

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

                    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 <Module>(modlist.Values);
                fixed_mods.UnionWith(registry.InstalledModules.Select(x => x.Module));

                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);
                }
                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 <Module, Module>(conflicting_mod, candidate));
                        conflicts.Add(new KeyValuePair <Module, Module>(candidate, conflicting_mod));
                    }
                    else
                    {
                        throw new InconsistentKraken(string.Format("{0} conflicts with {1}, can't install both.", conflicting_mod,
                                                                   candidate));
                    }
                }
            }
        }