Exemplo n.º 1
0
        public void HasUpdate_OtherModDependsOnCurrent_ReturnsFalse()
        {
            // Arrange
            using (var gameInstWrapper = new DisposableKSP())
            {
                CkanModule olderDepMod  = CkanModule.FromJson(@"{
                    ""spec_version"": ""v1.4"",
                    ""identifier"":   ""DependencyMod"",
                    ""version"":      ""1.0"",
                    ""ksp_version"":  ""1.11.1"",
                    ""download"":     ""https://mymods/DM/1.0""
                }");
                CkanModule newerDepMod  = CkanModule.FromJson(@"{
                    ""spec_version"": ""v1.4"",
                    ""identifier"":   ""DependencyMod"",
                    ""version"":      ""2.0"",
                    ""ksp_version"":  ""1.11.1"",
                    ""download"":     ""https://mymods/DM/2.0""
                }");
                CkanModule dependingMod = CkanModule.FromJson(@"{
                    ""spec_version"": ""v1.4"",
                    ""identifier"":   ""DependingMod"",
                    ""version"":      ""1.0"",
                    ""ksp_version"":  ""1.11.1"",
                    ""download"":     ""https://mymods/DM/2.0"",
                    ""depends"": [
                        {
                            ""name"":    ""DependencyMod"",
                            ""version"": ""1.0""
                        }
                    ]
                }");
                registry.AddAvailable(olderDepMod);
                registry.AddAvailable(newerDepMod);
                registry.AddAvailable(dependingMod);
                GameInstance gameInst = gameInstWrapper.KSP;
                registry.RegisterModule(olderDepMod, new string[0], gameInst, false);
                registry.RegisterModule(dependingMod, new string[0], gameInst, false);
                GameVersionCriteria crit = new GameVersionCriteria(olderDepMod.ksp_version);

                // Act
                bool has = registry.HasUpdate(olderDepMod.identifier, crit);

                // Assert
                Assert.IsFalse(has, "Upgrade allowed that would break another mod's dependency");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        ///     Install our mod from the filename supplied.
        ///     If no file is supplied, we will check the cache or throw FileNotFoundKraken.
        ///     Does *not* resolve dependencies; this actually does the heavy listing.
        ///     Does *not* save the registry.
        ///     Do *not* call this directly, use InstallList() instead.
        ///
        /// Propagates a BadMetadataKraken if our install metadata is bad.
        /// Propagates a FileExistsKraken if we were going to overwrite a file.
        /// Throws a FileNotFoundKraken if we can't find the downloaded module.
        ///
        /// </summary>
        //
        // TODO: The name of this and InstallModule() need to be made more distinctive.

        private void Install(CkanModule module, string filename = null)
        {
            CheckMetapackageInstallationKraken(module);

            Version version = registry_manager.registry.InstalledVersion(module.identifier);

            // TODO: This really should be handled by higher-up code.
            if (version != null)
            {
                User.RaiseMessage("    {0} {1} already installed, skipped", module.identifier, version);
                return;
            }

            // Find our in the cache if we don't already have it.
            filename = filename ?? Cache.GetCachedZip(module.download, true);

            // If we *still* don't have a file, then kraken bitterly.
            if (filename == null)
            {
                throw new FileNotFoundKraken(
                          null,
                          String.Format("Trying to install {0}, but it's not downloaded or download is corrupted", module)
                          );
            }

            // We'll need our registry to record which files we've installed.
            Registry registry = registry_manager.registry;

            using (var transaction = CkanTransaction.CreateTransactionScope())
            {
                // Install all the things!
                IEnumerable <string> files = InstallModule(module, filename);

                // Register our module and its files.
                registry.RegisterModule(module, files, ksp);

                // Finish our transaction, but *don't* save the registry; we may be in an
                // intermediate, inconsistent state.
                // This is fine from a transaction standpoint, as we may not have an enclosing
                // transaction, and if we do, they can always roll us back.
                transaction.Complete();
            }

            // Fire our callback that we've installed a module, if we have one.
            if (onReportModInstalled != null)
            {
                onReportModInstalled(module);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        ///     Install our mod from the filename supplied.
        ///     If no file is supplied, we will check the cache or download it.
        ///     Does *not* resolve dependencies; this actually does the heavy listing.
        ///     Does *not* save the registry.
        ///     Do *not* call this directly, use InstallList() instead.
        ///
        /// Propagates a BadMetadataKraken if our install metadata is bad.
        /// Propagates a FileExistsKraken if we were going to overwrite a file.
        ///
        /// </summary>
        //
        // TODO: The name of this and InstallModule() need to be made more distinctive.

        private void Install(CkanModule module, string filename = null)
        {
            Version version = registry_manager.registry.InstalledVersion(module.identifier);

            // TODO: This really should be handled by higher-up code.
            if (version != null)
            {
                User.WriteLine("    {0} {1} already installed, skipped", module.identifier, version);
                return;
            }

            // Fetch our file if we don't already have it.
            if (filename == null)
            {
                filename = CachedOrDownload(module);
            }

            // We'll need our registry to record which files we've installed.
            Registry registry = registry_manager.registry;

            using (var transaction = new TransactionScope())
            {
                // Install all the things!
                IEnumerable <string> files = InstallModule(module, filename);

                // Register our module and its files.
                registry.RegisterModule(module, files, ksp);

                // Finish our transaction, but *don't* save the registry; we may be in an
                // intermediate, inconsistent state.
                // This is fine from a transaction standpoint, as we may not have an enclosing
                // transaction, and if we do, they can always roll us back.
                transaction.Complete();
            }

            // Fire our callback that we've installed a module, if we have one.
            if (onReportModInstalled != null)
            {
                onReportModInstalled(module);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Install our mod from the filename supplied.
        /// If no file is supplied, we will fetch() it first.
        /// </summary>

        public void Install(CkanModule module, string filename = null)
        {
            Console.WriteLine(module.identifier + ":\n");

            string version = registry_manager.registry.InstalledVersion(module.identifier);

            if (version != null)
            {
                // TODO: Check if we can upgrade!
                Console.WriteLine("    {0} {1} already installed, skipped", module.identifier, version);
                return;
            }

            // Check our dependencies.

            if (module.requires != null)
            {
                foreach (dynamic depends in module.requires)
                {
                    string name = depends.name;
                    string ver  = registry_manager.registry.InstalledVersion(name);
                    // TODO: Compare versions.

                    if (ver == null)
                    {
                        // Oh, it's not installed! Let's see if we can find it.

                        // TODO: A big store of all our known CKAN data, so we can go
                        // find our module.

                        // If we can't find it, cry and moan.
                        Console.WriteLine("Requirement {0} not found", depends.name);
                        throw new ModuleNotFoundException(name, depends.version);
                    }
                }
            }

            // Fetch our file if we don't already have it.
            if (filename == null)
            {
                filename = CachedOrDownload(module);
            }

            // We'll need our registry to record which files we've installed.
            Registry registry = registry_manager.registry;

            // And a list of files to record them to.
            Dictionary <string, InstalledModuleFile> module_files = new Dictionary <string, InstalledModuleFile> ();

            // Open our zip file for processing
            ZipFile zipfile = new ZipFile(File.OpenRead(filename));

            // Walk through our install instructions.
            foreach (dynamic stanza in module.install)
            {
                InstallComponent(stanza, zipfile, module_files);
            }

            // Register our files.
            registry.RegisterModule(new InstalledModule(module_files, module, DateTime.Now));

            // Handle bundled mods, if we have them.
            if (module.bundles != null)
            {
                foreach (dynamic stanza in module.bundles)
                {
                    BundledModule bundled = new BundledModule(stanza);

                    string ver = registry_manager.registry.InstalledVersion(bundled.identifier);

                    if (ver != null)
                    {
                        Console.WriteLine(
                            "{0} {1} already installed, skipping bundled version {2}",
                            bundled.identifier, ver, bundled.version
                            );
                        continue;
                    }

                    // Not installed, so let's get about installing it!
                    Dictionary <string, InstalledModuleFile> installed_files = new Dictionary <string, InstalledModuleFile> ();

                    InstallComponent(stanza, zipfile, installed_files);

                    registry.RegisterModule(new InstalledModule(installed_files, bundled, DateTime.Now));
                }
            }

            // Done! Save our registry changes!
            registry_manager.Save();

            return;
        }
Exemplo n.º 5
0
        public void Up()
        {
            _instance = new DisposableKSP();
            _registry = Registry.Empty();
            _manager = new KSPManager(new NullUser(), new FakeWin32Registry(_instance.KSP));

            // this module contains a ksp_version of "any" which repros our issue
            _anyVersionModule = TestData.DogeCoinFlag_101_module();

            // install it and set it as pre-installed
            _instance.KSP.Cache.Store(TestData.DogeCoinFlag_101_module().download, TestData.DogeCoinFlagZip());
            _registry.RegisterModule(_anyVersionModule, new string[] { }, _instance.KSP);
            _registry.AddAvailable(_anyVersionModule);

            ModuleInstaller.GetInstance(_instance.KSP, _manager.User).InstallList(
                new List<CkanModule> { { _anyVersionModule } },
                new RelationshipResolverOptions(),
                new NetAsyncModulesDownloader(_manager.User)
            );

            // this module is not for "any" version, to provide another to sort against
            _registry.AddAvailable(TestData.kOS_014_module());

            // test object
            _modList = new MainModList(null, null, _manager.User);
            _listGui = new MainModListGUI();

            // todo: refactor the column header code to allow mocking of the GUI without creating columns
            _listGui.Columns.Add(new DataGridViewCheckBoxColumn());
            _listGui.Columns.Add(new DataGridViewCheckBoxColumn());
            for (int i = 0; i < 10; i++)
            {
                _listGui.Columns.Add(i.ToString(), "Column" + i);
            }
        }
Exemplo n.º 6
0
        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());
            }
        }