public void SingleDownload() { // Force log4net on. // BasicConfigurator.Configure(); // LogManager.GetRepository().Threshold = Level.Debug; log.Info("Performing single download test."); // We know kOS is in the TestKAN data, and hosted in KS. Let's get it. var modules = new List <CfanModule>(); CfanModule kOS = registry.LatestAvailable("kOS", null); Assert.IsNotNull(kOS); modules.Add(kOS); // Make sure we don't alread have kOS somehow. Assert.IsFalse(cache.IsCached(kOS.download)); // log.InfoFormat("Downloading kOS from {0}", kOS.download); // Download our module. async.DownloadModules( ksp.KSP.Cache, modules ); // Assert that we have it, and it passes zip validation. Assert.IsTrue(cache.IsCachedZip(kOS.download)); }
public void SingleDownload() { log.Info("Performing single download test."); // We know kOS is in the TestKAN data, and hosted in KS. Let's get it. var modules = new List <CkanModule>(); CkanModule kOS = registry.LatestAvailable("kOS", null); Assert.IsNotNull(kOS); modules.Add(kOS); // Make sure we don't alread have kOS somehow. Assert.IsFalse(cache.IsCached(kOS)); // log.InfoFormat("Downloading kOS from {0}", kOS.download); // Download our module. async.DownloadModules(modules); // Assert that we have it, and it passes zip validation. Assert.IsTrue(cache.IsCachedZip(kOS)); }
public void UpdateRegistryTarGz() { CKAN.Repo.UpdateRegistry(TestData.TestKANTarGz(), registry, ksp.KSP, new NullUser()); // Test we've got an expected module. CkanModule far = registry.LatestAvailable("FerramAerospaceResearch", KspVersion.Parse("0.25.0")); Assert.AreEqual("v0.14.3.2", far.version.ToString()); }
public void UpdateRegistryTarGz() { CKAN.Repo.UpdateRegistry(TestData.TestKANTarGz(), registry, ksp.KSP, new NullUser()); // Test we've got an expected module. CfanModule far = registry.LatestAvailable("FARL", new FactorioVersion("0.12.99")); Assert.AreEqual("0.5.25", far.modVersion.ToString()); }
/// <summary> /// Tries to parse an identifier in the format Modname=version /// If the module cannot be found in the registry, throws a ModuleNotFoundKraken. /// </summary> public static CkanModule FromIDandVersion(Registry registry, string mod, KSPVersion ksp_version) { CkanModule module; Match match = Regex.Match(mod, @"^(?<mod>[^=]*)=(?<version>.*)$"); if (match.Success) { string ident = match.Groups["mod"].Value; string version = match.Groups["version"].Value; module = registry.GetModuleByVersion(ident, version); if (module == null) { throw new ModuleNotFoundKraken(ident, version, string.Format("Cannot install {0}, version {1} not available", ident, version)); } } else { module = registry.LatestAvailable(mod, ksp_version); } if (module == null) { throw new ModuleNotFoundKraken(mod, null, string.Format("Cannot install {0}, module not available", mod)); } else { return(module); } }
public GUIMod(CkanModule mod, Registry registry, KSPVersion current_ksp_version) { //Currently anything which could alter these causes a full reload of the modlist // If this is ever changed these could be moved into the properties Mod = mod; IsInstalled = registry.IsInstalled(mod.identifier); IsInstallChecked = IsInstalled; HasUpdate = registry.HasUpdate(mod.identifier, current_ksp_version); IsIncompatible = !mod.IsCompatibleKSP(current_ksp_version); IsAutodetected = registry.IsAutodetected(mod.identifier); Authors = mod.author == null ? "N/A" : String.Join(",", mod.author); var installedVersion = registry.InstalledVersion(mod.identifier); var latestVersion = registry.LatestAvailable(mod.identifier, current_ksp_version); var kspVersion = mod.ksp_version; InstalledVersion = installedVersion != null?installedVersion.ToString() : "-"; LatestVersion = latestVersion != null?latestVersion.version.ToString() : "-"; KSPversion = kspVersion != null?kspVersion.ToString() : "-"; Abstract = mod.@abstract; Homepage = mod.resources != null && mod.resources.homepage != null ? (object)mod.resources.homepage : "N/A"; Identifier = mod.identifier; }
/// <summary> /// Create a CkanModule object that represents the currently installed /// mod list as a metapackage. /// </summary> /// <param name="recommends">If true, put the mods in the recommends relationship, otherwise use depends</param> /// <param name="with_versions">If true, set the installed mod versions in the relationships</param> /// <returns> /// The CkanModule object /// </returns> public CkanModule GenerateModpack(bool recommends = false, bool with_versions = true) { string kspInstanceName = ksp.Name; string name = $"installed-{kspInstanceName}"; var module = new CkanModule( // v1.18 to allow Unlicense new ModuleVersion("v1.18"), Identifier.Sanitize(name), name, $"A list of modules installed on the {kspInstanceName} KSP instance", null, new List <string>() { System.Environment.UserName }, new List <License>() { new License("unknown") }, new ModuleVersion(DateTime.UtcNow.ToString("yyyy.MM.dd.hh.mm.ss")), null, "metapackage" ) { download_content_type = "application/zip", release_date = DateTime.Now, }; List <RelationshipDescriptor> mods = registry.Installed(false, false) .Where(kvp => { // Skip unavailable modules (custom .ckan files) try { var avail = registry.LatestAvailable(kvp.Key, null, null); return(!avail.IsDLC); } catch { return(false); } }) .Select(kvp => (RelationshipDescriptor) new ModuleRelationshipDescriptor() { name = kvp.Key, version = with_versions ? kvp.Value : null }) .ToList(); if (recommends) { module.recommends = mods; } else { module.depends = mods; } return(module); }
public void LatestAvailable() { CkanModule module = registry.LatestAvailable("AGExt", temp_ksp.KSP.Version()); Assert.AreEqual("AGExt", module.identifier); Assert.AreEqual("1.24a", module.version.ToString()); }
/// <summary> /// Creates a new resolver that will find a way to install all the modules specified. /// </summary> public RelationshipResolver(List <string> modules, RelationshipResolverOptions options, Registry registry) { this.registry = registry; // 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. var user_requested_mods = new List <CkanModule>(); log.DebugFormat("Processing relationships for {0} modules", modules.Count); foreach (string module in modules) { CkanModule mod = registry.LatestAvailable(module); if (mod == null) { throw new ModuleNotFoundKraken(module); } log.DebugFormat("Preparing to resolve relationships for {0} {1}", mod.identifier, mod.version); foreach (CkanModule listed_mod in this.modlist.Values) { if (listed_mod.ConflictsWith(mod)) { throw new InconsistentKraken(string.Format("{0} conflicts with {1}, can't install both.", mod, listed_mod)); } } user_requested_mods.Add(mod); this.Add(mod); } // Now that we've already pre-populated modlist, we can resolve // the rest of our dependencies. foreach (CkanModule module in user_requested_mods) { log.InfoFormat("Resolving relationships for {0}", module.identifier); Resolve(module, options); } var final_modules = new List <Module>(modlist.Values); final_modules.AddRange(registry.InstalledModules.Select(x => x.Module)); if (!options.without_enforce_consistency) { // Finally, let's do a sanity check that our solution is actually sane. SanityChecker.EnforceConsistency( final_modules, registry.InstalledDlls ); } }
/// <summary> /// This function returns a changeset based on the selections of the user. /// Currently returns null if a conflict is detected. /// </summary> /// <param name="registry"></param> /// <param name="current_instance"></param> public static IEnumerable <KeyValuePair <CkanModule, GUIModChangeType> > ComputeChangeSetFromModList( Registry registry, HashSet <KeyValuePair <CkanModule, GUIModChangeType> > changeSet, ModuleInstaller installer, KSPVersion version) { var modules_to_install = new HashSet <string>(); var modules_to_remove = new HashSet <string>(); var options = new RelationshipResolverOptions() { without_toomanyprovides_kraken = true, with_recommends = false }; foreach (var change in changeSet) { switch (change.Value) { case GUIModChangeType.None: break; case GUIModChangeType.Install: modules_to_install.Add(change.Key.identifier); break; case GUIModChangeType.Remove: modules_to_remove.Add(change.Key.identifier); break; case GUIModChangeType.Update: break; default: throw new ArgumentOutOfRangeException(); } } //May throw InconsistentKraken var resolver = new RelationshipResolver(modules_to_install.ToList(), options, registry, version); changeSet.UnionWith( resolver.ModList() .Select(mod => new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Install))); foreach (var reverse_dependencies in modules_to_remove.Select(installer.FindReverseDependencies)) { //TODO This would be a good place to have a event that alters the row's graphics to show it will be removed //TODO This currently gets the latest version. This may cause the displayed version to wrong in the changset. var modules = reverse_dependencies.Select(rDep => registry.LatestAvailable(rDep, null)); changeSet.UnionWith( modules.Select(mod => new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Remove))); } return(changeSet); }
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); }
public void DogeCoin() { // Test with a module that depends and conflicts with nothing. var mods = new List <CkanModule> { registry.LatestAvailable("DogeCoinFlag", null) }; Assert.IsTrue(CKAN.SanityChecker.IsConsistent(mods), "DogeCoinFlag"); }
public void RemoveAvailableByName() { // Add our module and test it's there. registry.AddAvailable(module); Assert.IsNotNull(registry.LatestAvailable(identifier, v0_24_2)); // Remove it, and make sure it's gone. registry.RemoveAvailable(identifier, module.version); Assert.IsNull(registry.LatestAvailable(identifier, v0_24_2)); }
// this functions computes a changeset from the user's choices in the GUI private List <KeyValuePair <CkanModule, GUIModChangeType> > ComputeChangeSetFromModList() // this probably needs to be refactored { var changeset = new HashSet <KeyValuePair <CkanModule, GUIModChangeType> >(); // these are the lists var modulesToInstall = new HashSet <string>(); var modulesToRemove = new HashSet <string>(); Registry registry = RegistryManager.Instance(KSPManager.CurrentInstance).registry; foreach (DataGridViewRow row in ModList.Rows) { var mod = (CkanModule)row.Tag; if (mod == null) { continue; } bool isInstalled = registry.IsInstalled(mod.identifier); var isInstalledCell = row.Cells[0] as DataGridViewCheckBoxCell; var isInstalledChecked = (bool)isInstalledCell.Value; if (!isInstalled && isInstalledChecked) { modulesToInstall.Add(mod.identifier); } else if (isInstalled && !isInstalledChecked) { modulesToRemove.Add(mod.identifier); } } RelationshipResolverOptions options = RelationshipResolver.DefaultOpts(); options.with_recommends = false; options.without_toomanyprovides_kraken = true; options.without_enforce_consistency = true; RelationshipResolver resolver = null; try { resolver = new RelationshipResolver(modulesToInstall.ToList(), options, registry); } catch (Exception e) { return(null); } foreach (CkanModule mod in resolver.ModList()) { changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Install)); } ModuleInstaller installer = ModuleInstaller.Instance; foreach (string moduleName in modulesToRemove) { var reverseDependencies = installer.FindReverseDependencies(moduleName); foreach (string reverseDependency in reverseDependencies) { CkanModule mod = registry.LatestAvailable(reverseDependency); changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Remove)); } } foreach (DataGridViewRow row in ModList.Rows) { var mod = (CkanModule)row.Tag; if (mod == null) { continue; } bool isInstalled = registry.IsInstalled(mod.identifier); var isInstalledCell = row.Cells[0] as DataGridViewCheckBoxCell; var isInstalledChecked = (bool)isInstalledCell.Value; DataGridViewCell shouldBeUpdatedCell = row.Cells[1]; bool shouldBeUpdated = false; if (shouldBeUpdatedCell is DataGridViewCheckBoxCell && shouldBeUpdatedCell.Value != null) { shouldBeUpdated = (bool)shouldBeUpdatedCell.Value; } if (isInstalled && !isInstalledChecked) { changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Remove)); } else if (isInstalled && isInstalledChecked && mod.version.IsGreaterThan(registry.InstalledVersion(mod.identifier)) && shouldBeUpdated) { changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Update)); } } return(changeset.ToList()); }
/// <summary> /// This function returns a changeset based on the selections of the user. /// Currently returns null if a conflict is detected. /// </summary> /// <param name="registry"></param> /// <param name="current_instance"></param> public List <KeyValuePair <CkanModule, GUIModChangeType> > ComputeChangeSetFromModList(Registry registry, KSP current_instance) { var changeset = new HashSet <KeyValuePair <CkanModule, GUIModChangeType> >(); var modulesToInstall = new HashSet <string>(); var modulesToRemove = new HashSet <string>(); foreach (var mod in Modules.Where(mod => mod.IsInstallable())) { if (mod.IsInstalled) { if (!mod.IsInstallChecked) { modulesToRemove.Add(mod.Identifier); changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod.ToCkanModule(), GUIModChangeType.Remove)); } else if (mod.IsInstallChecked && mod.HasUpdate && mod.IsUpgradeChecked) { changeset.Add(new KeyValuePair <CkanModule, GUIModChangeType>(mod.ToCkanModule(), GUIModChangeType.Update)); } } else if (mod.IsInstallChecked) { modulesToInstall.Add(mod.Identifier); } } RelationshipResolverOptions options = RelationshipResolver.DefaultOpts(); options.with_recommends = false; options.without_toomanyprovides_kraken = true; options.without_enforce_consistency = true; RelationshipResolver resolver; try { resolver = new RelationshipResolver(modulesToInstall.ToList(), options, registry); } catch (Exception) { //TODO FIX this so the UI reacts. return(null); } changeset.UnionWith( resolver.ModList() .Select(mod => new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Install))); ModuleInstaller installer = ModuleInstaller.GetInstance(current_instance, GUI.user); foreach (var reverseDependencies in modulesToRemove.Select(mod => installer.FindReverseDependencies(mod))) { //TODO This would be a good place to have a event that alters the row's graphics to show it will be removed var modules = reverseDependencies.Select(rDep => registry.LatestAvailable(rDep)); changeset.UnionWith( modules.Select(mod => new KeyValuePair <CkanModule, GUIModChangeType>(mod, GUIModChangeType.Remove))); } return(changeset.ToList()); }
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); }