示例#1
0
 /// <summary>
 /// Check if the given module is a metapackage:
 /// if it is, throws a BadCommandKraken.
 /// </summary>
 private static void CheckMetapackageInstallationKraken(CfanModule module)
 {
     if (module.isMetapackage)
     {
         throw new BadCommandKraken("Metapackages can not be installed!");
     }
 }
示例#2
0
        /// <summary>
        /// Installs the module from the zipfile provided.
        /// Returns a list of files installed.
        /// Propagates a BadMetadataKraken if our install metadata is bad.
        /// Propagates a FileExistsKraken if we were going to overwrite a file.
        /// </summary>
        private IEnumerable <string> InstallModule(CfanModule module, string zip_filename)
        {
            CheckMetapackageInstallationKraken(module);

            IEnumerable <IInstallable> files = FindInstallableFiles(module, zip_filename, ksp);

            try
            {
                foreach (IInstallable file in files)
                {
                    log.InfoFormat("Copying {0}", file.Name);
                    CopyZipEntry(ksp.getModTypeRootDirectory(module.kind), file);
                }
            }
            catch (FileExistsKraken kraken)
            {
                // Decorate the kraken with our module and re-throw
                kraken.filename          = ksp.ToRelativeGameDataDir(kraken.filename);
                kraken.installing_module = module;
                kraken.owning_module     = registry_manager.registry.FileOwner(kraken.filename);
                throw;
            }

            return(files.Select(x => Path.Combine(ksp.getModTypeRootDirectory(module.kind), x.Destination)));
        }
示例#3
0
        private void _PostModCaching(CfanModule module)
        {
            HideWaitDialog(true);

            UpdateModContentsTree(module, true);
            RecreateDialogs();
        }
示例#4
0
        private void UpdateModInfo(GUIMod gui_module)
        {
            CfanModule module = gui_module.ToModule();

            Util.Invoke(MetadataModuleNameLabel, () => MetadataModuleNameLabel.Text         = gui_module.Name);
            Util.Invoke(MetadataModuleVersionLabel, () => MetadataModuleVersionLabel.Text   = gui_module.LatestVersion.ToString());
            Util.Invoke(MetadataModuleLicenseLabel, () => MetadataModuleLicenseLabel.Text   = "");
            Util.Invoke(MetadataModuleAuthorLabel, () => MetadataModuleAuthorLabel.Text     = gui_module.Authors);
            Util.Invoke(MetadataModuleAbstractLabel, () => MetadataModuleAbstractLabel.Text = module.@abstract);
            Util.Invoke(MetadataIdentifierLabel, () => MetadataIdentifierLabel.Text         = module.identifier);

            // If we have homepage provided use that, otherwise use the spacedock page or the github repo so that users have somewhere to get more info than just the abstract.
            Util.Invoke(MetadataModuleHomePageLinkLabel,
                        () => MetadataModuleHomePageLinkLabel.Text = gui_module.Homepage.ToString());

            if (string.IsNullOrEmpty(gui_module.Homepage))
            {
                Util.Invoke(MetadataModuleGitHubLinkLabel,
                            () => MetadataModuleGitHubLinkLabel.Text = "N/A");
            }

            if (module.release_status != null)
            {
                Util.Invoke(MetadataModuleReleaseStatusLabel, () => MetadataModuleReleaseStatusLabel.Text = module.release_status.ToString());
            }

            Util.Invoke(MetadataModuleKSPCompatibilityLabel, () => MetadataModuleKSPCompatibilityLabel.Text = gui_module.KSPCompatibilityLong);
        }
示例#5
0
        public void AutodetectedCanSatisfyRelationships()
        {
            using (var ksp = new DisposableKSP())
            {
                registry.RegisterPreexistingModule(ksp.KSP, Path.Combine(ksp.KSP.GameData(), "ModuleManager.dll"), new ModInfoJson()
                {
                    name    = "ModuleManager",
                    version = new ModVersion("0.2.3")
                });

                var depends = new List <ModDependency>()
                {
                    new ModDependency("ModuleManager")
                };

                CfanModule mod = generator.GeneratorRandomModule(depends: depends);

                new RelationshipResolver(
                    new CfanModule[] { mod },
                    RelationshipResolver.DefaultOpts(),
                    registry,
                    new FactorioVersion("1.0.0")
                    );
            }
        }
示例#6
0
        /// <summary>
        /// Tests that a module might be able to be installed via checking if dependencies
        /// exist for current version.
        /// </summary>
        /// <param name="module">The module to consider</param>
        /// <param name="compatible">For internal use</param>
        /// <returns>If it has dependencies compatible for the current version</returns>
        private bool MightBeInstallable(CfanModule module, List <string> compatible = null)
        {
            if (module.depends == null)
            {
                return(true);
            }
            if (compatible == null)
            {
                compatible = new List <string>();
            }
            else if (compatible.Contains(module.identifier))
            {
                return(true);
            }
            //When checking the dependencies we assume that this module is installable
            // in case a dependent depends on it
            compatible.Add(module.identifier);

            var needed = module.depends.Select(depend => registry.LatestAvailableWithProvides(depend.modName, kspversion));
            //We need every dependency to have at least one possible module
            var installable = needed.All(need => need.Any(mod => MightBeInstallable(mod, compatible)));

            compatible.Remove(module.identifier);
            return(installable);
        }
示例#7
0
        public string getCachedOrDownloadFile(IUser user, string url, string expectedFilename)
        {
            string cachePath       = getPathToCachedOrDownloadedFile(user, url, expectedFilename);
            string firstCharacters = head(cachePath, 100).TrimStart();

            if (firstCharacters.StartsWith("<!DOCTYPE"))
            {
                throw new HtmlInsteadOfModDownloadedKraken("Downloaded some kind of html.");
            }
            // the json string with error usually is from github
            if (firstCharacters.StartsWith("{\"error\":"))
            {
                throw new HtmlInsteadOfModDownloadedKraken("Downloaded some kind of json error.");
            }
            string temporaryFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());

            File.Copy(cachePath, temporaryFile);
            modNormalizer.normalizeModFile(temporaryFile, Path.GetFileNameWithoutExtension(expectedFilename));
            // move to target place
            ModInfoJson modInfo = FactorioModParser.parseMod(temporaryFile);

            expectedFilename = CfanModule.createStandardFileName(modInfo.name, modInfo.version.ToString());
            // normalize again, this time with real filename (in order to fix directory name in zip file)
            modNormalizer.normalizeModFile(temporaryFile, expectedFilename);
            string fmmModFile = Path.Combine(RepoModsDirectoryPath, expectedFilename) + ".zip";

            if (File.Exists(fmmModFile))
            {
                File.Delete(fmmModFile);
            }
            File.Move(temporaryFile, fmmModFile);
            return(fmmModFile);
        }
示例#8
0
        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));
        }
示例#9
0
        public void LatestAvailable()
        {
            CfanModule module =
                registry.LatestAvailable("FARL", temp_ksp.KSP.Version());

            Assert.AreEqual("FARL", module.identifier);
            Assert.AreEqual("0.5.24", module.modVersion.ToString());
        }
示例#10
0
 public Depends(CfanModule module)
 {
     if (module == null)
     {
         throw new ArgumentNullException();
     }
     Parent = module;
 }
示例#11
0
 public Suggested(CfanModule module)
 {
     if (module == null)
     {
         throw new ArgumentNullException();
     }
     Parent = module;
 }
示例#12
0
 public Recommended(CfanModule module)
 {
     if (module == null)
     {
         throw new ArgumentNullException();
     }
     Parent = module;
 }
示例#13
0
文件: Repo.cs 项目: trakos/CFAN
        public void UpdateRegistryZip()
        {
            CKAN.Repo.UpdateRegistry(TestData.TestKANZip(), 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());
        }
示例#14
0
        /// <summary>
        /// <see cref="IRegistryQuerier.Available"/>
        /// </summary>
        public List <CfanModule> Available(FactorioVersion ksp_version)
        {
            var candidates = new List <string>(available_modules.Keys);
            var compatible = new List <CfanModule>();

            // It's nice to see things in alphabetical order, so sort our keys first.
            candidates.Sort();

            //Cache
            CfanModule[] modules_for_current_version = available_modules.Values.Select(pair => pair.Latest(ksp_version)).Where(mod => mod != null).ToArray();
            // Now find what we can give our user.
            foreach (string candidate in candidates)
            {
                CfanModule available = LatestAvailable(candidate, ksp_version);

                if (available != null)
                {
                    // we need to check that we can get everything we depend on
                    bool failedDepedency = false;

                    if (available.depends != null)
                    {
                        foreach (ModDependency dependency in available.depends)
                        {
                            try
                            {
                                if (!LatestAvailableWithProvides(dependency.modName, ksp_version, modules_for_current_version).Any())
                                {
                                    log.InfoFormat("Cannot find available version with provides for {0} in registry required by {1}", dependency.modName, candidate);
                                    failedDepedency = true;
                                    break;
                                }
                            }
                            catch (KeyNotFoundException)
                            {
                                log.ErrorFormat("Cannot find available version with provides for {0} in registry", dependency.modName);
                                throw;
                            }
                            catch (ModuleNotFoundKraken)
                            {
                                log.InfoFormat("Cannot find available version with provides for {0} in registry required by {1}", dependency.modName, candidate);
                                failedDepedency = true;
                                break;
                            }
                        }
                    }

                    if (!failedDepedency)
                    {
                        compatible.Add(available);
                    }
                }
            }

            return(compatible);
        }
示例#15
0
 private void UpdateModContentsTree(CfanModule module, bool force = false)
 {
     ModInfoTabControl.Tag = module ?? ModInfoTabControl.Tag;
     //Can be costly. For now only update when visible.
     if (ModInfoTabControl.SelectedIndex != ContentTabPage.TabIndex && !force)
     {
         return;
     }
     Util.Invoke(ContentsPreviewTree, () => _UpdateModContentsTree(force));
 }
示例#16
0
        /// <summary>
        /// Displays a user readable string explaining why the mod was chosen.
        /// </summary>
        /// <param name="mod">A Mod in the resolvers modlist. Must not be null</param>
        /// <returns></returns>
        public string ReasonStringFor(CfanModule mod)
        {
            var reason       = ReasonFor(mod);
            var is_root_type = reason.GetType() == typeof(SelectionReason.UserRequested) ||
                               reason.GetType() == typeof(SelectionReason.Installed);

            return(is_root_type
                ? reason.Reason
                : reason.Reason + ReasonStringFor(reason.Parent));
        }
示例#17
0
        /// <summary>
        /// Record the given module version as being available.
        /// </summary>
        public void Add(CfanModule module)
        {
            if (!module.identifier.Equals(identifier))
            {
                throw new ArgumentException($"This AvailableModule is for tracking {identifier} not {module.identifier}");
            }

            log.DebugFormat("Adding {0}", module);
            module_version[module.modVersion] = module.cfanJson;
        }
示例#18
0
 private void UpdateModDependencyGraph(CfanModule module)
 {
     ModInfoTabControl.Tag = module ?? ModInfoTabControl.Tag;
     //Can be costly. For now only update when visible.
     if (ModInfoTabControl.SelectedIndex != RelationshipTabPage.TabIndex)
     {
         return;
     }
     Util.Invoke(DependsGraphTree, _UpdateModDependencyGraph);
 }
示例#19
0
        public void Incompatible(Type type, bool expected)
        {
            var comparator = (CKAN.IGameComparator)Activator.CreateInstance(type);

            gameMod = RandomModuleGenerator.GeneratorRandomModule(depends: new List <ModDependency> {
                new ModDependency("something")
            });

            // The mod without any version restriction is compatible with everything
            Assert.AreEqual(expected, comparator.Compatible(GameVersion, gameMod));
        }
示例#20
0
        public void GenerallySafeStrict(Type type, bool expected)
        {
            var comparator = (CKAN.IGameComparator)Activator.CreateInstance(type);

            gameMod = RandomModuleGenerator.GeneratorRandomModule(depends: new List <ModDependency> {
                new ModDependency("base==0.12.4")
            });

            // Now test!
            Assert.AreEqual(expected, comparator.Compatible(GameVersion, gameMod));
        }
示例#21
0
 /// <summary>
 /// Given a module and a path to a zipfile, returns all the files that would be installed
 /// from that zip for this module.
 ///
 /// This *will* throw an exception if the file does not exist.
 ///
 /// Throws a BadMetadataKraken if the stanza resulted in no files being returned.
 ///
 /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null.
 /// </summary>
 // TODO: Document which exception!
 public static List <IInstallable> FindInstallableFiles(CfanModule module, string zip_filename, KSP ksp)
 {
     if (module.kind == CfanJson.CfanModType.META)
     {
         return(new List <IInstallable>());
     }
     if (module.kind != CfanJson.CfanModType.MOD)
     {
         throw new NotImplementedException("Only regular mod is implemented.");
     }
     return(new List <IInstallable>(new IInstallable[] { new InstallableFile(zip_filename, module.standardFileName + ".zip") }));
 }
示例#22
0
        /// <summary>
        /// Returns the module contents if and only if we have it
        /// available in our cache. Returns null, otherwise.
        ///
        /// Intended for previews.
        /// </summary>
        // TODO: Return files relative to GameRoot
        public IEnumerable <string> GetModuleContentsList(CfanModule module)
        {
            string filename = ksp.Cache.GetCachedZip(module.download);

            if (filename == null)
            {
                return(null);
            }

            return(FindInstallableFiles(module, filename, ksp)
                   .Select(x => KSPPathUtils.NormalizePath(x.Destination)));
        }
示例#23
0
        /// <summary>
        /// Upgrades or installs the mods listed to the specified versions for the user's KSP.
        /// Will *re-install* or *downgrade* (with a warning) as well as upgrade.
        /// Throws ModuleNotFoundKraken if a module is not installed.
        /// </summary>
        public void Upgrade(IEnumerable <CfanModule> modules, IDownloader netAsyncDownloader)
        {
            // Start by making sure we've downloaded everything.
            DownloadModules(modules, netAsyncDownloader);

            // Our upgrade involves removing everything that's currently installed, then
            // adding everything that needs installing (which may involve new mods to
            // satisfy dependencies). We always know the list passed in is what we need to
            // install, but we need to calculate what needs to be removed.
            var to_remove = new List <string>();

            // Let's discover what we need to do with each module!
            foreach (CfanModule module in modules)
            {
                string          ident         = module.identifier;
                InstalledModule installed_mod = registry_manager.registry.InstalledModule(ident);

                if (installed_mod == null)
                {
                    //Maybe ModuleNotInstalled ?
                    if (registry_manager.registry.IsAutodetected(ident))
                    {
                        throw new ModuleNotFoundKraken(ident, module.modVersion.ToString(), String.Format("Can't upgrade {0} as it was not installed by CFAN. \n Please remove manually before trying to install it.", ident));
                    }

                    User.RaiseMessage("Installing previously uninstalled mod {0}", ident);
                }
                else
                {
                    // Module already installed. We'll need to remove it first.
                    to_remove.Add(module.identifier);

                    CfanModule installed = installed_mod.Module;
                    if (installed.modVersion.Equals(module.modVersion))
                    {
                        log.WarnFormat("{0} is already at the latest version, reinstalling", installed.identifier);
                    }
                    else if (installed.modVersion.IsGreaterThan(module.modVersion))
                    {
                        log.WarnFormat("Downgrading {0} from {1} to {2}", ident, installed.modVersion, module.modVersion);
                    }
                    else
                    {
                        log.InfoFormat("Upgrading {0} to {1}", ident, module.modVersion);
                    }
                }
            }

            AddRemove(
                modules,
                to_remove
                );
        }
示例#24
0
        public bool Compatible(FactorioVersion gameVersion, CfanModule module)
        {
            // If it's strictly compatible, then it's compatible.
            if (strict.Compatible(gameVersion, module))
            {
                return(true);
            }

            // if we will add something like "maximum game version" for a mod, then it might make sense to add something here (see summary of the class)

            return(false);
        }
示例#25
0
        /// <summary>
        ///     Register the supplied module as having been installed, thereby keeping
        ///     track of its metadata and files.
        /// </summary>
        public void RegisterModule(CfanModule mod, IEnumerable <string> absolute_files, KSP ksp)
        {
            SealionTransaction();

            // But we also want to keep track of all its files.
            // We start by checking to see if any files are owned by another mod,
            // if so, we abort with a list of errors.

            var inconsistencies = new List <string>();

            // We always work with relative files, so let's get some!
            IEnumerable <string> relative_files = absolute_files.Select(x => ksp.ToRelativeGameDataDir(x));

            // For now, it's always cool if a module wants to register a directory.
            // We have to flip back to absolute paths to actually test this.
            foreach (string file in relative_files.Where(file => !Directory.Exists(ksp.ToAbsoluteGameDataDir(file))))
            {
                string owner;
                if (installed_files.TryGetValue(file, out owner))
                {
                    // Woah! Registering an already owned file? Not cool!
                    // (Although if it existed, we should have thrown a kraken well before this.)
                    inconsistencies.Add(
                        string.Format("{0} wishes to install {1}, but this file is registered to {2}",
                                      mod.identifier, file, owner
                                      ));
                }
            }

            if (inconsistencies.Count > 0)
            {
                throw new InconsistentKraken(inconsistencies);
            }

            // If everything is fine, then we copy our files across. By not doing this
            // in the loop above, we make sure we don't have a half-registered module
            // when we throw our exceptinon.

            // This *will* result in us overwriting who owns a directory, and that's cool,
            // directories aren't really owned like files are. However because each mod maintains
            // its own list of files, we'll remove directories when the last mod using them
            // is uninstalled.
            foreach (string file in relative_files)
            {
                installed_files[file] = mod.identifier;
            }

            // Finally, register our module proper.
            var installed = new InstalledModule(ksp, mod, relative_files);

            installed_modules.Add(mod.identifier, installed);
        }
示例#26
0
        public void Setup()
        {
            // By setting these for every test, we can make sure our tests can change
            // them any way they like without harming other tests.

            dogezip = TestData.DogeCoinFlagZip();
            dogemod = TestData.DogeCoinFlag_101_module();

            mm_zip = TestData.ModuleManagerZip();
            mm_mod = TestData.ModuleManagerModule();

            ksp = new DisposableKSP();
        }
示例#27
0
        public SelectionReason ReasonFor(CfanModule mod)
        {
            if (mod == null)
            {
                throw new ArgumentNullException();
            }
            if (!ModList().Contains(mod))
            {
                throw new ArgumentException("Mod " + mod.identifier + " is not in the list");
            }

            return(reasons[mod]);
        }
示例#28
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(CfanModule module, string filename = null)
        {
            CheckMetapackageInstallationKraken(module);

            AbstractVersion 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);
            }
        }
示例#29
0
        internal static CfanModule LoadCkanFromFile(CKAN.KSP current_instance, string ckan_file)
        {
            CfanModule module = CfanFileManager.fromCfanFile(ckan_file);

            // We'll need to make some registry changes to do this.
            RegistryManager registry_manager = RegistryManager.Instance(current_instance);

            // Remove this version of the module in the registry, if it exists.
            registry_manager.registry.RemoveAvailable(module);

            // Sneakily add our version in...
            registry_manager.registry.AddAvailable(module);

            return(module);
        }
示例#30
0
        private void _UpdateModContentsTree(bool force = false)
        {
            GUIMod guiMod = GetSelectedModule();

            if (!guiMod.IsCKAN)
            {
                return;
            }
            CfanModule module = guiMod.ToCkanModule();

            if (Equals(module, current_mod_contents_module) && !force)
            {
                return;
            }
            else
            {
                current_mod_contents_module = module;
            }
            if (!guiMod.IsCached)
            {
                NotCachedLabel.Text            = "This mod is not in the cache, click 'Download' to preview contents";
                ContentsDownloadButton.Enabled = true;
                ContentsPreviewTree.Enabled    = false;
            }
            else
            {
                NotCachedLabel.Text            = "Module is cached, preview available";
                ContentsDownloadButton.Enabled = false;
                ContentsPreviewTree.Enabled    = true;
            }

            ContentsPreviewTree.Nodes.Clear();
            ContentsPreviewTree.Nodes.Add(module.title);

            IEnumerable <string> contents = ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user).GetModuleContentsList(module);

            if (contents == null)
            {
                return;
            }

            foreach (string item in contents)
            {
                ContentsPreviewTree.Nodes[0].Nodes.Add(item);
            }

            ContentsPreviewTree.Nodes[0].ExpandAll();
        }