Beispiel #1
0
        /// <summary>
        /// Takes a collection of directories and adds all parent directories within the GameData structure.
        /// </summary>
        /// <param name="directories">The collection of directory path strings to examine</param>
        public HashSet <string> AddParentDirectories(HashSet <string> directories)
        {
            if (directories == null || directories.Count == 0)
            {
                return(new HashSet <string>());
            }

            var gameDir = KSPPathUtils.NormalizePath(ksp.GameDir());

            return(directories
                   .Where(dir => !string.IsNullOrWhiteSpace(dir))
                   // normalize all paths before deduplicate
                   .Select(KSPPathUtils.NormalizePath)
                   // remove any duplicate paths
                   .Distinct()
                   .SelectMany(dir =>
            {
                var results = new HashSet <string>();
                // adding in the DirectorySeparatorChar fixes attempts on Windows
                // to parse "X:" which resolves to Environment.CurrentDirectory
                var dirInfo = new DirectoryInfo(dir + Path.DirectorySeparatorChar);

                // if this is a parentless directory (Windows)
                // or if the Root equals the current directory (Mono)
                if (dirInfo.Parent == null || dirInfo.Root == dirInfo)
                {
                    return results;
                }

                if (!dir.StartsWith(gameDir, StringComparison.CurrentCultureIgnoreCase))
                {
                    dir = KSPPathUtils.ToAbsolute(dir, gameDir);
                }

                // remove the system paths, leaving the path under the instance directory
                var relativeHead = KSPPathUtils.ToRelative(dir, gameDir);
                var pathArray = relativeHead.Split('/');
                var builtPath = string.Empty;
                foreach (var path in pathArray)
                {
                    builtPath += path + '/';
                    results.Add(KSPPathUtils.ToAbsolute(builtPath, gameDir));
                }

                return results;
            })
                   .Where(dir => !IsReservedDirectory(dir))
                   .ToHashSet());
        }
Beispiel #2
0
 /// <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()));
 }
Beispiel #3
0
        /// <summary>
        /// Uninstall the module provided. For internal use only.
        /// Use UninstallList for user queries, it also does dependency handling.
        /// This does *NOT* save the registry.
        /// </summary>

        private void Uninstall(string modName)
        {
            using (var transaction = CkanTransaction.CreateTransactionScope())
            {
                InstalledModule mod = registry_manager.registry.InstalledModule(modName);

                if (mod == null)
                {
                    log.ErrorFormat("Trying to uninstall {0} but it's not installed", modName);
                    throw new ModNotInstalledKraken(modName);
                }

                // Walk our registry to find all files for this mod.
                IEnumerable <string> files = mod.Files;

                var directoriesToDelete = new HashSet <string>();

                foreach (string file in files)
                {
                    string path = ksp.ToAbsoluteGameDir(file);

                    try
                    {
                        FileAttributes attr = File.GetAttributes(path);

                        if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
                        {
                            directoriesToDelete.Add(path);
                        }
                        else
                        {
                            log.InfoFormat("Removing {0}", file);
                            file_transaction.Delete(path);
                        }
                    }
                    catch (Exception ex)
                    {
                        // XXX: This is terrible, we're catching all exceptions.
                        log.ErrorFormat("Failure in locating file {0} : {1}", path, ex.Message);
                    }
                }

                // Remove from registry.

                registry_manager.registry.DeregisterModule(ksp, modName);

                // Sort our directories from longest to shortest, to make sure we remove child directories
                // before parents. GH #78.
                foreach (string directory in directoriesToDelete.OrderBy(dir => dir.Length).Reverse())
                {
                    if (!Directory.EnumerateFileSystemEntries(directory).Any())
                    {
                        // Skip Ships/VAB ans Ships/SPH
                        if (directory == KSPPathUtils.ToAbsolute("VAB", ksp.Ships()) ||
                            directory == KSPPathUtils.ToAbsolute("SPH", ksp.Ships()))
                        {
                            continue;
                        }

                        // We *don't* use our file_transaction to delete files here, because
                        // it fails if the system's temp directory is on a different device
                        // to KSP. However we *can* safely delete it now we know it's empty,
                        // because the TxFileMgr *will* put it back if there's a file inside that
                        // needs it.
                        //
                        // This works around GH #251.
                        // The filesystem boundry bug is described in https://transactionalfilemgr.codeplex.com/workitem/20

                        log.InfoFormat("Removing {0}", directory);
                        Directory.Delete(directory);
                    }
                    else
                    {
                        log.InfoFormat("Not removing directory {0}, it's not empty", directory);
                    }
                }
                transaction.Complete();
            }
        }