/// <summary> /// Get a dictionary of all mod versions indexed by their download URLs' hash. /// Useful for finding the mods for a group of URLs without repeatedly searching the entire registry. /// </summary> /// <returns> /// dictionary[urlHash] = {mod1, mod2, mod3}; /// </returns> public Dictionary <string, List <CkanModule> > GetDownloadHashIndex() { var index = new Dictionary <string, List <CkanModule> >(); foreach (var kvp in available_modules) { AvailableModule am = kvp.Value; foreach (var kvp2 in am.module_version) { CkanModule mod = kvp2.Value; if (mod.download != null) { string hash = NetFileCache.CreateURLHash(mod.download); if (index.ContainsKey(hash)) { index[hash].Add(mod); } else { index.Add(hash, new List <CkanModule>() { mod }); } } } } return(index); }
/// <summary> /// Get a dictionary of all mod versions indexed by their downloads' SHA-1 hash. /// Useful for finding the mods for a group of files without repeatedly searching the entire registry. /// </summary> /// <returns> /// dictionary[sha1] = {mod1, mod2, mod3}; /// </returns> public Dictionary <string, List <CkanModule> > GetSha1Index() { var index = new Dictionary <string, List <CkanModule> >(); foreach (var kvp in available_modules) { AvailableModule am = kvp.Value; foreach (var kvp2 in am.module_version) { CkanModule mod = kvp2.Value; if (mod.download_hash != null) { if (index.ContainsKey(mod.download_hash.sha1)) { index[mod.download_hash.sha1].Add(mod); } else { index.Add(mod.download_hash.sha1, new List <CkanModule>() { mod }); } } } } return(index); }
/// <summary> /// Returns the specified CkanModule with the version specified, /// or null if it does not exist. /// <see cref = "IRegistryQuerier.GetModuleByVersion" /> /// </summary> public CkanModule GetModuleByVersion(string ident, Version version) { log.DebugFormat("Trying to find {0} version {1}", ident, version); if (!available_modules.ContainsKey(ident)) { return(null); } AvailableModule available = available_modules[ident]; return(available.ByVersion(version)); }
/// <summary> /// Mark a given module as available. /// </summary> public void AddAvailable(CkanModule module) { SealionTransaction(); var identifier = module.identifier; // If we've never seen this module before, create an entry for it. if (!available_modules.ContainsKey(identifier)) { log.DebugFormat("Adding new available module {0}", identifier); available_modules[identifier] = new AvailableModule(identifier); } // Now register the actual version that we have. // (It's okay to have multiple versions of the same mod.) log.DebugFormat("Available: {0} version {1}", identifier, module.version); available_modules[identifier].Add(module); }
/// <summary> /// Ensure one AvailableModule is present in the right spots in the providers index /// </summary> private void BuildProvidesIndexFor(AvailableModule am) { foreach (CkanModule m in am.AllAvailable()) { foreach (string provided in m.ProvidesList) { if (providers.TryGetValue(provided, out HashSet <AvailableModule> provs)) { provs.Add(am); } else { providers.Add(provided, new HashSet <AvailableModule>() { am }); } } } }
public void BuildTagIndexFor(AvailableModule am) { bool tagged = false; foreach (CkanModule m in am.AllAvailable()) { if (m.Tags != null) { tagged = true; foreach (string tagName in m.Tags) { ModuleTag tag = null; if (Tags.TryGetValue(tagName, out tag)) { tag.Add(m.identifier); } else { Tags.Add(tagName, new ModuleTag() { Name = tagName, Visible = !HiddenTags.Contains(tagName), ModuleIdentifiers = new HashSet <string>() { m.identifier }, }); } } } } if (!tagged) { Untagged.Add(am.AllAvailable().First().identifier); } }
/// <summary> /// Mark a given module as available. /// </summary> public void AddAvailable(CkanModule module) { SealionTransaction(); var identifier = module.identifier; // If we've never seen this module before, create an entry for it. if (! available_modules.ContainsKey(identifier)) { log.DebugFormat("Adding new available module {0}", identifier); available_modules[identifier] = new AvailableModule(identifier); } // Now register the actual version that we have. // (It's okay to have multiple versions of the same mod.) log.DebugFormat("Available: {0} version {1}", identifier, module.version); available_modules[identifier].Add(module); }
/// <summary> /// Move an indeterminate module to Compatible or Incompatible /// based on its dependencies. /// </summary> /// <param name="identifier">Identifier of the module to check</param> /// <param name="am">The module to check</param> /// <param name="providers">Mapping from identifiers to mods providing those identifiers</param> private void CheckDepends(string identifier, AvailableModule am, Dictionary <string, HashSet <AvailableModule> > providers) { Investigating.Push(identifier); foreach (CkanModule m in am.AllAvailable().Where(m => m.IsCompatibleKSP(CompatibleVersions))) { log.DebugFormat("What about {0}?", m.version); bool installable = true; if (m.depends != null) { foreach (RelationshipDescriptor rel in m.depends) { bool foundCompat = false; if (rel.MatchesAny(installed.Select(kvp => kvp.Value.Module), dlls, dlc)) { // Matches a DLL or DLC, cool foundCompat = true; } else { // Get the list of identifiers that would satisfy this dependency // (mostly only one, except for any_of relationships). // For each of those identifiers, if it is provided by at least one module, get all the modules // that provide it (and make sure each is only once in the list) var candidates = RelationshipIdentifiers(rel) .Where(ident => providers.ContainsKey(ident)) .SelectMany(ident => providers[ident]) .Distinct(); foreach (AvailableModule provider in candidates) { string ident = provider.AllAvailable().First().identifier; log.DebugFormat("Checking depends: {0}", ident); if (Investigating.Contains(ident)) { // Circular dependency, pretend it's fine for now foundCompat = true; break; } if (Indeterminate.ContainsKey(ident)) { CheckDepends(ident, provider, providers); } if (Compatible.ContainsKey(ident)) { // This one's OK, go to next relationship foundCompat = true; break; } } } if (!foundCompat) { // Not satisfiable!! Next CkanModule installable = false; break; } } } if (installable) { // Apparently everything is OK, so we are compatible log.DebugFormat("Complexly compatible: {0}", identifier); Compatible.Add(identifier, am); Indeterminate.Remove(identifier); Investigating.Pop(); return; } } // None of the CkanModules can be installed! log.DebugFormat("Complexly incompatible: {0}", identifier); Incompatible.Add(identifier, am); Indeterminate.Remove(identifier); Investigating.Pop(); }