public void ScanDlls() { string pathDir = Path.Combine(ksp.Mods(), "Example-0.1.0"); Directory.CreateDirectory(pathDir); string infoJsonDir = Path.Combine(pathDir, "info.json"); Assert.IsFalse(ksp.Registry.IsInstalled("Example"), "Example should start uninstalled"); File.WriteAllText(infoJsonDir, @"{""name"":""Example"",""version"":""0.1.0"",""title"":""SomeTitle"",""author"":""someAuthor"",""contact"":""*****@*****.**"",""homepage"":""http://example.com"",""description"":""someDescription"",""dependencies"":[]}"); ksp.ScanGameData(); Assert.IsTrue(ksp.Registry.IsInstalled("Example"), "Example installed"); AbstractVersion version = ksp.Registry.InstalledVersion("Example"); Assert.IsInstanceOf <AutodetectedVersion>(version, "DLL detected as a DLL, not full mod"); // Now let's do the same with different case. pathDir = Path.Combine(ksp.Mods(), "NewMod-0.1.0"); Directory.CreateDirectory(pathDir); infoJsonDir = Path.Combine(pathDir, "info.json"); File.WriteAllText(infoJsonDir, @"{""name"":""NewMod"",""version"":""0.1.0"",""title"":""SomeTitle"",""author"":""someAuthor"",""contact"":""*****@*****.**"",""homepage"":""http://example.com"",""description"":""someDescription"",""dependencies"":[]}"); Assert.IsFalse(ksp.Registry.IsInstalled("NewMod")); ksp.ScanGameData(); Assert.IsTrue(ksp.Registry.IsInstalled("NewMod")); }
/// <summary> /// <see cref = "IRegistryQuerier.Installed" /> /// </summary> public Dictionary <string, AbstractVersion> Installed(bool withProvides = true) { var installed = new Dictionary <string, AbstractVersion>(); // Index our Preexisting Modules, because we like them as much as any other mod // unlike CKAN staff who hates their dlls! foreach (var preexisting in installed_preexisting_modules) { AbstractVersion modVersion = preexisting.Value.modInfo.version; if (modVersion != null) { installed[preexisting.Key] = modVersion; } } // Index our provides list, so users can see virtual packages if (withProvides) { foreach (var provided in Provided()) { installed[provided.Key] = provided.Value; } } // Index our installed modules (which may overwrite the installed DLLs and provides) foreach (var modinfo in installed_modules) { installed[modinfo.Key] = modinfo.Value.Module.modVersion; } return(installed); }
public bool isSatisfiedBy(string name, AbstractVersion modVersion) { if (name != modName) { return(isOptional); } var calculatedMaxVersion = calculateMaxVersion(); bool ret = (minVersion == null || modVersion >= minVersion) && (calculatedMaxVersion == null || modVersion <= calculatedMaxVersion); return(isConflict ? !ret : ret); }
//=========================================================================== Construction /// <summary> /// Initializes a new instance of the <see cref="VersionNumber"/> class. /// </summary> /// <param name="major">The major verion number.</param> /// <param name="minor">The minor version number.</param> /// <param name="status">The version status.</param> public VersionNumber(int major, int minor, VersionStatus status) { if (major < 0 || minor < 0) { throw new ArgumentException("Major or minor must be greater than or equal zero"); } _abstractVersion = AbstractVersion.Defined; _major = major; _minor = minor; _status = status; }
/// <summary> /// Returns the specified CkanModule with the version specified, /// or null if it does not exist. /// <see cref = "IRegistryQuerier.GetModuleByVersion" /> /// </summary> public CfanModule GetModuleByVersion(string ident, AbstractVersion 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(new ModVersion(version.ToString()))); }
/// <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); } }
public CfanModuleIdAndVersion(string stringWithIdentifierEqualsVersion) { Match match = Regex.Match(stringWithIdentifierEqualsVersion, @"^(?<mod>[a-zA-Z0-9_-][a-zA-Z0-9_ -\.]+[a-zA-Z0-9_-]*)(?<version>=\d+\.\d+\.?\d*)?$"); if (!match.Success) { throw new ModuleAndVersionStringInvalidKraken(stringWithIdentifierEqualsVersion); } identifier = match.Groups["mod"].Value; if (match.Groups["version"].Success) { version = new ModVersion(match.Groups["version"].Value.TrimStart('=')); } }
/// <summary> /// Returns the path to a cached copy of a module if it exists, or downloads /// and returns the downloaded copy otherwise. /// /// If no filename is provided, the module's standard name will be used. /// Chcecks provided cache first. /// </summary> public static string CachedOrDownload(string identifier, AbstractVersion version, Uri url, NetFileCache cache, string filename = null) { if (filename == null) { filename = CfanModule.createStandardFileName(identifier, version.ToString()); } string full_path = cache.GetCachedZip(url); if (full_path == null) { return(Download(url, filename, cache)); } log.DebugFormat("Using {0} (cached)", filename); return(full_path); }
public int RunCommand(CKAN.KSP ksp, object raw_options) { UpgradeOptions options = (UpgradeOptions)raw_options; if (options.ckan_file != null) { options.modules.Add(LoadCkanFromFile(ksp, options.ckan_file).identifier); } if (options.modules.Count == 0 && !options.upgrade_all) { // What? No files specified? User.RaiseMessage("Usage: cfan upgrade Mod [Mod2, ...]"); User.RaiseMessage(" or cfan upgrade --all"); User.RaiseMessage(" or cfan upgrade ckan"); return(Exit.BADOPT); } if (!options.upgrade_all && options.modules[0] == "cfan") { User.RaiseMessage("Querying the latest CFAN version"); AutoUpdate.Instance.FetchLatestReleaseInfo(); var latestVersion = AutoUpdate.Instance.LatestVersion; var currentVersion = new ModVersion(Meta.Version()); if (latestVersion.IsGreaterThan(currentVersion)) { User.RaiseMessage("New CFAN version available - " + latestVersion); var releaseNotes = AutoUpdate.Instance.ReleaseNotes; User.RaiseMessage(releaseNotes); User.RaiseMessage("\n"); if (User.RaiseYesNoDialog("Proceed with install?")) { User.RaiseMessage("Upgrading CFAN, please wait.."); AutoUpdate.Instance.StartUpdateProcess(false); } } else { User.RaiseMessage("You already have the latest version."); } return(Exit.OK); } User.RaiseMessage("\nUpgrading modules...\n"); try { if (options.upgrade_all) { var installed = new Dictionary <string, AbstractVersion>(ksp.Registry.Installed(true)); var to_upgrade = new List <CfanModule>(); foreach (KeyValuePair <string, AbstractVersion> mod in installed) { AbstractVersion current_version = mod.Value; if ((current_version is ProvidedVersion) || (current_version is AutodetectedVersion)) { continue; } try { // Check if upgrades are available CfanModule latest = ksp.Registry.LatestAvailable(mod.Key, ksp.Version()); // This may be an unindexed mod. If so, // skip rather than crash. See KSP-CKAN/CKAN#841. if (latest == null) { continue; } if (latest.modVersion.IsGreaterThan(mod.Value)) { // Upgradable log.InfoFormat("New version {0} found for {1}", latest.modVersion, latest.identifier); to_upgrade.Add(latest); } } catch (ModuleNotFoundKraken) { log.InfoFormat("{0} is installed, but no longer in the registry", mod.Key); } } ModuleInstaller.GetInstance(ksp, User).Upgrade(to_upgrade, new NetAsyncModulesDownloader(User, ksp.tryGetFactorioAuthData())); } else { // TODO: These instances all need to go. ModuleInstaller.GetInstance(ksp, User).Upgrade(options.modules, new NetAsyncModulesDownloader(User, ksp.tryGetFactorioAuthData())); } } catch (ModuleNotFoundKraken kraken) { User.RaiseMessage("Module {0} not found", kraken.module); return(Exit.ERROR); } User.RaiseMessage("\nDone!\n"); return(Exit.OK); }
/// <summary> /// Returns the path to a cached copy of a module if it exists, or downloads /// and returns the downloaded copy otherwise. /// /// If no filename is provided, the module's standard name will be used. /// Chcecks the CKAN cache first. /// </summary> public string CachedOrDownload(string identifier, AbstractVersion version, Uri url, string filename = null) { return(CachedOrDownload(identifier, version, url, Cache, filename)); }
/// <summary> /// Updates the supplied registry from the URL given. /// This does not *save* the registry. For that, you probably want Repo.Update /// </summary> internal static void UpdateRegistry(Uri repo, Registry registry, KSP ksp, IUser user, Boolean clear = true) { log.InfoFormat("Downloading {0}", repo); string repo_file = String.Empty; try { repo_file = Net.Download(repo); } catch (System.Net.WebException e) { user.RaiseError($"Couldn't download {repo}.", e); return; } // Clear our list of known modules. var old_available = registry.available_modules; if (clear) { registry.ClearAvailable(); } // Check the filetype. FileType type = FileIdentifier.IdentifyFile(repo_file); switch (type) { case FileType.TarGz: UpdateRegistryFromTarGz(repo_file, registry); break; case FileType.Zip: UpdateRegistryFromZip(repo_file, registry); break; default: break; } List <CfanModule> metadataChanges = new List <CfanModule>(); foreach (var identifierModulePair in old_available) { var identifier = identifierModulePair.Key; if (registry.IsInstalled(identifier)) { AbstractVersion abstractVersion = registry.InstalledVersion(identifier); var installedVersion = new ModVersion(abstractVersion.ToString()); if (!(registry.available_modules.ContainsKey(identifier))) { log.InfoFormat("UpdateRegistry, module {0}, version {1} not in repository ({2})", identifier, installedVersion, repo); continue; } if (!registry.available_modules[identifier].module_version.ContainsKey(installedVersion)) { continue; } // if the mod is installed and the metadata is different we have to reinstall it CfanModule metadata = new CfanModule(registry.available_modules[identifier].module_version[installedVersion]); if (!old_available.ContainsKey(identifier) || !old_available[identifier].module_version.ContainsKey(installedVersion)) { continue; } CfanModule oldMetadata = new CfanModule(old_available[identifier].module_version[installedVersion]); bool same = metadata.kind == oldMetadata.kind; if (!same) { metadataChanges.Add(new CfanModule(registry.available_modules[identifier].module_version[installedVersion])); } } } if (metadataChanges.Any()) { string mods = ""; for (int i = 0; i < metadataChanges.Count; i++) { mods += metadataChanges[i].identifier + " " + metadataChanges[i].modVersion.ToString() + ((i < metadataChanges.Count - 1) ? ", " : ""); } if (user.RaiseYesNoDialog(String.Format( @"The following mods have had their metadata changed since last update - {0}. It is advisable that you reinstall them in order to preserve consistency with the repository. Do you wish to reinstall now?", mods))) { ModuleInstaller installer = ModuleInstaller.GetInstance(ksp, new NullUser()); installer.Upgrade(metadataChanges, new NetAsyncModulesDownloader(new NullUser(), ksp.tryGetFactorioAuthData())); } } // Remove our downloaded meta-data now we've processed it. // Seems weird to do this as part of a transaction, but Net.Download uses them, so let's be consistent. file_transaction.Delete(repo_file); }
//=========================================================================== Construction /// <summary> /// Initializes a new instance of the <see cref="VersionNumber"/> class. /// </summary> /// <param name="major">The major verion number.</param> /// <param name="minor">The minor version number.</param> /// <param name="status">The version status.</param> public VersionNumber(int major, int minor, VersionStatus status) { if (major < 0 || minor < 0) throw new ArgumentException("Major or minor must be greater than or equal zero"); _abstractVersion = AbstractVersion.Defined; _major = major; _minor = minor; _status = status; }
private VersionNumber(AbstractVersion abstractVersion) { _abstractVersion = abstractVersion; _major = -1; _minor = -1 - (int)abstractVersion; }
public int RunCommand(CKAN.KSP ksp, object raw_options) { ListOptions options = (ListOptions)raw_options; IRegistryQuerier registry = RegistryManager.Instance(ksp).registry; ExportFileType?exportFileType = null; if (!string.IsNullOrWhiteSpace(options.export)) { exportFileType = GetExportFileType(options.export); if (exportFileType == null) { user.RaiseError("Unknown export format: {0}", options.export); } } if (!(options.porcelain) && exportFileType == null) { user.RaiseMessage("\nFactorio found at {0}\n", ksp.GameDir()); user.RaiseMessage("Factorio Version: {0}\n", ksp.Version()); user.RaiseMessage("Installed Modules:\n"); } if (exportFileType == null) { var installed = new SortedDictionary <string, AbstractVersion>(registry.Installed()); foreach (KeyValuePair <string, AbstractVersion> mod in installed) { AbstractVersion current_version = mod.Value; string bullet = "*"; if (current_version is ProvidedVersion) { // Skip virtuals for now. continue; } else if (current_version is AutodetectedVersion) { // Autodetected dll bullet = "-"; } else { try { // Check if upgrades are available, and show appropriately. CfanModule latest = registry.LatestAvailable(mod.Key, ksp.Version()); log.InfoFormat("Latest {0} is {1}", mod.Key, latest); if (latest == null) { // Not compatible! bullet = "X"; } else if (latest.modVersion.Equals(current_version)) { // Up to date bullet = "-"; } else if (latest.modVersion.IsGreaterThan(mod.Value)) { // Upgradable bullet = "^"; } } catch (ModuleNotFoundKraken) { log.InfoFormat("{0} is installed, but no longer in the registry", mod.Key); bullet = "?"; } } user.RaiseMessage("{0} {1} {2}", bullet, mod.Key, mod.Value); } } else { var stream = Console.OpenStandardOutput(); new Exporter(exportFileType.Value).Export(registry, stream); stream.Flush(); } if (!(options.porcelain) && exportFileType == null) { user.RaiseMessage("\nLegend: -: Up to date. X: Incompatible. ^: Upgradable. ?: Unknown "); } return(Exit.OK); }
private VersionNumber(AbstractVersion abstractVersion) { _abstractVersion = abstractVersion; _major = -1; _minor = -1 - (int)abstractVersion; }
public CfanModuleIdAndVersion(string identifier, AbstractVersion version) { this.identifier = identifier; this.version = version; }
public GUIMod(CfanModule mod, IRegistryQuerier registry, FactorioVersion current_ksp_version) { IsCKAN = mod is CfanModule; //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, false); IsInstallChecked = IsInstalled; HasUpdate = registry.HasUpdate(mod.identifier, current_ksp_version); IsIncompatible = !mod.IsCompatibleKSP(current_ksp_version); IsAutodetected = registry.IsAutodetected(mod.identifier); Authors = mod.authors == null ? "N/A" : String.Join(",", mod.authors); var installed_version = registry.InstalledVersion(mod.identifier); AbstractVersion latest_version = null; var ksp_version = mod.getMinFactorioVersion(); CfanModule latest_available = null; try { latest_available = registry.LatestAvailable(mod.identifier, current_ksp_version); if (latest_available != null) { latest_version = latest_available.modVersion; } } catch (ModuleNotFoundKraken) { latest_version = installed_version; } InstalledVersion = installed_version != null?installed_version.ToString() : "-"; // Let's try to find the compatibility for this mod. If it's not in the registry at // all (because it's a DarkKAN mod) then this might fail. CfanModule latest_available_for_any_ksp = null; try { latest_available_for_any_ksp = registry.LatestAvailable(mod.identifier, null); } catch { // If we can't find the mod in the CKAN, but we've a CkanModule installed, then // use that. if (IsCKAN) { latest_available_for_any_ksp = (CfanModule)mod; } } var showInfoFrom = latest_available ?? latest_available_for_any_ksp; // If there's known information for this mod in any form, calculate the highest compatible // KSP. if (showInfoFrom != null) { string minVersion = showInfoFrom.getMinFactorioVersion()?.ToString(); string maxVersion = showInfoFrom.HighestCompatibleKSP()?.ToString(); if (maxVersion != null && ModVersion.isMaxWithTheSameMinor(new ModVersion(maxVersion))) { maxVersion = maxVersion.Replace(int.MaxValue.ToString(), "x"); } if (minVersion != null && maxVersion != null) { KSPCompatibility = minVersion.ToString() + " - " + maxVersion.ToString(); } else if (minVersion != null) { KSPCompatibility = " >= " + minVersion.ToString(); } else if (maxVersion != null) { KSPCompatibility = " <= " + maxVersion.ToString(); } else { KSPCompatibility = "any"; } KSPCompatibilityLong = KSPCompatibility; // If the mod we have installed is *not* the mod we have installed, or we don't know // what we have installed, indicate that an upgrade would be needed. if (installed_version == null || !showInfoFrom.modVersion.Equals(installed_version)) { KSPCompatibilityLong = string.Format("{0} (using mod version {1})", KSPCompatibility, showInfoFrom.modVersion); } } else { // No idea what this mod is, sorry! KSPCompatibility = KSPCompatibilityLong = "unknown"; } if (latest_version != null) { LatestVersion = latest_version.ToString(); } else if (latest_available_for_any_ksp != null) { LatestVersion = latest_available_for_any_ksp.modVersion.ToString(); } else { LatestVersion = "-"; } KSPversion = ksp_version != null?ksp_version.ToString() : "-"; Abstract = mod.@abstract; // 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. Homepage = "N/A"; if (!string.IsNullOrEmpty(mod.homepage)) { Homepage = mod.homepage; } Identifier = mod.identifier; if (mod.download_size == 0) { DownloadSize = "N/A"; } else if (mod.download_size / 1024.0 < 1) { DownloadSize = "1<KB"; } else { DownloadSize = mod.download_size / 1024 + ""; } Abbrevation = new string(mod.title.Split(' '). Where(s => s.Length > 0).Select(s => s[0]).ToArray()); if (Main.Instance != null) { IsCached = Main.Instance.CurrentInstance.Cache.IsMaybeCachedZip(mod.download); } }