diff --git a/GeneralMods/AdvancedSaveBackup/SaveBackup.cs b/GeneralMods/AdvancedSaveBackup/SaveBackup.cs
index bb24d44c..9b998b09 100644
--- a/GeneralMods/AdvancedSaveBackup/SaveBackup.cs
+++ b/GeneralMods/AdvancedSaveBackup/SaveBackup.cs
@@ -2,6 +2,7 @@ using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
+using System.Reflection;
using Omegasis.SaveBackup.Framework;
using StardewModdingAPI;
using StardewModdingAPI.Events;
@@ -57,21 +58,108 @@ namespace Omegasis.SaveBackup
this.BackupSaves(SaveBackup.NightlyBackupsPath);
}
+ /// Recursively copy a directory or file.
+ /// The file or folder to copy.
+ /// The folder to copy into.
+ /// Whether to copy the root folder itself, or false to only copy its contents.
+ /// A filter which matches the files or directories to copy, or null to copy everything.
+ /// Derived from the SMAPI installer code.
+ /// Returns whether any files were copied.
+ private bool RecursiveCopy(FileSystemInfo source, DirectoryInfo targetFolder, bool copyRoot = true)
+ {
+ if (!source.Exists)
+ return false;
+
+ bool anyCopied = false;
+
+ switch (source)
+ {
+ case FileInfo sourceFile:
+ targetFolder.Create();
+ sourceFile.CopyTo(Path.Combine(targetFolder.FullName, sourceFile.Name));
+ anyCopied = true;
+ break;
+
+ case DirectoryInfo sourceDir:
+ DirectoryInfo targetSubfolder = copyRoot ? new DirectoryInfo(Path.Combine(targetFolder.FullName, sourceDir.Name)) : targetFolder;
+ foreach (var entry in sourceDir.EnumerateFileSystemInfos())
+ anyCopied = this.RecursiveCopy(entry, targetSubfolder) || anyCopied;
+ break;
+
+ default:
+ throw new NotSupportedException($"Unknown filesystem info type '{source.GetType().FullName}'.");
+ }
+
+ return anyCopied;
+ }
+
+ /// Create a zip using the .NET compression library.
+ /// The file or directory path to zip.
+ /// The destination file to create.
+ /// The compression libraries aren't available on this system.
+ private void CompressUsingNetFramework(string sourcePath, FileInfo destination)
+ {
+ // get compress method
+ MethodInfo createFromDirectory;
+ try
+ {
+ // create compressed backup
+ Assembly coreAssembly = Assembly.Load("System.IO.Compression, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") ?? throw new InvalidOperationException("Can't load System.IO.Compression assembly.");
+ Assembly fsAssembly = Assembly.Load("System.IO.Compression.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") ?? throw new InvalidOperationException("Can't load System.IO.Compression assembly.");
+ Type compressionLevelType = coreAssembly.GetType("System.IO.Compression.CompressionLevel") ?? throw new InvalidOperationException("Can't load CompressionLevel type.");
+ Type zipFileType = fsAssembly.GetType("System.IO.Compression.ZipFile") ?? throw new InvalidOperationException("Can't load ZipFile type.");
+ createFromDirectory = zipFileType.GetMethod("CreateFromDirectory", new[] { typeof(string), typeof(string), compressionLevelType, typeof(bool) }) ?? throw new InvalidOperationException("Can't load ZipFile.CreateFromDirectory method.");
+ }
+ catch (Exception ex)
+ {
+ throw new NotSupportedException("Couldn't load the .NET compression libraries on this system.", ex);
+ }
+
+ // compress file
+ createFromDirectory.Invoke(null, new object[] { sourcePath, destination.FullName, CompressionLevel.Fastest, false });
+ }
+
+ private void OriginCompressLogic(string folderPath)
+ {
+ ZipFile.CreateFromDirectory(SaveBackup.SavesPath, Path.Combine(folderPath, $"backup-{DateTime.Now:yyyyMMdd'-'HHmmss}.zip"));
+ }
+
/// Back up saves to the specified folder.
/// The folder path in which to generate saves.
private void BackupSaves(string folderPath)
{
// back up saves
Directory.CreateDirectory(folderPath);
- ZipFile.CreateFromDirectory(SaveBackup.SavesPath, Path.Combine(folderPath, $"backup-{DateTime.Now:yyyyMMdd'-'HHmmss}.zip"));
+ if(Constants.TargetPlatform == GamePlatform.Android)
+ {
+ FileInfo targetFile = new FileInfo(Path.Combine(folderPath, $"backup-{DateTime.Now:yyyyMMdd'-'HHmmss}.zip"));
+ try
+ {
+ this.CompressUsingNetFramework(folderPath, targetFile);
+ }
+ catch (NotSupportedException)
+ {
+ this.RecursiveCopy(new DirectoryInfo(SaveBackup.SavesPath), new DirectoryInfo(Path.Combine(folderPath, $"backup-{DateTime.Now:yyyyMMdd'-'HHmmss}")), false);
+ }
+ }
+ else
+ {
+ this.OriginCompressLogic(folderPath);
+ }
// delete old backups
new DirectoryInfo(folderPath)
- .EnumerateFiles()
+ .GetFileSystemInfos()
.OrderByDescending(f => f.CreationTime)
.Skip(this.Config.SaveCount)
.ToList()
- .ForEach(file => file.Delete());
+ .ForEach(file =>
+ {
+ if (file is DirectoryInfo folder)
+ folder.Delete(recursive: true);
+ else
+ file.Delete();
+ });
}
}
}