Example #1
0
        public void ToRelative()
        {
            string absolute = Path.Combine(ksp_dir, "GameData/HydrazinePrincess");

            Assert.AreEqual(
                "GameData/HydrazinePrincess",
                ksp.ToRelativeGameDir(absolute)
                );
        }
Example #2
0
        /// <summary>
        /// Ensures all files for this module have relative paths.
        /// Called when upgrading registry versions. Should be a no-op
        /// if called on newer registries.
        /// </summary>
        public void Renormalise(GameInstance ksp)
        {
            var normalised_installed_files = new Dictionary <string, InstalledModuleFile>();

            foreach (KeyValuePair <string, InstalledModuleFile> tuple in installed_files)
            {
                string path = CKANPathUtils.NormalizePath(tuple.Key);

                if (Path.IsPathRooted(path))
                {
                    path = ksp.ToRelativeGameDir(path);
                }

                normalised_installed_files[path] = tuple.Value;
            }

            installed_files = normalised_installed_files;
        }
Example #3
0
        /// <summary>
        /// Set up the display for interaction.
        /// This is separate from Wait so we can set up
        /// before the calling code switches to the tab.
        /// </summary>
        /// <param name="possibleConfigOnlyDirs">Directories that the user may want to delete</param>
        public void LoadDirs(GameInstance ksp, HashSet <string> possibleConfigOnlyDirs)
        {
            instance = ksp;
            var items = possibleConfigOnlyDirs
                        .OrderBy(d => d)
                        .Select(d => new ListViewItem(instance.ToRelativeGameDir(d).Replace('/', Path.DirectorySeparatorChar))
            {
                Tag     = d,
                Checked = true
            })
                        .ToArray();

            Util.Invoke(this, () =>
            {
                DirectoriesListView.Items.Clear();
                DirectoriesListView.Items.AddRange(items);
                DirectoriesListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
                DirectoriesListView_ItemSelectionChanged(null, null);
            });
        }
Example #4
0
        /// <summary>
        /// Ensures all files for this module have relative paths.
        /// Called when upgrading registry versions. Should be a no-op
        /// if called on newer registries.
        /// </summary>
        public void Renormalise(GameInstance ksp)
        {
            // We need case insensitive path matching on Windows
            var normalised_installed_files = Platform.IsWindows
                ? new Dictionary <string, InstalledModuleFile>(StringComparer.OrdinalIgnoreCase)
                : new Dictionary <string, InstalledModuleFile>();

            foreach (KeyValuePair <string, InstalledModuleFile> tuple in installed_files)
            {
                string path = CKANPathUtils.NormalizePath(tuple.Key);

                if (Path.IsPathRooted(path))
                {
                    path = ksp.ToRelativeGameDir(path);
                }

                normalised_installed_files[path] = tuple.Value;
            }

            installed_files = normalised_installed_files;
        }
Example #5
0
        /// <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, GameInstance ksp)
        {
            string installDir;
            var    files = new List <InstallableFile>();

            // Normalize the path before doing everything else
            string install_to = CKANPathUtils.NormalizePath(this.install_to);

            // The installation path cannot contain updirs
            if (install_to.Contains("/../") || install_to.EndsWith("/.."))
            {
                throw new BadInstallLocationKraken("Invalid installation path: " + install_to);
            }

            if (ksp == null)
            {
                installDir = null;
            }
            else if (install_to == ksp.game.PrimaryModDirectoryRelative ||
                     install_to.StartsWith($"{ksp.game.PrimaryModDirectoryRelative}/"))
            {
                // The installation path can be either "GameData" or a sub-directory of "GameData"
                string subDir = install_to.Substring(ksp.game.PrimaryModDirectoryRelative.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 = CKANPathUtils.NormalizePath(ksp.game.PrimaryModDirectory(ksp) + "/" + subDir);
            }
            else
            {
                switch (install_to)
                {
                case "GameRoot":
                    installDir = ksp.GameDir();
                    break;

                default:
                    if (ksp.game.AllowInstallationIn(install_to, out string path))
                    {
                        installDir = ksp.ToAbsoluteGameDir(path);
                    }
                    else
                    {
                        throw new BadInstallLocationKraken("Unknown install_to " + install_to);
                    }
                    break;
                }
            }

            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     = false,
                    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(
                        ksp.game, entry.Name, installDir, @as);
                    file_info.makedir = AllowDirectoryCreation(
                        ksp.game,
                        ksp?.ToRelativeGameDir(file_info.destination)
                        ?? file_info.destination);
                }

                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);
        }