예제 #1
0
        private static List <string> GetFMSupportedLanguagesFromInstDir(string fmInstPath, bool earlyOutOnEnglish)
        {
            // Get initial list of base FM dirs the normal way: we don't want to count these as lang dirs even if
            // they're named such (matching FMSel behavior)
            var searchList = FastIO.GetDirsTopOnly(fmInstPath, "*", ignoreReparsePoints: true);

            if (searchList.Count == 0)
            {
                return(new List <string>());
            }

            #region Move key dirs to end of list (priority)

            // Searching folders is horrendously slow, so prioritize folders most likely to contain lang dirs so
            // if we find English, we end up earlying-out much faster

            for (int i = 0; i < 3; i++)
            {
                string keyDir = i switch { 0 => "/books", 1 => "/intrface", _ => "/strings" };

                for (int j = 0; j < searchList.Count; j++)
                {
                    if (j < searchList.Count - 1 &&
                        searchList[j].PathEndsWithI(keyDir))
                    {
                        string item = searchList[j];
                        searchList.RemoveAt(j);
                        searchList.Add(item);
                        break;
                    }
                }
            }

            #endregion

            var langsFoundList = new HashSetI(Supported.Length);

            while (searchList.Count > 0)
            {
                string bdPath = searchList[searchList.Count - 1];
                searchList.RemoveAt(searchList.Count - 1);
                bool englishFound = FastIO.SearchDirForLanguages(SupportedHash, bdPath, searchList, langsFoundList, earlyOutOnEnglish);
                // Matching FMSel behavior: early-out on English
                if (earlyOutOnEnglish && englishFound)
                {
                    return new List <string> {
                               "English"
                    }
                }
                ;
            }

            return(SortLangsToSpec(langsFoundList));
        }
예제 #2
0
        private static void ClearCacheDir(FanMission fm)
        {
            string fmCachePath = Path.Combine(Paths.FMsCache, fm.InstalledDir);

            if (!fmCachePath.TrimEnd(CA_BS_FS).PathEqualsI(Paths.FMsCache.TrimEnd(CA_BS_FS)) && Directory.Exists(fmCachePath))
            {
                try
                {
                    foreach (string f in FastIO.GetFilesTopOnly(fmCachePath, "*"))
                    {
                        File.Delete(f);
                    }
                    foreach (string d in FastIO.GetDirsTopOnly(fmCachePath, "*"))
                    {
                        Directory.Delete(d, recursive: true);
                    }
                }
                catch (Exception ex)
                {
                    Log("Exception clearing files in FM cache for " + fm.Archive + " / " + fm.InstalledDir, ex);
                }
            }
        }
예제 #3
0
        internal static void CreateOrClearTempPath(string path)
        {
            #region Safety check

            // Make sure we never delete any paths that are not safely tucked in our temp folder
            string baseTemp = _baseTemp.TrimEnd(CA_BS_FS_Space);

            // @DIRSEP: getting rid of this concat is more trouble than it's worth
            // This method is called rarely and only once in a row
            bool pathIsInTempDir = path.PathStartsWithI(baseTemp + "\\");

            Misc.AssertR(pathIsInTempDir, "Path '" + path + "' is not in temp dir '" + baseTemp + "'");

            if (!pathIsInTempDir)
            {
                return;
            }

            #endregion

            if (Directory.Exists(path))
            {
                try
                {
                    foreach (string f in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
                    {
                        new FileInfo(f).IsReadOnly = false;
                    }

                    foreach (string d in Directory.GetDirectories(path, "*", SearchOption.AllDirectories))
                    {
                        Misc.Dir_UnSetReadOnly(d);
                    }
                }
                catch (Exception ex)
                {
                    Log("Exception setting temp path subtree to all non-readonly.\r\n" +
                        "path was: " + path, ex);
                }

                try
                {
                    foreach (string f in FastIO.GetFilesTopOnly(path, "*"))
                    {
                        File.Delete(f);
                    }
                    foreach (string d in FastIO.GetDirsTopOnly(path, "*"))
                    {
                        Directory.Delete(d, recursive: true);
                    }
                }
                catch (Exception ex)
                {
                    Log("Exception clearing temp path " + path, ex);
                }
            }
            else
            {
                try
                {
                    Directory.CreateDirectory(path);
                }
                catch (Exception ex)
                {
                    Log("Exception creating temp path " + path, ex);
                }
            }
        }
예제 #4
0
        internal static async Task BackupFM(FanMission fm, string fmInstalledPath, string fmArchivePath)
        {
            bool backupSavesAndScreensOnly = fmArchivePath.IsEmpty() ||
                                             (Config.BackupFMData == BackupFMData.SavesAndScreensOnly &&
                                              (fm.Game != Game.Thief3 || !Config.T3UseCentralSaves));

            if (!GameIsKnownAndSupported(fm.Game))
            {
                Log("Game type is unknown or unsupported (" + fm.Archive + ", " + fm.InstalledDir + ", " + fm.Game + ")", stackTrace: true);
                return;
            }

            await Task.Run(() =>
            {
                if (backupSavesAndScreensOnly && fm.InstalledDir.IsEmpty())
                {
                    return;
                }

                string thisFMInstallsBasePath = Config.GetFMInstallPathUnsafe(fm.Game);
                string savesDir     = fm.Game == Game.Thief3 ? _t3SavesDir : _darkSavesDir;
                string savesPath    = Path.Combine(thisFMInstallsBasePath, fm.InstalledDir, savesDir);
                string netSavesPath = Path.Combine(thisFMInstallsBasePath, fm.InstalledDir, _darkNetSavesDir);
                // Screenshots directory name is the same for T1/T2/T3/SS2
                string screensPath    = Path.Combine(thisFMInstallsBasePath, fm.InstalledDir, _screensDir);
                string ss2CurrentPath = Path.Combine(thisFMInstallsBasePath, fm.InstalledDir, _ss2CurrentDir);

                string bakFile = Path.Combine(Config.FMsBackupPath,
                                              (!fm.Archive.IsEmpty() ? fm.Archive.RemoveExtension() : fm.InstalledDir) +
                                              Paths.FMBackupSuffix);

                if (backupSavesAndScreensOnly)
                {
                    var savesAndScreensFiles = new List <string>();

                    if (Directory.Exists(savesPath))
                    {
                        savesAndScreensFiles.AddRange(Directory.GetFiles(savesPath, "*", SearchOption.AllDirectories));
                    }
                    if (Directory.Exists(netSavesPath))
                    {
                        savesAndScreensFiles.AddRange(Directory.GetFiles(netSavesPath, "*", SearchOption.AllDirectories));
                    }
                    if (Directory.Exists(screensPath))
                    {
                        savesAndScreensFiles.AddRange(Directory.GetFiles(screensPath, "*", SearchOption.AllDirectories));
                    }
                    if (fm.Game == Game.SS2)
                    {
                        savesAndScreensFiles.AddRange(Directory.GetFiles(ss2CurrentPath, "*", SearchOption.AllDirectories));

                        var ss2SaveDirs = FastIO.GetDirsTopOnly(
                            Path.Combine(thisFMInstallsBasePath, fm.InstalledDir), "save_*");

                        foreach (string dir in ss2SaveDirs)
                        {
                            if (_ss2SaveDirsOnDiskRegex.IsMatch(dir))
                            {
                                savesAndScreensFiles.AddRange(Directory.GetFiles(dir, "*", SearchOption.AllDirectories));
                            }
                        }
                    }

                    if (savesAndScreensFiles.Count == 0)
                    {
                        return;
                    }

                    using var archive = new ZipArchive(new FileStream(bakFile, FileMode.Create, FileAccess.Write),
                                                       ZipArchiveMode.Create, leaveOpen: false);

                    foreach (string f in savesAndScreensFiles)
                    {
                        string fn = f.Substring(fmInstalledPath.Length).Trim(CA_BS_FS);
                        AddEntry(archive, f, fn);
                    }

                    return;
                }

                string[] installedFMFiles = Directory.GetFiles(fmInstalledPath, "*", SearchOption.AllDirectories);

                var(changedList, addedList, fullList) =
                    GetFMDiff(installedFMFiles, fmInstalledPath, fmArchivePath, fm.Game);

                // If >90% of files are different, re-run and use only size difference
                // They could have been extracted with NDL which uses SevenZipSharp and that one puts different
                // timestamps, when it puts the right ones at all
                if (changedList.Count > 0 && ((double)changedList.Count / fullList.Count) > 0.9)
                {
                    (changedList, addedList, fullList) =
                        GetFMDiff(installedFMFiles, fmInstalledPath, fmArchivePath, fm.Game, useOnlySize: true);
                }

                try
                {
                    using var archive = new ZipArchive(new FileStream(bakFile, FileMode.Create, FileAccess.Write),
                                                       ZipArchiveMode.Create, leaveOpen: false);

                    foreach (string f in installedFMFiles)
                    {
                        string fn = f.Substring(fmInstalledPath.Length).Trim(CA_BS_FS);
                        if (IsSaveOrScreenshot(fn, fm.Game) ||
                            (!fn.PathEqualsI(Paths.FMSelInf) && !fn.PathEqualsI(_startMisSav) &&
                             (changedList.PathContainsI(fn) || addedList.PathContainsI(fn))))
                        {
                            AddEntry(archive, f, fn);
                        }
                    }

                    string fmSelInfString = "";
                    for (int i = 0; i < fullList.Count; i++)
                    {
                        string f = fullList[i];
                        if (!installedFMFiles.PathContainsI(Path.Combine(fmInstalledPath, f)))
                        {
                            // @DIRSEP: Test if FMSel is dirsep-agnostic here. If so, remove the ToSystemDirSeps()
                            fmSelInfString += _removeFileEq + f.ToSystemDirSeps() + "\r\n";
                        }
                    }

                    if (!fmSelInfString.IsEmpty())
                    {
                        var entry    = archive.CreateEntry(Paths.FMSelInf, CompressionLevel.Fastest);
                        using var eo = entry.Open();
                        using var sw = new StreamWriter(eo, Encoding.UTF8);
                        sw.Write(fmSelInfString);
                    }
                }
                catch (Exception ex)
                {
                    Log("Exception in zip archive create and/or write (" + fm.Archive + ", " + fm.InstalledDir + ", " + fm.Game + ")", ex);
                }
            });
        }