// We require our constructor to be private so we can // enforce this being an instance (via Instance() above) private RegistryManager(string path, KSP ksp) { this.ksp = ksp; this.path = Path.Combine(path, "registry.json"); lockfilePath = Path.Combine(path, "registry.json.locked"); // Create a lock for this registry, so we cannot touch it again. if (!GetLock()) { throw new RegistryInUseKraken(lockfilePath); } LoadOrCreate(); // We don't cause an inconsistency error to stop the registry from being loaded, // because then the user can't do anything to correct it. However we're // sure as hell going to complain if we spot one! try { registry.CheckSanity(); } catch (InconsistentKraken kraken) { log.ErrorFormat("Loaded registry with inconsistencies:\r\n\r\n{0}", kraken.InconsistenciesPretty); } }
// We require our constructor to be private so we can // enforce this being an instance (via Instance() above) private RegistryManager(string path, GameInstance ksp) { this.ksp = ksp; this.path = Path.Combine(path, "registry.json"); lockfilePath = InstanceRegistryLockPath(path); // Create a lock for this registry, so we cannot touch it again. if (!GetLock()) { log.DebugFormat("Unable to acquire registry lock: {0}", lockfilePath); throw new RegistryInUseKraken(lockfilePath); } try { LoadOrCreate(); } catch { // Clean up the lock file Dispose(false); throw; } // We don't cause an inconsistency error to stop the registry from being loaded, // because then the user can't do anything to correct it. However we're // sure as hell going to complain if we spot one! try { registry.CheckSanity(); } catch (InconsistentKraken kraken) { // Only log an error for this if user-interactive, // automated tools do not care that no one picked a Scatterer config if (ksp.User.Headless) { log.InfoFormat("Loaded registry with inconsistencies:\r\n\r\n{0}", kraken.InconsistenciesPretty); } else { log.ErrorFormat("Loaded registry with inconsistencies:\r\n\r\n{0}", kraken.InconsistenciesPretty); } } }
// We require our constructor to be private so we can // enforce this being an instance (via Instance() above) private RegistryManager(string path, KSP ksp) { this.ksp = ksp; this.path = Path.Combine(path, "registry.json"); LoadOrCreate(); // We don't cause an inconsistency error to stop the registry from being loaded, // because then the user can't do anything to correct it. However we're // sure as hell going to complain if we spot one! try { registry.CheckSanity(); } catch (InconsistentKraken kraken) { log.ErrorFormat("Loaded registry with inconsistencies:\n\n{0}", kraken.InconsistenciesPretty); } }
public void UninstallingConflictingModule_InstallingRecursiveDependencies_ResolvesSuccessfully() { using (var ksp = new DisposableKSP()) { // Arrange: create dummy modules that resemble the relationship entanglement, and make them available var eve = generator.GeneratorRandomModule( identifier: "EnvironmentalVisualEnhancements", depends: new List <RelationshipDescriptor> { new ModuleRelationshipDescriptor { name = "EnvironmentalVisualEnhancements-Config" } } ); var eveDefaultConfig = generator.GeneratorRandomModule( identifier: "EnvironmentalVisualEnhancements-Config-stock", provides: new List <string> { "EnvironmentalVisualEnhancements-Config" }, conflicts: new List <RelationshipDescriptor> { new ModuleRelationshipDescriptor { name = "EnvironmentalVisualEnhancements-Config" } } ); var avp = generator.GeneratorRandomModule( identifier: "AstronomersVisualPack", provides: new List <string> { "EnvironmentalVisualEnhancements-Config" }, depends: new List <RelationshipDescriptor> { new ModuleRelationshipDescriptor { name = "AVP-Textures" }, new ModuleRelationshipDescriptor { name = "EnvironmentalVisualEnhancements" } }, conflicts: new List <RelationshipDescriptor> { new ModuleRelationshipDescriptor { name = "EnvironmentalVisualEnhancements-Config" } } ); var avp2kTextures = generator.GeneratorRandomModule( identifier: "AVP-2kTextures", provides: new List <string> { "AVP-Textures" }, depends: new List <RelationshipDescriptor> { new ModuleRelationshipDescriptor { name = "AstronomersVisualPack" } }, conflicts: new List <RelationshipDescriptor> { new ModuleRelationshipDescriptor { name = "AVP-Textures" } } ); AddToRegistry(eve, eveDefaultConfig, avp, avp2kTextures); // Start with eve and eveDefaultConfig installed registry.RegisterModule(eve, new string[0], ksp.KSP, false); registry.RegisterModule(eveDefaultConfig, new string[0], ksp.KSP, false); Assert.DoesNotThrow(() => registry.CheckSanity()); List <CkanModule> modulesToInstall; List <CkanModule> modulesToRemove; RelationshipResolver resolver; // Act and assert: play through different possible user interactions // Scenario 1 - Try installing AVP, expect an exception for proceed_with_inconsistencies=false modulesToInstall = new List <CkanModule> { avp }; modulesToRemove = new List <CkanModule>(); options.proceed_with_inconsistencies = false; Assert.Throws <InconsistentKraken>(() => { resolver = new RelationshipResolver(modulesToInstall, modulesToRemove, options, registry, null); }); // Scenario 2 - Try installing AVP, expect no exception for proceed_with_inconsistencies=true, but a conflict list resolver = null; options.proceed_with_inconsistencies = true; Assert.DoesNotThrow(() => { resolver = new RelationshipResolver(modulesToInstall, modulesToRemove, options, registry, null); }); CollectionAssert.AreEquivalent(new List <CkanModule> { avp, eveDefaultConfig }, resolver.ConflictList.Keys); // Scenario 3 - Try uninstalling eveDefaultConfig and installing avp, should work and result in no conflicts modulesToInstall = new List <CkanModule> { avp }; modulesToRemove = new List <CkanModule> { eveDefaultConfig }; resolver = null; options.proceed_with_inconsistencies = false; Assert.DoesNotThrow(() => { resolver = new RelationshipResolver(modulesToInstall, modulesToRemove, options, registry, null); }); Assert.IsEmpty(resolver.ConflictList); CollectionAssert.AreEquivalent(new List <CkanModule> { avp, avp2kTextures }, resolver.ModList()); } }