Beispiel #1
0
        /// <summary>
        /// <see cref="IRegistryQuerier.CheckSanity"/>
        /// </summary>
        public void CheckSanity()
        {
            IEnumerable <CkanModule> installed = from pair in installed_modules select pair.Value.Module;

            SanityChecker.EnforceConsistency(installed, installed_dlls.Keys, _installedDlcModules);
        }
Beispiel #2
0
        /// <summary>
        /// Add modules to consideration of the relationship resolver.
        /// </summary>
        /// <param name="modules">Modules to attempt to install</param>
        private void AddModulesToInstall(IEnumerable <CkanModule> modules)
        {
            //Count may need to do a full enumeration. Might as well convert to array
            var ckan_modules = modules as CkanModule[] ?? modules.ToArray();

            log.DebugFormat("Processing relationships for {0} modules", ckan_modules.Count());

            // Start by figuring out what versions we're installing, and then
            // adding them to the list. This *must* be pre-populated with all
            // user-specified modules, as they may be supplying things that provide
            // virtual packages.
            foreach (CkanModule module in ckan_modules)
            {
                log.DebugFormat("Preparing to resolve relationships for {0} {1}", module.identifier, module.version);

                //Need to check against installed mods and those to install.
                var mods = modlist.Values.Concat(installed_modules).Where(listed_mod => listed_mod.ConflictsWith(module));
                foreach (CkanModule listed_mod in mods)
                {
                    if (options.proceed_with_inconsistencies)
                    {
                        conflicts.Add(new KeyValuePair <CkanModule, CkanModule>(listed_mod, module));
                        conflicts.Add(new KeyValuePair <CkanModule, CkanModule>(module, listed_mod));
                    }
                    else
                    {
                        throw new InconsistentKraken(
                                  $"{module} conflicts with {listed_mod}");
                    }
                }

                user_requested_mods.Add(module);
                Add(module, new SelectionReason.UserRequested());
            }

            // Now that we've already pre-populated the modlist, we can resolve
            // the rest of our dependencies.

            foreach (var module in user_requested_mods)
            {
                log.DebugFormat("Resolving relationships for {0}", module.identifier);
                Resolve(module, options);
            }

            try
            {
                // Finally, let's do a sanity check that our solution is actually sane.
                SanityChecker.EnforceConsistency(
                    modlist.Values.Concat(installed_modules),
                    registry.InstalledDlls,
                    registry.InstalledDlc
                    );
            }
            catch (BadRelationshipsKraken k)
            {
                // Add to this.conflicts (catches conflicting DLLs and DLCs that the above loops miss)
                foreach (var kvp in k.Conflicts)
                {
                    conflicts.Add(new KeyValuePair <CkanModule, CkanModule>(
                                      kvp.Key, null
                                      ));
                }
                if (!options.without_enforce_consistency)
                {
                    // Only re-throw if caller asked for consistency enforcement
                    throw;
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// <see cref="IRegistryQuerier.CheckSanity"/>
        /// </summary>
        public void CheckSanity()
        {
            IEnumerable <CfanModule> installed = from pair in installed_modules select pair.Value.Module;

            SanityChecker.EnforceConsistency(installed, installed_preexisting_modules.Keys);
        }
Beispiel #4
0
        public List <string> GetSanityErrors()
        {
            var installed = from pair in installed_modules select pair.Value.Module;

            return(SanityChecker.ConsistencyErrors(installed, installed_dlls.Keys).ToList());
        }
Beispiel #5
0
        /// <summary>
        /// Finds and returns all modules that could not exist without the listed modules installed, including themselves.
        /// Acts recursively and lazily.
        /// </summary>
        /// <param name="modulesToRemove">Modules that are about to be removed.</param>
        /// <param name="modulesToInstall">Optional list of modules that are about to be installed.</param>
        /// <param name="origInstalled">Modules that are already installed</param>
        /// <param name="dlls">Installed DLLs</param>
        /// <param name="dlc">Installed DLCs</param>
        /// <returns>List of modules whose dependencies are about to be or already removed.</returns>
        internal static IEnumerable <string> FindReverseDependencies(
            IEnumerable <string> modulesToRemove,
            IEnumerable <CkanModule> modulesToInstall,
            IEnumerable <CkanModule> origInstalled,
            IEnumerable <string> dlls,
            IDictionary <string, ModuleVersion> dlc
            )
        {
            modulesToRemove = modulesToRemove.Memoize();
            origInstalled   = origInstalled.Memoize();
            var dllSet = dlls.ToHashSet();

            // The empty list has no reverse dependencies
            // (Don't remove broken modules if we're only installing)
            if (modulesToRemove.Any())
            {
                // All modules in the input are included in the output
                foreach (string starter in modulesToRemove)
                {
                    yield return(starter);
                }
                while (true)
                {
                    // Make our hypothetical install, and remove the listed modules from it.
                    HashSet <CkanModule> hypothetical = new HashSet <CkanModule>(origInstalled); // Clone because we alter hypothetical.
                    if (modulesToInstall != null)
                    {
                        // Pretend the mods we are going to install are already installed, so that dependencies that will be
                        // satisfied by a mod that is going to be installed count as satisfied.
                        hypothetical = hypothetical.Concat(modulesToInstall).ToHashSet();
                    }
                    hypothetical.RemoveWhere(mod => modulesToRemove.Contains(mod.identifier));

                    log.DebugFormat("Started with {0}, removing {1}, and keeping {2}; our dlls are {3}", string.Join(", ", origInstalled), string.Join(", ", modulesToRemove), string.Join(", ", hypothetical), string.Join(", ", dllSet));

                    // Find what would break with this configuration.
                    var broken = SanityChecker.FindUnsatisfiedDepends(hypothetical, dllSet, dlc)
                                 .Select(x => x.Key.identifier).ToHashSet();

                    if (modulesToInstall != null)
                    {
                        // Make sure to only report modules as broken if they are actually currently installed.
                        // This is mainly to remove the modulesToInstall again which we added
                        // earlier to the hypothetical list.
                        broken.IntersectWith(origInstalled.Select(m => m.identifier));
                    }
                    // Lazily return each newly found rev dep
                    foreach (string newFound in broken.Except(modulesToRemove))
                    {
                        yield return(newFound);
                    }

                    // If nothing else would break, it's just the list of modules we're removing.
                    HashSet <string> to_remove = new HashSet <string>(modulesToRemove);

                    if (to_remove.IsSupersetOf(broken))
                    {
                        log.DebugFormat("{0} is a superset of {1}, work done", string.Join(", ", to_remove), string.Join(", ", broken));
                        break;
                    }

                    // Otherwise, remove our broken modules as well, and recurse.
                    broken.UnionWith(to_remove);
                    modulesToRemove = broken;
                }
            }
        }