public string Ships() { return(KSPPathUtils.NormalizePath( Path.Combine(GameDir(), "Ships") )); }
public string ShipsSph() { return(KSPPathUtils.NormalizePath( Path.Combine(Ships(), "SPH") )); }
public string InstallHistoryDir() { return(KSPPathUtils.NormalizePath( Path.Combine(CkanDir(), "history") )); }
public string Missions() { return(KSPPathUtils.NormalizePath( Path.Combine(GameDir(), "Missions") )); }
public string GameData() { return(KSPPathUtils.NormalizePath( Path.Combine(GameDir(), "GameData") )); }
public string DownloadCacheDir() { return(KSPPathUtils.NormalizePath( Path.Combine(CkanDir(), "downloads") )); }
/// <summary> /// Returns path relative to this KSP's GameDir. /// </summary> public string ToRelativeGameDir(string path) { return(KSPPathUtils.ToRelative(path, GameDir())); }
/// <summary> /// Given an open zipfile, returns all files that would be installed /// for this stanza. /// /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null. /// /// Throws a BadInstallLocationKraken if the install stanza targets an /// unknown install location (eg: not GameData, Ships, etc) /// /// Throws a BadMetadataKraken if the stanza resulted in no files being returned. /// </summary> /// <exception cref="BadInstallLocationKraken">Thrown when the installation path is not valid according to the spec.</exception> public List <InstallableFile> FindInstallableFiles(ZipFile zipfile, KSP ksp) { string installDir; bool makeDirs; var files = new List <InstallableFile>(); // Normalize the path before doing everything else string install_to = KSPPathUtils.NormalizePath(this.install_to); if (install_to == "GameData" || install_to.StartsWith("GameData/")) { // The installation path can be either "GameData" or a sub-directory of "GameData" // but it cannot contain updirs if (install_to.Contains("/../") || install_to.EndsWith("/..")) { throw new BadInstallLocationKraken("Invalid installation path: " + install_to); } string subDir = install_to.Substring("GameData".Length); // remove "GameData" subDir = subDir.StartsWith("/") ? subDir.Substring(1) : subDir; // remove a "/" at the beginning, if present // Add the extracted subdirectory to the path of KSP's GameData installDir = ksp == null ? null : (KSPPathUtils.NormalizePath(ksp.GameData() + "/" + subDir)); makeDirs = true; } else if (install_to.StartsWith("Ships")) { // Don't allow directory creation in ships directory makeDirs = false; switch (install_to) { case "Ships": installDir = ksp?.Ships(); break; case "Ships/VAB": installDir = ksp?.ShipsVab(); break; case "Ships/SPH": installDir = ksp?.ShipsSph(); break; case "Ships/@thumbs": installDir = ksp?.ShipsThumbs(); break; case "Ships/@thumbs/VAB": installDir = ksp?.ShipsThumbsVAB(); break; case "Ships/@thumbs/SPH": installDir = ksp?.ShipsThumbsSPH(); break; default: throw new BadInstallLocationKraken("Unknown install_to " + install_to); } } else { switch (install_to) { case "Tutorial": installDir = ksp?.Tutorial(); makeDirs = true; break; case "Scenarios": installDir = ksp?.Scenarios(); makeDirs = true; break; case "Missions": installDir = ksp?.Missions(); makeDirs = true; break; case "GameRoot": installDir = ksp?.GameDir(); makeDirs = false; break; default: throw new BadInstallLocationKraken("Unknown install_to " + install_to); } } EnsurePattern(); // `find` is supposed to match the "topmost" folder. Find it. var shortestMatch = find == null ? (int?)null : zipfile.Cast <ZipEntry>() .Select(entry => inst_pattern.Match(entry.Name.Replace('\\', '/'))) .Where(match => match.Success) .DefaultIfEmpty() .Min(match => match?.Index); // O(N^2) solution, as we're walking the zipfile for each stanza. // Surely there's a better way, although this is fast enough we may not care. foreach (ZipEntry entry in zipfile) { // Skips dirs and things not prescribed by our install stanza. if (!IsWanted(entry.Name, shortestMatch)) { continue; } // Prepare our file info. InstallableFile file_info = new InstallableFile { source = entry, makedir = makeDirs, destination = null }; // If we have a place to install it, fill that in... if (installDir != null) { // Get the full name of the file. // Update our file info with the install location file_info.destination = TransformOutputName( entry.Name, installDir, @as); } files.Add(file_info); } // If we have no files, then something is wrong! (KSP-CKAN/CKAN#93) if (files.Count == 0) { // We have null as the first argument here, because we don't know which module we're installing throw new BadMetadataKraken(null, String.Format("No files found matching {0} to install!", DescribeMatch())); } return(files); }
public string Scenarios() { return(KSPPathUtils.NormalizePath( Path.Combine(GameDir(), "saves", "scenarios") )); }
public string TempDir() { return(KSPPathUtils.NormalizePath( Path.Combine(CkanDir(), "temp") )); }
/// <summary> /// Given a stanza and an open zipfile, returns all files that would be installed /// for this stanza. /// /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null. /// /// Throws a BadInstallLocationKraken if the install stanza targets an /// unknown install location (eg: not GameData, Ships, etc) /// /// Throws a BadMetadataKraken if the stanza resulted in no files being returned. /// </summary> /// <exception cref="BadInstallLocationKraken">Thrown when the installation path is not valid according to the spec.</exception> internal static List <InstallableFile> FindInstallableFiles(ModuleInstallDescriptor stanza, ZipFile zipfile, KSP ksp) { string installDir; bool makeDirs; var files = new List <InstallableFile> (); // Normalize the path before doing everything else // TODO: This really should happen in the ModuleInstallDescriptor itself. stanza.install_to = KSPPathUtils.NormalizePath(stanza.install_to); // Convert our stanza to a standard `file` type. This is a no-op if it's // already the basic type. stanza = stanza.ConvertFindToFile(zipfile); if (stanza.install_to == "GameData" || stanza.install_to.StartsWith("GameData/")) { // The installation path can be either "GameData" or a sub-directory of "GameData" // but it cannot contain updirs if (stanza.install_to.Contains("/../") || stanza.install_to.EndsWith("/..")) { throw new BadInstallLocationKraken("Invalid installation path: " + stanza.install_to); } string subDir = stanza.install_to.Substring("GameData".Length); // remove "GameData" subDir = subDir.StartsWith("/") ? subDir.Substring(1) : subDir; // remove a "/" at the beginning, if present // Add the extracted subdirectory to the path of KSP's GameData installDir = ksp == null ? null : (KSPPathUtils.NormalizePath(ksp.GameData() + "/" + subDir)); makeDirs = true; } else if (stanza.install_to.StartsWith("Ships")) { // Don't allow directory creation in ships directory makeDirs = false; switch (stanza.install_to) { case "Ships": installDir = ksp == null ? null : ksp.Ships(); break; case "Ships/VAB": installDir = ksp == null ? null : ksp.ShipsVab(); break; case "Ships/SPH": installDir = ksp == null ? null : ksp.ShipsSph(); break; case "Ships/@thumbs": installDir = ksp == null ? null : ksp.ShipsThumbs(); break; case "Ships/@thumbs/VAB": installDir = ksp == null ? null : ksp.ShipsThumbsVAB(); break; case "Ships/@thumbs/SPH": installDir = ksp == null ? null : ksp.ShipsThumbsSPH(); break; default: throw new BadInstallLocationKraken("Unknown install_to " + stanza.install_to); } } else { switch (stanza.install_to) { case "Tutorial": installDir = ksp == null ? null : ksp.Tutorial(); makeDirs = true; break; case "Scenarios": installDir = ksp == null ? null : ksp.Scenarios(); makeDirs = true; break; case "GameRoot": installDir = ksp == null ? null : ksp.GameDir(); makeDirs = false; break; default: throw new BadInstallLocationKraken("Unknown install_to " + stanza.install_to); } } // O(N^2) solution, as we're walking the zipfile for each stanza. // Surely there's a better way, although this is fast enough we may not care. foreach (ZipEntry entry in zipfile) { // Skips things not prescribed by our install stanza. if (!stanza.IsWanted(entry.Name)) { continue; } // Prepare our file info. InstallableFile file_info = new InstallableFile { source = entry, makedir = makeDirs, destination = null }; // If we have a place to install it, fill that in... if (installDir != null) { // Get the full name of the file. string outputName = entry.Name; // Update our file info with the install location file_info.destination = TransformOutputName(stanza.file, outputName, installDir); } files.Add(file_info); } // If we have no files, then something is wrong! (KSP-CKAN/CKAN#93) if (files.Count == 0) { // We have null as the first argument here, because we don't know which module we're installing throw new BadMetadataKraken(null, String.Format("No files found in {0} to install!", stanza.file)); } return(files); }
private void DeSerialisationFixes(StreamingContext context) { // Our context is our KSP install. KSP ksp = (KSP)context.Context; // Older registries didn't have the installed_files list, so we create one // if absent. if (installed_files == null) { log.Warn("Older registry format detected, adding installed files manifest..."); ReindexInstalled(); } // If we have no registry version at all, then we're from the pre-release period. // We would check for a null here, but ints *can't* be null. if (registry_version == 0) { log.Warn("Older registry format detected, normalising paths..."); var normalised_installed_files = new Dictionary <string, string>(); foreach (KeyValuePair <string, string> tuple in installed_files) { string path = KSPPathUtils.NormalizePath(tuple.Key); if (Path.IsPathRooted(path)) { path = ksp.ToRelativeGameDir(path); normalised_installed_files[path] = tuple.Value; } else { // Already relative. normalised_installed_files[path] = tuple.Value; } } installed_files = normalised_installed_files; // Now update all our module file manifests. foreach (InstalledModule module in installed_modules.Values) { module.Renormalise(ksp); } // Our installed dlls have contained relative paths since forever, // and the next `ckan scan` will fix them anyway. (We can't scan here, // because that needs a registry, and we chicken-egg.) log.Warn("Registry upgrade complete"); } // Fix control lock, which previously was indexed with an invalid identifier. if (registry_version < 2) { InstalledModule control_lock_entry; const string old_ident = "001ControlLock"; const string new_ident = "ControlLock"; if (installed_modules.TryGetValue("001ControlLock", out control_lock_entry)) { if (ksp == null) { throw new Kraken("Internal bug: No KSP instance provided on registry deserialisation"); } log.WarnFormat("Older registry detected. Reindexing {0} as {1}. This may take a moment.", old_ident, new_ident); // Remove old record. installed_modules.Remove(old_ident); // Extract the old module metadata CkanModule control_lock_mod = control_lock_entry.Module; // Change to the correct ident. control_lock_mod.identifier = new_ident; // Prepare to re-index. var new_control_lock_installed = new InstalledModule( ksp, control_lock_mod, control_lock_entry.Files ); // Re-insert into registry. installed_modules[new_control_lock_installed.identifier] = new_control_lock_installed; // Re-index files. ReindexInstalled(); } } // If we spot a default repo with the old .zip URL, flip it to the new .tar.gz URL // Any other repo we leave *as-is*, even if it's the github meta-repo, as it's been // custom-added by our user. Repository default_repo; var oldDefaultRepo = new Uri("https://github.com/KSP-CKAN/CKAN-meta/archive/master.zip"); if (repositories != null && repositories.TryGetValue(Repository.default_ckan_repo_name, out default_repo) && default_repo.uri == oldDefaultRepo) { log.InfoFormat("Updating default metadata URL from {0} to {1}", oldDefaultRepo, Repository.default_ckan_repo_uri); repositories["default"].uri = Repository.default_ckan_repo_uri; } registry_version = LATEST_REGISTRY_VERSION; }
public string CkanDir() { return(KSPPathUtils.NormalizePath( Path.Combine(GameDir(), "CKAN") )); }
public string ShipsThumbsVAB() { return(KSPPathUtils.NormalizePath( Path.Combine(ShipsThumbs(), "VAB") )); }
/// <summary> /// Given a path relative to this KSP's GameDir, returns the /// absolute path on the system. /// </summary> public string ToAbsoluteGameDir(string path) { return(KSPPathUtils.ToAbsolute(path, GameDir())); }
public string Tutorial() { return(KSPPathUtils.NormalizePath( Path.Combine(GameDir(), "saves", "training") )); }
/// <summary> /// Compare two install stanzas /// </summary> /// <param name="other">The other stanza for comparison</param> /// <returns> /// True if they're equivalent, false if they're different. /// IEquatable<> uses this for more efficient comparisons. /// </returns> public bool Equals(ModuleInstallDescriptor otherStanza) { if (otherStanza == null) { // Not even the right type! return(false); } if (KSPPathUtils.NormalizePath(file) != KSPPathUtils.NormalizePath(otherStanza.file)) { return(false); } if (KSPPathUtils.NormalizePath(find) != KSPPathUtils.NormalizePath(otherStanza.find)) { return(false); } if (find_regexp != otherStanza.find_regexp) { return(false); } if (KSPPathUtils.NormalizePath(install_to) != KSPPathUtils.NormalizePath(otherStanza.install_to)) { return(false); } if (@as != otherStanza.@as) { return(false); } if ((filter == null) != (otherStanza.filter == null)) { return(false); } if (filter != null && !filter.SequenceEqual(otherStanza.filter)) { return(false); } if ((filter_regexp == null) != (otherStanza.filter_regexp == null)) { return(false); } if (filter_regexp != null && !filter_regexp.SequenceEqual(otherStanza.filter_regexp)) { return(false); } if (find_matches_files != otherStanza.find_matches_files) { return(false); } if ((include_only == null) != (otherStanza.include_only == null)) { return(false); } if (include_only != null && !include_only.SequenceEqual(otherStanza.include_only)) { return(false); } if ((include_only_regexp == null) != (otherStanza.include_only_regexp == null)) { return(false); } if (include_only_regexp != null && !include_only_regexp.SequenceEqual(otherStanza.include_only_regexp)) { return(false); } return(true); }