/// <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); }
/// <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; } } }
/// <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); }
public List <string> GetSanityErrors() { var installed = from pair in installed_modules select pair.Value.Module; return(SanityChecker.ConsistencyErrors(installed, installed_dlls.Keys).ToList()); }
/// <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; } } }